diff --git a/src/renderer/features/search/components/command-palette.tsx b/src/renderer/features/search/components/command-palette.tsx new file mode 100644 index 00000000..8e4aa275 --- /dev/null +++ b/src/renderer/features/search/components/command-palette.tsx @@ -0,0 +1,99 @@ +/* eslint-disable react/no-unknown-property */ +import { useCallback, useState } from 'react'; +import { useDisclosure } from '@mantine/hooks'; +import styled from 'styled-components'; +import { GoToCommands } from './go-to-commands'; +import { Command, CommandPalettePages } from '/@/renderer/features/search/components/command'; +import { Modal } from '/@/renderer/components'; +import { HomeCommands } from './home-commands'; + +interface CommandPaletteProps { + modalProps: typeof useDisclosure['arguments']; +} + +const CustomModal = styled(Modal)` + & .mantine-Modal-header { + display: none; + } +`; + +export const CommandPalette = ({ modalProps }: CommandPaletteProps) => { + const [value, setValue] = useState(''); + const [query, setQuery] = useState(''); + const [pages, setPages] = useState([CommandPalettePages.HOME]); + const activePage = pages[pages.length - 1]; + const isHome = activePage === CommandPalettePages.HOME; + + const popPage = useCallback(() => { + setPages((pages) => { + const x = [...pages]; + x.splice(-1, 1); + return x; + }); + }, []); + + return ( + { + if (isHome) { + modalProps.handlers.close(); + setQuery(''); + } else { + popPage(); + } + }, + toggle: () => { + console.log('toggle'); + if (isHome) { + modalProps.handlers.toggle(); + setQuery(''); + } else { + popPage(); + } + }, + }} + > + { + if (value.includes(search)) return 1; + if (value === 'search') return 1; + return 0; + }} + label="Global Command Menu" + value={value} + onValueChange={setValue} + > + + + + No results found. + + {activePage === CommandPalettePages.HOME && ( + + )} + {activePage === CommandPalettePages.GO_TO && ( + + )} + + + + ); +}; diff --git a/src/renderer/features/search/components/command.tsx b/src/renderer/features/search/components/command.tsx new file mode 100644 index 00000000..8bb56d44 --- /dev/null +++ b/src/renderer/features/search/components/command.tsx @@ -0,0 +1,61 @@ +import { Command as Cmdk } from 'cmdk'; +import styled from 'styled-components'; + +export enum CommandPalettePages { + GO_TO = 'go to', + HOME = 'home', +} + +export const Command = styled(Cmdk)` + [cmdk-root] { + font-family: var(--content-font-family); + background-color: var(--background-color); + } + + input[cmdk-input] { + width: 100%; + height: 2rem; + margin-bottom: 1rem; + padding: 0 0.5rem; + color: var(--input-fg); + font-size: 1.1rem; + background: transparent; + border: none; + + &::placeholder { + color: var(--input-placeholder-fg); + } + } + + div[cmdk-group-heading] { + margin: 1rem 0; + font-size: 0.9rem; + opacity: 0.8; + } + + div[cmdk-item] { + display: flex; + gap: 0.5rem; + align-items: center; + padding: 1rem 0.5rem; + color: var(--btn-subtle-fg); + background: var(--btn-subtle-bg); + border-radius: 5px; + + svg { + width: 1.2rem; + height: 1.2rem; + } + + &[data-selected] { + color: var(--btn-subtle-fg-hover); + background: rgba(255, 255, 255, 10%); + } + } + + div[cmdk-separator] { + height: 1px; + margin: 0 0 0.5rem; + background: var(--generic-border-color); + } +`; diff --git a/src/renderer/features/search/components/go-to-commands.tsx b/src/renderer/features/search/components/go-to-commands.tsx new file mode 100644 index 00000000..cc1f3c8d --- /dev/null +++ b/src/renderer/features/search/components/go-to-commands.tsx @@ -0,0 +1,41 @@ +import { useCallback } from 'react'; +import { useNavigate } from 'react-router'; +import { Command, CommandPalettePages } from '/@/renderer/features/search/components/command'; +import { AppRoute } from '/@/renderer/router/routes'; + +interface GoToCommandsProps { + handleClose: () => void; + setPages: (pages: CommandPalettePages[]) => void; +} + +export const GoToCommands = ({ setPages, handleClose }: GoToCommandsProps) => { + const navigate = useNavigate(); + + const goTo = useCallback( + (route: string) => { + navigate(route); + setPages([CommandPalettePages.HOME]); + handleClose(); + }, + [handleClose, navigate, setPages], + ); + + return ( + <> + goTo(AppRoute.HOME)}>Home + goTo(AppRoute.SEARCH)}>Search + goTo(AppRoute.SETTINGS)}>Settings + + goTo(AppRoute.LIBRARY_ALBUMS)}>Albums + goTo(AppRoute.LIBRARY_SONGS)}>Tracks + goTo(AppRoute.LIBRARY_ALBUM_ARTISTS)}> + Album artists + + goTo(AppRoute.LIBRARY_GENRES)}>Genres + goTo(AppRoute.LIBRARY_FOLDERS)}>Folders + goTo(AppRoute.PLAYLISTS)}>Playlists + + + + ); +}; diff --git a/src/renderer/features/search/components/home-commands.tsx b/src/renderer/features/search/components/home-commands.tsx new file mode 100644 index 00000000..66d771da --- /dev/null +++ b/src/renderer/features/search/components/home-commands.tsx @@ -0,0 +1,62 @@ +import { openModal, closeAllModals } from '@mantine/modals'; +import { Dispatch, useCallback } from 'react'; +import { useNavigate } from 'react-router'; +import { CreatePlaylistForm } from '/@/renderer/features/playlists'; +import { Command, CommandPalettePages } from '/@/renderer/features/search/components/command'; +import { AppRoute } from '/@/renderer/router/routes'; +import { useCurrentServer } from '/@/renderer/store'; +import { ServerType } from '/@/renderer/types'; + +interface HomeCommandsProps { + handleClose: () => void; + pages: CommandPalettePages[]; + query: string; + setPages: Dispatch; + setQuery: Dispatch; +} + +export const HomeCommands = ({ + query, + setQuery, + pages, + setPages, + handleClose, +}: HomeCommandsProps) => { + const navigate = useNavigate(); + const server = useCurrentServer(); + + const handleCreatePlaylistModal = useCallback(() => { + handleClose(); + + openModal({ + children: closeAllModals()} />, + size: server?.type === ServerType?.NAVIDROME ? 'lg' : 'sm', + title: 'Create Playlist', + }); + }, [handleClose, server?.type]); + + const handleSearch = useCallback(() => { + navigate(AppRoute.SEARCH); + setQuery(''); + handleClose(); + }, [handleClose, navigate, setQuery]); + + return ( + <> + + Create playlist... + setPages([...pages, CommandPalettePages.GO_TO])}> + Go to page... + + {query !== '' && ( + + {query ? `Search for "${query}"...` : 'Search...'} + + )} + + + ); +};