Flutter Firebase Chat App – Part 6: Typing Indicator Implementation
Learn how to implement a typing indicator in a Flutter chat app using Firebase Firestore. Show real-time “User is typing…” updates efficiently.
Introduction
Typing indicators are a small but powerful feature that improves the real-time communication experience.
When a user starts typing, the other participant sees:
User is typing...
This creates a more natural conversation flow.
In this article we will implement:
- Typing state in Firestore
- Updating typing status
- Real-time UI updates
- Performance optimization
Typing Indicator Architecture
User starts typing
↓
Update Firestore typing status
↓
Other user listens to typing field
↓
UI shows "Typing..."
Firestore Conversation Structure
We store typing status in the conversation document.
conversations ├── conversationId │ ├── participants │ ├── lastMessage │ ├── typing
Example Typing Field
{
"typing": {
"user1": true,
"user2": false
}
}
Step 1: Update Typing Status
When the user starts typing:
await FirebaseFirestore.instance
.collection('conversations')
.doc(conversationId)
.update({
"typing.currentUserId": true
});
Step 2: Stop Typing
When the message is sent or typing stops:
await FirebaseFirestore.instance
.collection('conversations')
.doc(conversationId)
.update({
"typing.currentUserId": false
});
Step 3: Listen to Typing State
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('conversations')
.doc(conversationId)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return SizedBox();
}
final data = snapshot.data!.data();
bool isTyping =
data['typing'][otherUserId] ?? false;
if (isTyping) {
return Text("User is typing...");
}
return SizedBox();
},
);
Detect Text Input Changes
TextField(
onChanged: (value) {
if (value.isNotEmpty) {
setTyping(true);
} else {
setTyping(false);
}
},
)
Typing Timeout Optimization
If the user stops typing but does not send the message, the typing state should automatically reset.
Timer(
Duration(seconds: 3),
() {
setTyping(false);
}
);
UI Example
Column(
children: [
MessageList(),
if (isTyping)
Text(
"Typing...",
style: TextStyle(
fontStyle: FontStyle.italic
),
),
MessageInput()
],
)
Performance Optimization
- Avoid updating typing status too frequently
- Use debounce or delay
- Reset typing state automatically
Debounce Example
Timer? typingTimer;
void onTyping() {
typingTimer?.cancel();
setTyping(true);
typingTimer = Timer(
Duration(seconds: 2),
() => setTyping(false)
);
}
Security Rule Reminder
match /conversations/{conversationId} {
allow update: if request.auth != null
&& request.auth.uid in resource.data.participants;
}
Common Mistakes
- Updating typing state on every keystroke
- Not resetting typing status
- Writing typing status to message collection
Production Flow Summary
User types message
↓
Typing status updated
↓
Other user receives realtime update
↓
UI displays typing indicator
↓
User sends message
↓
Typing status reset
Conclusion
Typing indicators significantly improve the real-time feel of a messaging app.
By updating a lightweight typing field in Firestore, we can create smooth real-time interaction between users.
In Part 7, we will implement: Online / Offline User Status System.
Share
What's Your Reaction?
Like
0
Dislike
0
Love
0
Funny
0
Angry
0
Sad
0
Wow
0