3.6 KiB
App Module
Single Activity architecture. MainActivity is the sole entry point.
Navigation
LibreChatNavHost is the root composable. It uses adaptive layout based on WindowSizeClass:
- Phone:
ModalNavigationDraweras primary navigation (sidebar-first pattern matching the web frontend). No bottom navigation bar. Drawer opens via hamburger button in chat header or swipe gesture. - Tablet (600dp+ width): Persistent side panel with full conversation list. No
NavigationRailor bottom bar.
Sidebar / Drawer Content
DrawerContent is the rich sidebar matching the web's left panel:
- "New Chat" button at top
- Search bar with debounce filtering
- Conversation items grouped by date (Today, Yesterday, Previous 7 Days, etc.)
- Each item shows: endpoint icon, title, model name, relative time
- Active conversation highlighted with left border indicator and tinted background
- Footer: links to Agents, Files, Settings
- Sign out button at bottom
Top-Level Destinations
Defined in TopLevelDestination enum: Chat, Conversations, Agents, Files, Settings.
Conversations are integrated into the drawer body. Agents, Files, and Settings are accessible via drawer footer links. All routes remain registered in the NavHost.
Active Conversation Tracking
NavHostViewModel.activeConversationId tracks the currently viewed conversation. Updated automatically from the navigation back stack when the chat route changes. Used by DrawerContent to highlight the active conversation.
Auth & Session
NavHostViewModelobserves auth state viaisLoggedInflow- Start destination is
CHAT_GRAPH_ROUTEif logged in,AUTH_GRAPH_ROUTEotherwise sessionExpiredflow triggers nav to auth graph with full backstack clear- Drawer gestures are hidden during auth flow
Deep Linking
- Scheme:
librechat://conversation/{conversationId} - Handled in
MainActivity.handleDeepLink()and forwarded toLibreChatNavHost onNewIntenthandles deep links when app is already running
Connectivity
ConnectivityObserverinjected intoMainActivity- Offline banner animates in/out at top of screen when connection is lost
Dependencies
This module depends on all :core:* and all :feature:* modules.
It applies convention plugins: librechat.android.application, librechat.android.compose, librechat.android.koin.
Server-Synced Favorites
NavHostViewModelexposesfavorites: StateFlow<Set<String>>andtoggleFavorite()- Currently backed by
SettingsDataStore(local) — server sync viaUserApi.getFavorites()/updateFavorites()available but needs wiring DrawerContentshows star icon per conversation (filled = bookmarked)- Favorites state passed through
LibreChatNavHostandTabletLayout
Server Banners
NavHostViewModelfetches banners fromBannerRepositoryon init, filters expired viadisplayFrom/displayTowithInstant.parse()- Dismissed banner IDs tracked in-memory via
dismissedBannerIds: StateFlow<Set<String>>(session-scoped, not persisted) BannerDisplaycomposable shown at top of content in bothLibreChatNavHost(phone) andTabletLayout- Banner types: "info" (blue), "warning" (amber), "error" (red) — defaults to "info" if type is null
- Gotcha:
displayFrom/displayToare ISO 8601 strings parsed withInstant.parse()— wrap inrunCatchingsince the format from the server is not guaranteed
Preset Navigation
PRESET_MANAGER_ROUTEregistered inSettingsNavigation.ktPresetManagerScreenaccessible from Settings → Chat section- Navigation wired in both
LibreChatNavHostandTabletLayout