import { Outlet } from 'react-router-dom'; import { useBootstrap } from '@/lib/api/hooks'; import { useChatList } from '@/lib/tinode/hooks'; import { BottomTabBar } from './BottomTabBar'; import { NavRail } from './NavRail'; /** * Top-level chrome: persistent icon rail (>=640px) or bottom tab bar (<640px), wrapping whichever * feature section is active. Each feature section owns its own list/main/detail responsive split * internally (see e.g. features/messages) -- this shell only decides "rail vs tabs", nothing about * columns within a section. */ export function AppShell() { const contacts = useChatList(); const bootstrap = useBootstrap(); // "sys"/"slf" have their own authoritative unread source in entry_badges (bootstrap.ts) -- excluded // here in case they ever also show up as regular Tinode subscriptions in `contacts`, which would // otherwise double-count the same unread messages into this badge. const unreadMessages = contacts.reduce((sum, c) => (c.topic === 'sys' || c.topic === 'slf' ? sum : sum + (c.unread || 0)), 0) + (bootstrap.data?.entry_badges?.system_unread_count || 0) + (bootstrap.data?.entry_badges?.file_assistant_unread_count || 0); return (