diff --git a/interface/app/$libraryId/Explorer/ContextMenu/FilePath/Items.tsx b/interface/app/$libraryId/Explorer/ContextMenu/FilePath/Items.tsx index 55d8f8afc..22d6c8988 100644 --- a/interface/app/$libraryId/Explorer/ContextMenu/FilePath/Items.tsx +++ b/interface/app/$libraryId/Explorer/ContextMenu/FilePath/Items.tsx @@ -1,15 +1,8 @@ import { Image, Package, Trash, TrashSimple } from '@phosphor-icons/react'; import { libraryClient, useLibraryMutation } from '@sd/client'; -import { - ContextMenu, - dialogManager, - keySymbols, - ModifierKeys, - modifierSymbols, - toast -} from '@sd/ui'; +import { ContextMenu, dialogManager, ModifierKeys, toast } from '@sd/ui'; import { Menu } from '~/components/Menu'; -import { useOperatingSystem } from '~/hooks'; +import { useKeysMatcher, useOperatingSystem } from '~/hooks'; import { useKeybindFactory } from '~/hooks/useKeybindFactory'; import { useQuickRescan } from '~/hooks/useQuickRescan'; import { isNonEmpty } from '~/util'; @@ -33,7 +26,7 @@ export const Delete = new ConditionalItem({ }, Component: ({ selectedFilePaths, selectedEphemeralPaths }) => { const rescan = useQuickRescan(); - + const os = useOperatingSystem(); const dirCount = selectedFilePaths.filter((p) => p.is_dir).length + selectedEphemeralPaths.filter((p) => p.is_dir).length; @@ -55,12 +48,18 @@ export const Delete = new ConditionalItem({ paths: selectedEphemeralPaths.map((p) => p.path) } : undefined; + const deleteKeybind = useKeysMatcher(['Meta', 'Backspace']); return ( dialogManager.create((dp) => ( ; -type osKeys = Record; icon: string }>; + +type keyTypes = + keyof typeof ModifierKeys | keyof typeof EditingKeys | keyof typeof UIKeys | keyof typeof NavigationKeys; //This is a helper function to handle the possibility of a modifier key being undefined due to OS initial check -const modifierKey = (key: keyof typeof ModifierKeys, os: 'Windows' | 'macOS' | 'Other') => { +const modifierKey = (key: keyTypes, os: 'Windows' | 'macOS' | 'Other') => { return modifierSymbols[key][os] ?? modifierSymbols[key]['Other']; }; + //Match macOS keys to Windows keys and others -const keysOsMap = { +const keysOsMap: { + [T in keyTypes]?: { + [T in os]?: { key: string; icon: string }; + }; +} = { Meta: { macOS: { key: 'Meta', icon: modifierKey(ModifierKeys.Meta, 'macOS') }, - windows: { key: 'Control', icon: modifierKey(ModifierKeys.Control, 'Windows') }, - browser: { key: 'Control', icon: modifierKey(ModifierKeys.Control, 'Windows') }, - linux: { key: 'Control', icon: modifierKey(ModifierKeys.Control, 'Windows') }, - unknown: { key: 'Control', icon: modifierKey(ModifierKeys.Control, 'Windows') } - }, + all: { key: 'Control', icon: modifierKey(ModifierKeys.Control, 'Windows') }, }, Shift: { macOS: { key: 'Shift', icon: modifierKey(ModifierKeys.Shift, 'macOS') }, - windows: { key: 'Shift', icon: modifierKey(ModifierKeys.Shift, 'Other') }, - browser: { key: 'Shift', icon: modifierKey(ModifierKeys.Shift, 'Other') }, - linux: { key: 'Shift', icon: modifierKey(ModifierKeys.Shift, 'Other') }, - unknown: { key: 'Shift', icon: modifierKey(ModifierKeys.Shift, 'Other') } + all: { key: 'Shift', icon: modifierKey(ModifierKeys.Shift, 'Other') }, }, Alt: { macOS: { key: 'Alt', icon: modifierKey(ModifierKeys.Alt, 'macOS') }, - windows: { key: 'Alt', icon: modifierKey(ModifierKeys.Alt, 'Other') }, - browser: { key: 'Alt', icon: modifierKey(ModifierKeys.Alt, 'Other') }, - linux: { key: 'Alt', icon: modifierKey(ModifierKeys.Alt, 'Other') }, - unknown: { key: 'Alt', icon: modifierKey(ModifierKeys.Alt, 'Other') } + all: { key: 'Alt', icon: modifierKey(ModifierKeys.Alt, 'Other') }, + }, + Escape: { + macOS: { key: 'Escape', icon: modifierKey(UIKeys.Escape, 'macOS') }, + all: { key: 'Escape', icon: modifierKey(UIKeys.Escape, 'Other') }, + }, + Delete: { + macOS: { key: 'Delete', icon: modifierKey(EditingKeys.Delete, 'macOS') }, + all: { key: 'Delete', icon: modifierKey(EditingKeys.Delete, 'Other') }, + }, + Backspace: { + macOS: { key: 'Backspace', icon: modifierKey(EditingKeys.Backspace, 'macOS') }, + all: { key: 'Backspace', icon: modifierKey(EditingKeys.Backspace, 'Other') }, + }, + ArrowUp: { + all: { key: 'ArrowUp', icon: modifierKey(NavigationKeys.ArrowUp, 'Other') }, + }, + ArrowDown: { + all: { key: 'ArrowDown', icon: modifierKey(NavigationKeys.ArrowDown, 'Other') }, + }, + ArrowLeft: { + all: { key: 'ArrowLeft', icon: modifierKey(NavigationKeys.ArrowLeft, 'Other') }, + }, + ArrowRight: { + all: { key: 'ArrowRight', icon: modifierKey(NavigationKeys.ArrowRight, 'Other') }, } -}; +} -export function useKeyMatcher(arg: T): { key: string; icon: string } { - const os = useOperatingSystem(); - const key = keysOsMap[arg][os]; +type keysOfOsMap = keyof typeof keysOsMap; +type os = Exclude | "all" + +export function useKeyMatcher(arg: T): + { key: string; icon: string } { + const os = useOperatingSystem() as os; + const key = keysOsMap[arg]?.[os] ?? keysOsMap[arg]?.['all'] + if (!key) { + throw new Error(`No key found for ${arg} on ${os}`); + } return key; } //This is another hook to pass an array for multiple keys rather than one at a time -export function useKeysMatcher( +export function useKeysMatcher( arg: T[] ): Record { - const os = useOperatingSystem(); + const os = useOperatingSystem() as os; const object = {} as Record; for (const key of arg) { - object[key] = { - key: keysOsMap[key][os].key, - icon: keysOsMap[key][os].icon - }; + object[key] = { + key: keysOsMap[key]?.[os]?.key as string ?? keysOsMap[key]?.['all']?.key, + icon: keysOsMap[key]?.[os]?.icon as string ?? keysOsMap[key]?.['all']?.icon, + }; } return object; } diff --git a/packages/ui/src/keys.ts b/packages/ui/src/keys.ts index 510435fcc..d8783a2a4 100644 --- a/packages/ui/src/keys.ts +++ b/packages/ui/src/keys.ts @@ -11,13 +11,29 @@ export enum ModifierKeys { NumLock = 'NumLock', ScrollLock = 'ScrollLock', Symbol = 'Symbol', - SymbolLock = 'SymbolLock' + SymbolLock = 'SymbolLock', +} + +export enum EditingKeys { + Backspace = 'Backspace', + Delete = 'Delete' +} + +export enum UIKeys { + Escape = 'Escape', +} + +export enum NavigationKeys { + ArrowUp = 'ArrowUp', + ArrowDown = 'ArrowDown', + ArrowLeft = 'ArrowLeft', + ArrowRight = 'ArrowRight', } export type OSforKeys = 'macOS' | 'Windows' | 'Other'; export const modifierSymbols: Record< - ModifierKeys, + ModifierKeys | EditingKeys | UIKeys | NavigationKeys, { macOS?: string; Windows?: string; Other: string } > = { Alt: { macOS: '⌥', Other: 'Alt' }, @@ -31,7 +47,14 @@ export const modifierSymbols: Record< ScrollLock: { macOS: '⤓', Other: 'ScrLk' }, Shift: { Other: 'Shift', macOS: '⇧' }, Symbol: { macOS: '⎄', Other: 'Sym' }, - SymbolLock: { macOS: '⎄', Other: 'Sym' } + SymbolLock: { macOS: '⎄', Other: 'Sym' }, + Escape: { macOS: '⎋', Other: 'Esc' }, + Delete: { macOS: '⌦', Other: 'Del' }, + Backspace: { macOS: '⌫', Other: '⟵' }, + ArrowUp: { Other: '↑' }, + ArrowDown: { Other: '↓' }, + ArrowLeft: { Other: '←' }, + ArrowRight: { Other: '→' }, }; export const keySymbols: Record = {