Day 9: Adding Typing Indicators and Presence (Online/Offline) Status


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:

  1. Use Firestore to track user presence.
  2. Display online/offline status for users.
  3. Add a typing indicator when users are typing.

Step 1: Track User Presence in Firestore

  1. 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).
  2. 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

  1. 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;
  1. Use the UserPresence component in ChatScreen.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 in ChatScreen.js.
<TypingIndicator userId={otherUserId} />

Step 4: Test Typing Indicators and Presence

  1. Run the app:
    • For Android: npx react-native run-android
    • For iOS: npx react-native run-ios.
  2. Verify online/offline status:
    • Open the app on multiple devices.
    • Confirm that user status updates in real-time.
  3. Test typing indicators:
    • Start typing in one device.
    • Verify that the “User is typing…” indicator appears on the other device.
See also  How to Whitelist Your Domain for Facebook Messenger Chat Widget

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.


Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.