/* eslint-disable react-refresh/only-export-components */ import { useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { LogOut, MoreHorizontal, Search, Settings, SquareArrowOutUpRight, X, } from "lucide-react"; import type { TabType } from "@/types/ui-types"; import type { RailView } from "@/sidebar/AppRail"; import { groupRailItems, useRailItems, type RailItemDef, } from "@/sidebar/rail-items"; import { useHiddenRailTabs } from "@/sidebar/hidden-rail-tabs"; import { RailBadge } from "@/sidebar/RailBadge"; import { cn } from "@/lib/utils"; import { isElectron } from "@/lib/electron"; const PRIMARY_COUNT = 4; /** The four bar slots: flagged items first, then the rest in rail order. */ export function pickPrimaryItems(items: RailItemDef[]): RailItemDef[] { const usable = items.filter((item) => item.kind !== "tab"); return [ ...usable.filter((item) => item.mobilePrimary), ...usable.filter((item) => !item.mobilePrimary), ].slice(0, PRIMARY_COUNT); } /** * The rail on a phone: the most used destinations on the bar, everything else * in a sheet behind More with search, settings and logout. */ export function MobileBar({ railView, sidebarOpen, username, onRailClick, onOpenTab, onOpenSettings, onOpenPalette, onLogout, }: { railView: RailView; sidebarOpen: boolean; username: string; onRailClick: (view: RailView) => void; onOpenTab: (type: TabType) => void; onOpenSettings: () => void; onOpenPalette: () => void; onLogout: () => void; }) { const { t } = useTranslation(); const [moreOpen, setMoreOpen] = useState(false); const railItems = useRailItems(); const hidden = useHiddenRailTabs(); const visible = useMemo( () => railItems.filter((item) => !hidden.has(item.id)), [railItems, hidden], ); const main = visible.filter((item) => item.placement !== "footer"); const footer = visible.filter((item) => item.placement === "footer"); const primary = useMemo(() => pickPrimaryItems(main), [main]); const bands = useMemo(() => groupRailItems(main), [main]); const badged = footer.find((item) => item.useBadge); const close = () => setMoreOpen(false); const open = (item: RailItemDef) => { close(); if (item.kind === "tab") onOpenTab(item.id as TabType); else onRailClick(item.id as RailView); }; return ( <> {moreOpen && (
{ close(); onOpenPalette(); }} /> {bands.map((band) => (
{t(`nav.group.${band.group}`)}
{band.items.map((item) => ( { close(); onOpenTab(item.id as TabType); } : undefined } onClick={() => open(item)} /> ))}
))}
{footer.map((item) => ( open(item)} /> ))} { close(); onOpenSettings(); }} /> {!isElectron() && ( { close(); onLogout(); }} /> )}
)} ); } function BarButton({ icon: Icon, label, active, useBadge, onClick, }: { icon: React.ElementType; label: string; active?: boolean; useBadge?: () => number | null | undefined; onClick: () => void; }) { return ( ); } function SheetRow({ icon: Icon, label, hint, useBadge, active, onClick, onOpenAsTab, }: { icon: React.ElementType; label: string; hint?: string; useBadge?: () => number | null | undefined; active?: boolean; onClick: () => void; onOpenAsTab?: () => void; }) { const { t } = useTranslation(); return (
{onOpenAsTab && ( )}
); }