Features

Typing Indicators

Typing indicators show when other users are currently typing in a room. This feature uses Firebase Realtime Database for fast, real-time updates with automatic cleanup.

How It Works

Data Structure

Typing status is stored in Realtime Database:

typing/{roomId}/{uid}: true | null

When a user is typing, their node is set to true. When they stop typing, the node is removed (set to null).

Sending Typing Status

When a user types in the chat input, handleTyping(roomId, uid) is called from typing.service.ts:

  • Sets the typing node to true (only once per typing session to minimize writes)
  • Sets up onDisconnect to automatically remove the node if connection drops
  • Starts a timeout (default 3 seconds) that will clear typing status if no further typing occurs
  • Each keystroke resets the timeout, so typing status stays active while the user is actively typing

This debouncing approach reduces database writes while still providing responsive typing indicators.

Clearing Typing Status

Typing status is cleared in two scenarios:

  • Timeout: After TYPING_TIMEOUT_MS (default 3000ms) of no typing activity, clearTyping(roomId, uid) is called automatically
  • Message sent: When the user sends a message, typing status is cleared immediately
  • Connection drop: If the user's connection drops, onDisconnect automatically removes the typing node

Receiving Typing Status

Subscribing to Typing

To see who is typing in a room, use subscribeToTyping from typing.service.ts:

subscribeToTyping(roomId, (typingIds) => {
  // typingIds is an array of UIDs currently typing
  // e.g. ["uid1", "uid2"]
});

The callback receives an array of user IDs who are currently typing. The subscription automatically updates whenever someone starts or stops typing.

Using the Hook

Components use useTypingIndicator hook to get typing status:

const typingIds = useTypingIndicator(roomId);

// typingIds is an array of UIDs currently typing
// Excludes the current user automatically
// Returns empty array if roomId is null

The hook automatically filters out the current user (you don't want to see your own typing indicator) and handles subscription cleanup when the component unmounts or roomId changes.

UI Display

TypingIndicator Component

The template includes a TypingIndicator component that displays typing status:

  • Shows animated dots when users are typing
  • Displays user names (e.g., "John, Jane are typing...")
  • Automatically hides when no one is typing
  • Positioned at the bottom of the message list, above the input field

The component uses useTypingIndicator to get typing IDs and useUserInfo to fetch user names for display.

Performance Optimizations

The typing indicator system is optimized for performance:

  • Debounced writes: Typing status is only written once per typing session, not on every keystroke
  • Automatic cleanup: Timeout and onDisconnect ensure typing nodes don't persist unnecessarily
  • Realtime Database: Fast updates with lower latency than Firestore for this ephemeral data
  • Selective subscriptions: Only active rooms have typing subscriptions, reducing unnecessary listeners

Implementation Details

Key files for typing indicators:

  • features/chat/services/typing.service.ts – handleTyping, clearTyping, subscribeToTyping
  • features/chat/hooks/use-typing-indicator.ts – React hook for subscribing to typing status
  • features/chat/components/ui/typing-indicator.tsx – UI component that displays typing status
  • features/chat/components/room-pane/chat-input.tsx – Input component that calls handleTyping on user input
  • features/chat/constants/chat.constants.ts – TYPING_TIMEOUT_MS constant (default: 3000ms)