Features

User Search & Invite Flow

The template includes a user search feature that allows users to find and invite others to chat rooms. This section explains how search works and how the invite flow is implemented.

Search Functionality

How It Works

User search is implemented via searchUserByEmailSmart from user-search.service.ts:

  • Searches the users collection in Firestore
  • Uses Firestore query with where("email", ">=", query) and where("email", ">=", query + "\uf8ff") for prefix matching
  • Limits results to a reasonable number (e.g., 10) to avoid excessive reads
  • Returns user info including displayName, avatarURL, and email

Note: This is a simple prefix search. For more advanced search (full-text, fuzzy matching), you would need to integrate a search service like Algolia or Elasticsearch.

Debounced Search

The search is debounced to avoid excessive Firestore queries while the user is typing:

  • Uses SEARCH_DEBOUNCE_MS constant (default: 300ms) from chat.constants.ts
  • Search query is executed only after the user stops typing for the debounce duration
  • Each keystroke resets the timer, so search only runs when the user pauses
  • Empty queries return no results immediately (no API call)

Using the Search Hook

useUserSearch Hook

Components use useUserSearch hook to manage search state:

const {
  query,
  loading,
  matchedUsers,
  handleSearchChange,
  clearQuery
} = useUserSearch(currentUid, selectedUsers);

// matchedUsers automatically excludes:
// - Current user
// - Already selected users
  • query – Current search query string
  • loading – Whether search is in progress
  • matchedUsers – Filtered search results (excludes current user and already selected users)
  • handleSearchChange – Callback to update search query (debounced internally)
  • clearQuery – Clears search query and results

Search User Dialog

SearchUserDialog Component

The template includes a SearchUserDialog component that provides the full search and invite UI:

  • Opens when user clicks "Create Group" or starts a new private chat
  • Contains a search input that uses useUserSearch hook
  • Displays search results as a list of user cards with avatar, name, and email
  • Allows selecting multiple users (for group chats) or a single user (for private chats)
  • Shows selected users in a preview section with ability to remove them
  • Has "Create" button that triggers room creation with selected users

User Selector Component

The UserSelector component handles the search input and results display:

  • Renders a search input with loading indicator
  • Shows "No results" message when search returns empty
  • Displays user cards that can be clicked to select/deselect
  • Highlights selected users visually

Invite Flow

Creating Private Chat

When creating a private chat:

  1. User searches for and selects a single user
  2. Clicks "Create" button
  3. System calls ensureCreatePrivateChat(currentUid, recipientUid)
  4. If a private room already exists between these users, it opens that room
  5. If no room exists, creates a new private room and opens it

Creating Group Chat

When creating a group chat:

  1. User searches for and selects multiple users (minimum 1)
  2. Optionally enters a group name
  3. Clicks "Create" button
  4. System calls createGroupChat(creatorUid, participantUids, groupName, groupAvatarURL)
  5. Creates a new group room with all selected participants
  6. Creates a system message: "created the group"
  7. Opens the newly created group room

State Management

The search dialog state is managed via dialog.store.ts:

  • isOpen – Whether the dialog is visible
  • selectedUsers – Array of selected user objects
  • roomType – "private" or "group" (determines if single or multiple selection)

The store provides actions to open/close the dialog, add/remove selected users, and reset state.

Implementation Details

Key files for user search:

  • features/chat/services/user-search.service.ts – searchUserByEmailSmart function
  • features/chat/hooks/use-user-search.ts – React hook for managing search state
  • features/chat/components/dialog/search-user-dialog.tsx – Main dialog component
  • features/chat/components/dialog/user-selector.tsx – Search input and results display
  • features/chat/components/dialog/selected-user-preview.tsx – Preview of selected users
  • features/chat/stores/dialog.store.ts – Zustand store for dialog state