Today, you’ll enhance the chat app by displaying message status indicators such as sent, delivered, and read. This feature improves user engagement and provides clarity on the status of each message.
What You Will Do Today:
- Add fields to Firestore to track message status.
- Update Firestore rules and structure for status management.
- Implement real-time status updates for sent, delivered, and read indicators.
- Display message statuses in the chat UI.
Step 1: Add Status Tracking to Firestore
- Each message document in the
messages
collection will now include:- status: String (
sent
,delivered
,read
).
- status: String (
- Update your Firebase Firestore structure:
- Go to Firestore Database > Data.
- Add a test message document with the
status
field.
Step 2: Update Firestore Rules for Status Management
Modify Firestore security rules to allow updates for the status
field:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /messages/{messageId} {
allow read: if request.auth != null;
allow update: if request.auth != null && request.resource.data.status in ['delivered', 'read'];
allow create: if request.auth != null;
}
}
}
Step 3: Set Message Status When Sent
- Update the
sendMessage
function inChatScreen.js
to initialize the messagestatus
assent
:
const sendMessage = async () => {
if (text.trim()) {
const { uid, email } = auth().currentUser;
try {
await firestore().collection('messages').add({
text,
userId: uid,
userName: email,
chatId,
status: 'sent', // Initial status
createdAt: firestore.FieldValue.serverTimestamp(),
});
setText('');
} catch (error) {
console.error('Error sending message:', error);
}
}
};
Step 4: Update Message Status to Delivered
- Use Firebase Functions to automatically update the
status
field to delivered when a message is added:
// functions/index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.updateMessageStatusToDelivered = functions.firestore
.document('messages/{messageId}')
.onCreate(async (snapshot, context) => {
const messageId = context.params.messageId;
try {
await admin.firestore().collection('messages').doc(messageId).update({
status: 'delivered',
});
console.log('Message marked as delivered:', messageId);
} catch (error) {
console.error('Error updating message status to delivered:', error);
}
});
- Deploy the updated function:
firebase deploy --only functions
Step 5: Update Message Status to Read
- In
ChatScreen.js
, update thefetchMessages
function to mark messages as read when loaded:
useEffect(() => {
const unsubscribe = firestore()
.collection('messages')
.where('chatId', '==', chatId)
.orderBy('createdAt', 'desc')
.onSnapshot(async (querySnapshot) => {
const fetchedMessages = querySnapshot.docs.map((doc) => ({
id: doc.id,
...doc.data(),
}));
setMessages(fetchedMessages);
// Update status to 'read' for all fetched messages
const batch = firestore().batch();
querySnapshot.docs.forEach((doc) => {
if (doc.data().status === 'delivered') {
batch.update(doc.ref, { status: 'read' });
}
});
await batch.commit();
});
return unsubscribe;
}, []);
Step 6: Display Message Status in the Chat UI
- Modify the
renderMessage
function to display the message status:
const renderMessage = ({ item }) => (
<View style={styles.messageContainer}>
<Text style={styles.messageUser}>{item.userName}</Text>
<Text style={styles.messageText}>{item.text}</Text>
<View style={styles.statusContainer}>
<Text style={styles.messageTimestamp}>
{item.createdAt?.toDate().toLocaleTimeString()}
</Text>
<Text style={styles.messageStatus}>
{item.status === 'sent'
? '✓ Sent'
: item.status === 'delivered'
? '✓✓ Delivered'
: '✓✓ Read'}
</Text>
</View>
</View>
);
const styles = StyleSheet.create({
statusContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
messageStatus: {
fontSize: 12,
color: '#888',
marginLeft: 8,
},
});
Step 7: Test Message Status Updates
- Run the app:
- For Android:
npx react-native run-android
- For iOS:
npx react-native run-ios
- For Android:
- Send a message:
- Confirm that the message status appears as
✓ Sent
.
- Confirm that the message status appears as
- Verify delivered and read statuses:
- Open the chat on another device or simulator.
- Confirm that the status updates to
✓✓ Delivered
and then✓✓ Read
.
- Check Firestore:
- Go to the Firebase Console under Firestore Database > messages.
- Confirm that the
status
field updates correctly for each message.
Summary
Today, you implemented message status indicators for sent, delivered, and read messages. This feature provides real-time feedback to users about their message statuses, enhancing the chat experience.
Tomorrow, you’ll work on handling attachments like images and videos.