Today, you’ll implement typing indicators to show when a user is typing and online/offline presence status to indicate user availability. These features enhance the real-time communication experience in the chat app.
What You Will Do Today:
- Use Firestore to track user presence.
- Display online/offline status for users.
- Add a typing indicator when users are typing.
Step 1: Track User Presence in Firestore
- Update Firestore Structure:
- Create a new collection called
users
in Firestore. - Each document in the collection should have the following structure:
- userId: String (the user’s unique ID).
- isOnline: Boolean (whether the user is online).
- lastSeen: Timestamp (the last time the user was online).
- Create a new collection called
- Update User Presence in the App: Modify
App.js
to update the user’s presence status in Firestore.
import React, { useEffect } from 'react';
import auth from '@react-native-firebase/auth';
import firestore from '@react-native-firebase/firestore';
export default function App() {
useEffect(() => {
const user = auth().currentUser;
if (user) {
const userRef = firestore().collection('users').doc(user.uid);
// Set user as online
userRef.set({ isOnline: true }, { merge: true });
// Set user as offline when the app is closed
const handleOffline = async () => {
await userRef.update({ isOnline: false, lastSeen: firestore.FieldValue.serverTimestamp() });
};
window.addEventListener('beforeunload', handleOffline);
return () => {
window.removeEventListener('beforeunload', handleOffline);
handleOffline();
};
}
}, []);
return <YourNavigationStack />;
}
Step 2: Display User Online/Offline Status
- Add Presence UI to ChatScreen:
import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import firestore from '@react-native-firebase/firestore';
import auth from '@react-native-firebase/auth';
function UserPresence({ userId }) {
const [isOnline, setIsOnline] = useState(false);
const [lastSeen, setLastSeen] = useState(null);
useEffect(() => {
const userRef = firestore().collection('users').doc(userId);
const unsubscribe = userRef.onSnapshot((doc) => {
if (doc.exists) {
setIsOnline(doc.data().isOnline);
setLastSeen(doc.data().lastSeen?.toDate());
}
});
return unsubscribe;
}, [userId]);
return (
<View style={styles.presenceContainer}>
<Text style={styles.presenceText}>
{isOnline ? 'Online' : `Last seen: ${lastSeen ? lastSeen.toLocaleString() : 'N/A'}`}
</Text>
</View>
);
}
const styles = StyleSheet.create({
presenceContainer: {
marginBottom: 10,
},
presenceText: {
fontSize: 14,
color: '#888',
},
});
export default UserPresence;
- Use the
UserPresence
component inChatScreen.js
.
import UserPresence from '../components/UserPresence';
function ChatScreen() {
const userId = auth().currentUser.uid;
return (
<View style={styles.container}>
<UserPresence userId={userId} />
{/* Chat UI */}
</View>
);
}
Step 3: Add Typing Indicator
- Track Typing Status: Update Firestore with the user’s typing status.
const handleTyping = async (isTyping) => {
const userId = auth().currentUser.uid;
await firestore().collection('users').doc(userId).update({ isTyping });
};
Use this function in the text input:
<TextInput
style={styles.input}
placeholder="Type a message..."
value={text}
onChangeText={(value) => {
setText(value);
handleTyping(value.length > 0);
}}
/>
- Display Typing Indicator: Add a
TypingIndicator
component.
import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import firestore from '@react-native-firebase/firestore';
function TypingIndicator({ userId }) {
const [isTyping, setIsTyping] = useState(false);
useEffect(() => {
const userRef = firestore().collection('users').doc(userId);
const unsubscribe = userRef.onSnapshot((doc) => {
if (doc.exists) {
setIsTyping(doc.data().isTyping);
}
});
return unsubscribe;
}, [userId]);
if (!isTyping) return null;
return (
<View style={styles.typingIndicator}>
<Text style={styles.typingText}>User is typing...</Text>
</View>
);
}
const styles = StyleSheet.create({
typingIndicator: {
padding: 10,
backgroundColor: '#f0f0f0',
borderRadius: 8,
alignSelf: 'flex-start',
marginVertical: 5,
},
typingText: {
fontSize: 14,
fontStyle: 'italic',
color: '#888',
},
});
export default TypingIndicator;
- Use the
TypingIndicator
component inChatScreen.js
.
<TypingIndicator userId={otherUserId} />
Step 4: Test Typing Indicators and Presence
- Run the app:
- For Android:
npx react-native run-android
- For iOS:
npx react-native run-ios
.
- For Android:
- Verify online/offline status:
- Open the app on multiple devices.
- Confirm that user status updates in real-time.
- Test typing indicators:
- Start typing in one device.
- Verify that the “User is typing…” indicator appears on the other device.
Summary
Today, you added typing indicators and online/offline presence to the chat app. These features improve the real-time communication experience for users.
Tomorrow, you’ll wrap up by deploying and scaling the chat app.