From ce9ccec98dd751649cd22759ccb8b64baed22911 Mon Sep 17 00:00:00 2001 From: ameer2468 <33054370+ameer2468@users.noreply.github.com> Date: Mon, 18 Sep 2023 17:09:40 +0300 Subject: [PATCH] [ENG-1119] - Open folder shortcut + select item with arrow down (#1355) * Open folder shortcut + select item with arrow down * tweaks * symbol tweaks * Update index.tsx --- .../app/$libraryId/Explorer/TopBarOptions.tsx | 20 +++++++++------ .../app/$libraryId/Explorer/View/GridList.tsx | 16 +++++++++++- .../app/$libraryId/Explorer/View/ListView.tsx | 23 +++++++++++------ .../app/$libraryId/Explorer/View/index.tsx | 10 +++++++- .../app/$libraryId/Layout/Sidebar/Footer.tsx | 25 +++++++++++++------ .../app/$libraryId/TopBar/TopBarOptions.tsx | 7 ++++-- .../settings/library/locations/PathInput.tsx | 3 +-- 7 files changed, 77 insertions(+), 27 deletions(-) diff --git a/interface/app/$libraryId/Explorer/TopBarOptions.tsx b/interface/app/$libraryId/Explorer/TopBarOptions.tsx index 0e7b27ceb..51b6c9798 100644 --- a/interface/app/$libraryId/Explorer/TopBarOptions.tsx +++ b/interface/app/$libraryId/Explorer/TopBarOptions.tsx @@ -11,9 +11,8 @@ import { import clsx from 'clsx'; import { useEffect, useRef } from 'react'; import { useRspcLibraryContext } from '@sd/client'; -import { ModifierKeys } from '~/../packages/ui/src'; +import { ModifierKeys, modifierSymbols } from '@sd/ui'; import { useOperatingSystem } from '~/hooks'; -import { keybindForOs } from '~/util/keybinds'; import { KeyManager } from '../KeyManager'; import TopBarOptions, { ToolOption, TOP_BAR_ICON_STYLE } from '../TopBar/TopBarOptions'; @@ -26,7 +25,14 @@ export const useExplorerTopBarOptions = () => { const explorerStore = useExplorerStore(); const explorer = useExplorerContext(); const os = useOperatingSystem(); - const keybind = keybindForOs(os); + const controlSymbol = (letter: string) => { + return [ + os === 'macOS' + ? modifierSymbols[ModifierKeys.Meta][os] + : modifierSymbols[ModifierKeys.Control]['Other'], + letter + ] as string[]; + }; const settings = explorer.useSettingsSnapshot(); @@ -34,7 +40,7 @@ export const useExplorerTopBarOptions = () => { { toolTipLabel: 'Grid view', icon: , - keybinds: [keybind([ModifierKeys.Meta], ['V'])], + keybinds: controlSymbol('V'), topBarActive: settings.layoutMode === 'grid', onClick: () => (explorer.settingsStore.layoutMode = 'grid'), showAtResolution: 'sm:flex' @@ -42,7 +48,7 @@ export const useExplorerTopBarOptions = () => { { toolTipLabel: 'List view', icon: , - keybinds: [keybind([ModifierKeys.Meta], ['V'])], + keybinds: controlSymbol('V'), topBarActive: settings.layoutMode === 'list', onClick: () => (explorer.settingsStore.layoutMode = 'list'), showAtResolution: 'sm:flex' @@ -57,7 +63,7 @@ export const useExplorerTopBarOptions = () => { { toolTipLabel: 'Media view', icon: , - keybinds: [keybind([ModifierKeys.Meta], ['V'])], + keybinds: controlSymbol('V'), topBarActive: settings.layoutMode === 'media', onClick: () => (explorer.settingsStore.layoutMode = 'media'), showAtResolution: 'sm:flex' @@ -74,7 +80,7 @@ export const useExplorerTopBarOptions = () => { }, { toolTipLabel: 'Show Inspector', - keybinds: [keybind([ModifierKeys.Meta], ['I'])], + keybinds: controlSymbol('I'), onClick: () => (getExplorerStore().showInspector = !explorerStore.showInspector), icon: ( { return; } + if (e.key === 'ArrowDown' && explorer.selectedItems.size === 0) { + const item = grid.getItem(0); + if (!item?.data) return; + const selectedItemDom = document.querySelector( + `[data-selectable-id="${uniqueId(item.data)}"]` + ); + if (selectedItemDom) { + explorer.resetSelectedItems([item.data]); + selecto.current?.setSelectedTargets([selectedItemDom as HTMLElement]); + activeItem.current = item.data; + } + return; + } + if (explorer.selectedItems.size > 0) e.preventDefault(); const lastItem = activeItem.current; diff --git a/interface/app/$libraryId/Explorer/View/ListView.tsx b/interface/app/$libraryId/Explorer/View/ListView.tsx index 1d447b3b6..788cd087e 100644 --- a/interface/app/$libraryId/Explorer/View/ListView.tsx +++ b/interface/app/$libraryId/Explorer/View/ListView.tsx @@ -59,7 +59,7 @@ interface ListViewItemProps { const ListViewItem = memo((props: ListViewItemProps) => { return ( -
+
{props.row.getVisibleCells().map((cell) => (
{ const range = getRangeByIndex(ranges.length - 1); + if (e.key === 'ArrowDown' && explorer.selectedItems.size === 0) { + const item = rows[0]?.original; + if (item) { + explorer.addSelectedItem(item); + setRanges([[uniqueId(item), uniqueId(item)]]); + } + return; + } + if (!range) return; if (e.key === 'Escape') { @@ -1019,7 +1028,7 @@ export default () => { useLayoutEffect(() => setListOffset(tableRef.current?.offsetTop ?? 0), []); return ( -
+
{sized && ( <> @@ -1041,7 +1050,7 @@ export default () => {
e.stopPropagation()} > {headerGroup.headers.map((header, i) => { @@ -1064,7 +1073,7 @@ export default () => { return (
{ -
+
{ return (
{ )} > {selectedPrior && ( -
+
)} { const navigate = useNavigate(); const { library } = useLibraryContext(); const { openFilePaths } = usePlatform(); + const os = useOperatingSystem(); const updateAccessTime = useLibraryMutation('files.updateAccessTime'); + const metaCtrlKey = os === 'macOS' ? ModifierKeys.Meta : ModifierKeys.Control; + + useKeys([metaCtrlKey, 'ArrowUp'], async (e) => { + e.stopPropagation(); + await onDoubleClick(); + }); const onDoubleClick = async () => { const selectedItems = [...explorer.selectedItems]; @@ -279,7 +287,7 @@ export const EmptyNotice = (props: { icon?: Icon | ReactNode; message?: ReactNod }; return ( -
+
{props.icon ? isValidElement(props.icon) ? props.icon diff --git a/interface/app/$libraryId/Layout/Sidebar/Footer.tsx b/interface/app/$libraryId/Layout/Sidebar/Footer.tsx index a306991c9..53f1b2be8 100644 --- a/interface/app/$libraryId/Layout/Sidebar/Footer.tsx +++ b/interface/app/$libraryId/Layout/Sidebar/Footer.tsx @@ -1,9 +1,16 @@ import { Gear } from '@phosphor-icons/react'; import { useNavigate } from 'react-router'; import { JobManagerContextProvider, useClientContext, useDebugState } from '@sd/client'; -import { Button, ButtonLink, dialogManager, ModifierKeys, Popover, Tooltip } from '@sd/ui'; +import { + Button, + ButtonLink, + dialogManager, + ModifierKeys, + modifierSymbols, + Popover, + Tooltip +} from '@sd/ui'; import { useKeyBind, useOperatingSystem } from '~/hooks'; -import { keybindForOs } from '~/util/keybinds'; import DebugPopover from './DebugPopover'; import FeedbackDialog from './FeedbackDialog'; @@ -13,8 +20,12 @@ export default () => { const { library } = useClientContext(); const debugState = useDebugState(); const os = useOperatingSystem(); - const keybind = keybindForOs(os); const navigate = useNavigate(); + const jobManagerKeys = [os === 'macOS' ? ModifierKeys.Meta : ModifierKeys.Control, 'j']; + const recentJobsSymbol = + os === 'macOS' + ? modifierSymbols[ModifierKeys.Meta][os] + : modifierSymbols[ModifierKeys.Control]['Other']; useKeyBind(['g', 's'], (e) => { e.stopPropagation(); @@ -23,7 +34,7 @@ export default () => { return (
-
+
{ className="text-sidebar-inkFaint ring-offset-sidebar" > - + { {library && ( diff --git a/interface/app/$libraryId/TopBar/TopBarOptions.tsx b/interface/app/$libraryId/TopBar/TopBarOptions.tsx index 466cbbaeb..5b56848dc 100644 --- a/interface/app/$libraryId/TopBar/TopBarOptions.tsx +++ b/interface/app/$libraryId/TopBar/TopBarOptions.tsx @@ -3,6 +3,7 @@ import { useLayoutEffect, useState } from 'react'; import { useKeys } from 'rooks'; import { ModifierKeys, Popover, Tooltip } from '@sd/ui'; import { ExplorerLayout } from '~/../packages/client/src'; +import { useKeyBind, useOperatingSystem } from '~/hooks'; import { useExplorerContext } from '../Explorer/Context'; import TopBarButton from './TopBarButton'; @@ -33,8 +34,10 @@ export default ({ options }: TopBarChildrenProps) => { const toolsNotSmFlex = options ?.flatMap((group) => group) .filter((t) => t.showAtResolution !== 'sm:flex'); + const os = useOperatingSystem(); + const keys = [os === 'macOS' ? ModifierKeys.Meta : ModifierKeys.Control, 'v']; - useKeys(['Meta', 'v'], (e) => { + useKeyBind(keys, (e) => { e.stopPropagation(); const explorerLayouts: ExplorerLayout[] = ['grid', 'list', 'media']; //based on the order of the icons const currentLayout = explorerLayouts.indexOf( @@ -56,7 +59,7 @@ export default ({ options }: TopBarChildrenProps) => { }, []); return ( -
+
{options?.map((group, groupIndex) => { return group.map( diff --git a/interface/app/$libraryId/settings/library/locations/PathInput.tsx b/interface/app/$libraryId/settings/library/locations/PathInput.tsx index 0299bc797..f4ac5a2d5 100644 --- a/interface/app/$libraryId/settings/library/locations/PathInput.tsx +++ b/interface/app/$libraryId/settings/library/locations/PathInput.tsx @@ -2,8 +2,8 @@ import clsx from 'clsx'; import { forwardRef } from 'react'; import { useFormContext } from 'react-hook-form'; import { InputField, InputFieldProps, toast } from '@sd/ui'; - import { usePlatform } from '~/util/Platform'; + import { openDirectoryPickerDialog } from './openDirectoryPickerDialog'; export const LocationPathInputField = forwardRef< @@ -12,7 +12,6 @@ export const LocationPathInputField = forwardRef< >((props, ref) => { const platform = usePlatform(); const form = useFormContext(); - console.log(form.formState.isDirty); return (