"use client" import { Command } from "cmdk" import { useEffect, useRef, useState } from "react" import { useRouter } from "next/navigation" import { useUserInterfaceStore } from "@/lib/stores/user-interface-store" import { useSubscriptions } from "@/lib/queries/use-subscriptions" export function CommandPalette() { const isOpen = useUserInterfaceStore((state) => state.isCommandPaletteOpen) const setOpen = useUserInterfaceStore((state) => state.setCommandPaletteOpen) const toggleSidebar = useUserInterfaceStore((state) => state.toggleSidebar) const setEntryListViewMode = useUserInterfaceStore( (state) => state.setEntryListViewMode ) const setAddFeedDialogOpen = useUserInterfaceStore( (state) => state.setAddFeedDialogOpen ) const router = useRouter() const { data: subscriptionsData } = useSubscriptions() const listReference = useRef(null) const [inputValue, setInputValue] = useState("") useEffect(() => { function handleKeyDown(event: KeyboardEvent) { if (event.key === "k" && (event.metaKey || event.ctrlKey)) { event.preventDefault() setOpen(!isOpen) } } document.addEventListener("keydown", handleKeyDown) return () => document.removeEventListener("keydown", handleKeyDown) }, [isOpen, setOpen]) useEffect(() => { if (!isOpen) return function handleKeyDown(event: KeyboardEvent) { if (event.key === "Escape") { setOpen(false) return } if (event.key === "ArrowDown" || event.key === "ArrowUp") { setTimeout(() => { const list = listReference.current if (!list) return const selected = list.querySelector('[aria-selected="true"]') as HTMLElement if (!selected) return const listRect = list.getBoundingClientRect() const selectedRect = selected.getBoundingClientRect() if (selectedRect.bottom > listRect.bottom) { list.scrollTop += selectedRect.bottom - listRect.bottom } else if (selectedRect.top < listRect.top) { list.scrollTop -= listRect.top - selectedRect.top } }, 0) } } document.addEventListener("keydown", handleKeyDown) return () => document.removeEventListener("keydown", handleKeyDown) }, [isOpen, setOpen]) if (!isOpen) return null function handleInputKeyDown(event: React.KeyboardEvent) { if (event.key === "Backspace" && inputValue === "") { event.preventDefault() setOpen(false) } } function navigateAndClose(path: string) { router.push(path) setOpen(false) } function actionAndClose(action: () => void) { action() setOpen(false) } return (
setOpen(false)} /> no results found navigateAndClose("/reader")} className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary" > go to all entries navigateAndClose("/reader/saved")} className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary" > go to saved navigateAndClose("/reader/settings")} className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary" > go to settings {subscriptionsData && subscriptionsData.subscriptions.length > 0 && ( {subscriptionsData.subscriptions.map((subscription) => ( navigateAndClose( `/reader?feed=${subscription.feedIdentifier}` ) } className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary" > {subscription.customTitle ?? subscription.feedTitle} ))} )} actionAndClose(() => setAddFeedDialogOpen(true)) } className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary" > add feed actionAndClose(toggleSidebar)} className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary" > toggle sidebar actionAndClose(() => setEntryListViewMode("compact")) } className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary" > compact view actionAndClose(() => setEntryListViewMode("comfortable")) } className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary" > comfortable view actionAndClose(() => setEntryListViewMode("expanded")) } className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary" > expanded view actionAndClose(() => { const store = useUserInterfaceStore.getState() store.resetSidebarLayout?.() store.resetDetailLayout?.() }) } className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary" > reset panel sizes
) }