"use client"; import Image from "next/image"; import type { StoreAppSummary } from "@/lib/shared/contracts/apps"; import type { RecentCommandAction } from "@/lib/desktop/recent-actions"; import { CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, } from "@/components/ui/command"; import { Clock, FolderOpen, Search, Settings, ShoppingBag, Sparkles, TerminalSquare, } from "@/components/icons/platform-icons"; import { useDebouncedValue } from "@/hooks/useDebouncedValue"; import { useStoreCatalog } from "@/modules/apps/hooks/useStoreCatalog"; export type CommandPaletteSettingsSection = { id: string; label: string; }; export type CommandPaletteRecentAction = RecentCommandAction; type CommandPaletteProps = { open: boolean; onOpenChange: (open: boolean) => void; query: string; onQueryChange: (query: string) => void; settingsSections: readonly CommandPaletteSettingsSection[]; recentActions: readonly CommandPaletteRecentAction[]; onOpenSettingsSection: (sectionId: string) => void; onOpenAppStoreSearch: (input: { search: string; appId?: string }) => void; onOpenWindow: (windowId: "files" | "settings" | "app-store" | "terminal") => void; onSelectRecentAction: (action: CommandPaletteRecentAction) => void; }; function StoreSearchIcon({ app }: { app: StoreAppSummary }) { if (app.logoUrl) { return (
); } return (
); } export function CommandPalette({ open, onOpenChange, query, onQueryChange, settingsSections, recentActions, onOpenSettingsSection, onOpenAppStoreSearch, onOpenWindow, onSelectRecentAction, }: CommandPaletteProps) { const normalizedQuery = query.trim(); const debouncedQuery = useDebouncedValue(normalizedQuery, 180); const matchingSettings = normalizedQuery ? settingsSections.filter((section) => section.label.toLowerCase().includes(normalizedQuery.toLowerCase()), ) : settingsSections.slice(0, 5); const storeCatalogQuery = useStoreCatalog({ search: debouncedQuery || undefined, }); const appResults = (storeCatalogQuery.data?.apps ?? []) .slice(0, normalizedQuery ? 7 : 5); const filteredRecentActions = recentActions.filter((action) => { if (!normalizedQuery) return true; const haystack = `${action.title} ${action.subtitle}`.toLowerCase(); return haystack.includes(normalizedQuery.toLowerCase()); }); function renderRecentActionIcon(action: CommandPaletteRecentAction) { if (action.kind === "window") { if (action.windowId === "files") return ; if (action.windowId === "settings") return ; if (action.windowId === "app-store") { return ; } return ; } if (action.kind === "settings-section") { return ; } return ; } return ( {/* Hero header — matches lock screen / login design language */}
Command Palette
⌘K · Esc

No matches found

Try a settings section, app name, or desktop tool.

{filteredRecentActions.length > 0 ? ( <> {filteredRecentActions.map((action) => ( onSelectRecentAction(action)} > {renderRecentActionIcon(action)}
{action.title}
{action.subtitle}
Recent
))}
) : null} onOpenWindow("settings")}> Open Settings System onOpenWindow("app-store")}> Open App Store Apps onOpenWindow("files")}> Open Files /DATA onOpenWindow("terminal")}> Open Terminal Shell {matchingSettings.map((section) => ( onOpenSettingsSection(section.id)} > {section.label} Settings ))} {storeCatalogQuery.isLoading && normalizedQuery ? (
Searching apps...
) : null} {!storeCatalogQuery.isLoading && appResults.length === 0 && normalizedQuery ? (
No App Store apps match “{normalizedQuery}”.
) : null} {appResults.map((app) => ( onOpenAppStoreSearch({ search: app.name, appId: app.id, }) } className="gap-3 rounded-lg py-2.5" >
{app.name} {app.updateAvailable ? ( Update ) : null}

{app.description}

App Store
))}
); }