persist command palette collapsed sections to app store

This commit is contained in:
jeffvli
2026-03-17 22:34:07 -07:00
parent 3c562c1398
commit b7cbdb4d6c
3 changed files with 65 additions and 7 deletions
@@ -8,19 +8,30 @@ import { Paper } from '/@/shared/components/paper/paper';
interface CollapsibleCommandGroupProps {
children: ReactNode;
defaultExpanded?: boolean;
expanded?: boolean;
heading: string;
onToggle?: () => void;
}
export function CollapsibleCommandGroup({
children,
defaultExpanded = true,
expanded: controlledExpanded,
heading,
onToggle,
}: CollapsibleCommandGroupProps) {
const [expanded, setExpanded] = useState(defaultExpanded);
const [internalExpanded, setInternalExpanded] = useState(defaultExpanded);
const isControlled = controlledExpanded !== undefined && onToggle !== undefined;
const expanded = isControlled ? controlledExpanded : internalExpanded;
const toggle = useCallback(() => {
setExpanded((prev) => !prev);
}, []);
if (isControlled) {
onToggle?.();
} else {
setInternalExpanded((prev) => !prev);
}
}, [isControlled, onToggle]);
const handleKeyDown = useCallback(
(e: React.KeyboardEvent) => {
@@ -12,7 +12,7 @@ import { HomeCommands } from '/@/renderer/features/search/components/home-comman
import { LibraryCommandItem } from '/@/renderer/features/search/components/library-command-item';
import { ServerCommands } from '/@/renderer/features/search/components/server-commands';
import { AppRoute } from '/@/renderer/router/routes';
import { useCurrentServer } from '/@/renderer/store';
import { useAppStore, useCurrentServer } from '/@/renderer/store';
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
import { Breadcrumb } from '/@/shared/components/breadcrumb/breadcrumb';
import { Button } from '/@/shared/components/button/button';
@@ -31,9 +31,21 @@ interface CommandPaletteProps {
modalProps: (typeof useDisclosure)['arguments'];
}
const SEARCH_SECTION_IDS = {
albums: 'albums',
artists: 'artists',
tracks: 'tracks',
} as const;
export const CommandPalette = ({ modalProps }: CommandPaletteProps) => {
const navigate = useNavigate();
const server = useCurrentServer();
const searchSectionsExpanded = useAppStore(
(state) => state.commandPaletteSearchSectionsExpanded,
);
const setSearchSectionExpanded = useAppStore(
(state) => state.actions.setCommandPaletteSearchSectionExpanded,
);
const [value, setValue] = useState('');
const [query, setQuery] = useState('');
const [debouncedQuery] = useDebouncedValue(query, 400);
@@ -148,7 +160,16 @@ export const CommandPalette = ({ modalProps }: CommandPaletteProps) => {
{t('common.noResultsFromQuery', { postProcess: 'sentenceCase' })}
</Command.Empty>
{showAlbumGroup && (
<CollapsibleCommandGroup heading="Albums">
<CollapsibleCommandGroup
expanded={searchSectionsExpanded[SEARCH_SECTION_IDS.albums] ?? true}
heading="Albums"
onToggle={() =>
setSearchSectionExpanded(
SEARCH_SECTION_IDS.albums,
!(searchSectionsExpanded[SEARCH_SECTION_IDS.albums] ?? true),
)
}
>
{data?.albums?.map((album) => (
<CommandItemSelectable
key={`search-album-${album.id}`}
@@ -182,7 +203,16 @@ export const CommandPalette = ({ modalProps }: CommandPaletteProps) => {
</CollapsibleCommandGroup>
)}
{showArtistGroup && (
<CollapsibleCommandGroup heading="Artists">
<CollapsibleCommandGroup
expanded={searchSectionsExpanded[SEARCH_SECTION_IDS.artists] ?? true}
heading="Artists"
onToggle={() =>
setSearchSectionExpanded(
SEARCH_SECTION_IDS.artists,
!(searchSectionsExpanded[SEARCH_SECTION_IDS.artists] ?? true),
)
}
>
{data?.albumArtists.map((artist) => (
<CommandItemSelectable
key={`artist-${artist.id}`}
@@ -221,7 +251,16 @@ export const CommandPalette = ({ modalProps }: CommandPaletteProps) => {
</CollapsibleCommandGroup>
)}
{showTrackGroup && (
<CollapsibleCommandGroup heading="Tracks">
<CollapsibleCommandGroup
expanded={searchSectionsExpanded[SEARCH_SECTION_IDS.tracks] ?? true}
heading="Tracks"
onToggle={() =>
setSearchSectionExpanded(
SEARCH_SECTION_IDS.tracks,
!(searchSectionsExpanded[SEARCH_SECTION_IDS.tracks] ?? true),
)
}
>
{data?.songs.map((song) => (
<CommandItemSelectable
key={`artist-${song.id}`}