mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-14 08:54:04 +00:00
[ENG-1126] Key matcher hook (#1358)
* key matcher hook * Update TopBarOptions.tsx
This commit is contained in:
parent
0382a4e48f
commit
d0dd8d11ec
|
@ -11,8 +11,7 @@ import {
|
|||
import clsx from 'clsx';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useRspcLibraryContext } from '@sd/client';
|
||||
import { ModifierKeys, modifierSymbols } from '@sd/ui';
|
||||
import { useOperatingSystem } from '~/hooks';
|
||||
import { useKeyMatcher } from '~/hooks';
|
||||
|
||||
import { KeyManager } from '../KeyManager';
|
||||
import TopBarOptions, { ToolOption, TOP_BAR_ICON_STYLE } from '../TopBar/TopBarOptions';
|
||||
|
@ -24,15 +23,7 @@ import { useExplorerSearchParams } from './util';
|
|||
export const useExplorerTopBarOptions = () => {
|
||||
const explorerStore = useExplorerStore();
|
||||
const explorer = useExplorerContext();
|
||||
const os = useOperatingSystem();
|
||||
const controlSymbol = (letter: string) => {
|
||||
return [
|
||||
os === 'macOS'
|
||||
? modifierSymbols[ModifierKeys.Meta][os]
|
||||
: modifierSymbols[ModifierKeys.Control]['Other'],
|
||||
letter
|
||||
] as string[];
|
||||
};
|
||||
const controlIcon = useKeyMatcher('Meta').icon;
|
||||
|
||||
const settings = explorer.useSettingsSnapshot();
|
||||
|
||||
|
@ -40,7 +31,7 @@ export const useExplorerTopBarOptions = () => {
|
|||
{
|
||||
toolTipLabel: 'Grid view',
|
||||
icon: <SquaresFour className={TOP_BAR_ICON_STYLE} />,
|
||||
keybinds: controlSymbol('V'),
|
||||
keybinds: [controlIcon, 'V'],
|
||||
topBarActive: settings.layoutMode === 'grid',
|
||||
onClick: () => (explorer.settingsStore.layoutMode = 'grid'),
|
||||
showAtResolution: 'sm:flex'
|
||||
|
@ -48,7 +39,7 @@ export const useExplorerTopBarOptions = () => {
|
|||
{
|
||||
toolTipLabel: 'List view',
|
||||
icon: <Rows className={TOP_BAR_ICON_STYLE} />,
|
||||
keybinds: controlSymbol('V'),
|
||||
keybinds: [controlIcon, 'V'],
|
||||
topBarActive: settings.layoutMode === 'list',
|
||||
onClick: () => (explorer.settingsStore.layoutMode = 'list'),
|
||||
showAtResolution: 'sm:flex'
|
||||
|
@ -63,7 +54,7 @@ export const useExplorerTopBarOptions = () => {
|
|||
{
|
||||
toolTipLabel: 'Media view',
|
||||
icon: <MonitorPlay className={TOP_BAR_ICON_STYLE} />,
|
||||
keybinds: controlSymbol('V'),
|
||||
keybinds: [controlIcon, 'V'],
|
||||
topBarActive: settings.layoutMode === 'media',
|
||||
onClick: () => (explorer.settingsStore.layoutMode = 'media'),
|
||||
showAtResolution: 'sm:flex'
|
||||
|
@ -80,7 +71,7 @@ export const useExplorerTopBarOptions = () => {
|
|||
},
|
||||
{
|
||||
toolTipLabel: 'Show Inspector',
|
||||
keybinds: controlSymbol('I'),
|
||||
keybinds: [controlIcon, 'I'],
|
||||
onClick: () => (getExplorerStore().showInspector = !explorerStore.showInspector),
|
||||
icon: (
|
||||
<SidebarSimple
|
||||
|
|
|
@ -27,7 +27,7 @@ import {
|
|||
} from '@sd/client';
|
||||
import { ContextMenu, dialogManager, ModifierKeys, toast } from '@sd/ui';
|
||||
import { Loader } from '~/components';
|
||||
import { useOperatingSystem } from '~/hooks';
|
||||
import { useKeyMatcher, useOperatingSystem } from '~/hooks';
|
||||
import { isNonEmpty } from '~/util';
|
||||
import { usePlatform } from '~/util/Platform';
|
||||
|
||||
|
@ -54,10 +54,9 @@ export const ViewItem = ({ data, children, ...props }: ViewItemProps) => {
|
|||
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;
|
||||
const metaCtrlKey = useKeyMatcher('Meta').key;
|
||||
|
||||
useKeys([metaCtrlKey, 'ArrowUp'], async (e) => {
|
||||
e.stopPropagation();
|
||||
|
@ -287,7 +286,7 @@ export const EmptyNotice = (props: { icon?: Icon | ReactNode; message?: ReactNod
|
|||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center h-full text-ink-faint">
|
||||
<div className="flex h-full flex-col items-center justify-center text-ink-faint">
|
||||
{props.icon
|
||||
? isValidElement(props.icon)
|
||||
? props.icon
|
||||
|
|
|
@ -1,16 +1,8 @@
|
|||
import { Gear } from '@phosphor-icons/react';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { JobManagerContextProvider, useClientContext, useDebugState } from '@sd/client';
|
||||
import {
|
||||
Button,
|
||||
ButtonLink,
|
||||
dialogManager,
|
||||
ModifierKeys,
|
||||
modifierSymbols,
|
||||
Popover,
|
||||
Tooltip
|
||||
} from '@sd/ui';
|
||||
import { useKeyBind, useOperatingSystem } from '~/hooks';
|
||||
import { Button, ButtonLink, dialogManager, ModifierKeys, Popover, Tooltip } from '@sd/ui';
|
||||
import { useKeyBind, useKeyMatcher, useOperatingSystem } from '~/hooks';
|
||||
|
||||
import DebugPopover from './DebugPopover';
|
||||
import FeedbackDialog from './FeedbackDialog';
|
||||
|
@ -22,10 +14,6 @@ export default () => {
|
|||
const os = useOperatingSystem();
|
||||
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();
|
||||
|
@ -34,7 +22,7 @@ export default () => {
|
|||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center justify-between w-full">
|
||||
<div className="flex w-full items-center justify-between">
|
||||
<div className="flex">
|
||||
<ButtonLink
|
||||
to="settings/client/general"
|
||||
|
@ -43,7 +31,7 @@ export default () => {
|
|||
className="text-sidebar-inkFaint ring-offset-sidebar"
|
||||
>
|
||||
<Tooltip label="Settings" keybinds={['G', 'S']}>
|
||||
<Gear className="w-5 h-5" />
|
||||
<Gear className="h-5 w-5" />
|
||||
</Tooltip>
|
||||
</ButtonLink>
|
||||
<JobManagerContextProvider>
|
||||
|
@ -59,7 +47,7 @@ export default () => {
|
|||
{library && (
|
||||
<Tooltip
|
||||
label="Recent Jobs"
|
||||
keybinds={[recentJobsSymbol as string, 'J']}
|
||||
keybinds={[useKeyMatcher('Meta').icon, 'J']}
|
||||
>
|
||||
<IsRunningJob />
|
||||
</Tooltip>
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { ArrowLeft, ArrowRight } from '@phosphor-icons/react';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { ModifierKeys, Tooltip } from '@sd/ui';
|
||||
import { useOperatingSystem, useSearchStore } from '~/hooks';
|
||||
import { keybindForOs } from '~/util/keybinds';
|
||||
import { Tooltip } from '@sd/ui';
|
||||
import { useKeyMatcher, useSearchStore } from '~/hooks';
|
||||
|
||||
import TopBarButton from './TopBarButton';
|
||||
|
||||
|
@ -10,12 +9,11 @@ export const NavigationButtons = () => {
|
|||
const navigate = useNavigate();
|
||||
const { isFocused } = useSearchStore();
|
||||
const idx = history.state.idx as number;
|
||||
const os = useOperatingSystem();
|
||||
const keybind = keybindForOs(os);
|
||||
const controlIcon = useKeyMatcher('Meta').icon;
|
||||
|
||||
return (
|
||||
<div data-tauri-drag-region className="flex">
|
||||
<Tooltip keybinds={[keybind([ModifierKeys.Control], ['←'])]} label="Navigate back">
|
||||
<Tooltip keybinds={[controlIcon, '←']} label="Navigate back">
|
||||
<TopBarButton
|
||||
rounding="left"
|
||||
// className="text-[14px] text-ink-dull"
|
||||
|
@ -25,7 +23,7 @@ export const NavigationButtons = () => {
|
|||
<ArrowLeft size={14} className="m-[4px]" weight="bold" />
|
||||
</TopBarButton>
|
||||
</Tooltip>
|
||||
<Tooltip keybinds={[keybind([ModifierKeys.Control], ['→'])]} label="Navigate forward">
|
||||
<Tooltip keybinds={[controlIcon, '→']} label="Navigate forward">
|
||||
<TopBarButton
|
||||
rounding="right"
|
||||
// className="text-[14px] text-ink-dull"
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import clsx from 'clsx';
|
||||
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 { useKeyBind, useKeyMatcher } from '~/hooks';
|
||||
|
||||
import { useExplorerContext } from '../Explorer/Context';
|
||||
import TopBarButton from './TopBarButton';
|
||||
|
@ -34,10 +33,9 @@ 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'];
|
||||
const metaCtrlKey = useKeyMatcher('Meta').key;
|
||||
|
||||
useKeyBind(keys, (e) => {
|
||||
useKeyBind([metaCtrlKey, 'v'], (e) => {
|
||||
e.stopPropagation();
|
||||
const explorerLayouts: ExplorerLayout[] = ['grid', 'list', 'media']; //based on the order of the icons
|
||||
const currentLayout = explorerLayouts.indexOf(
|
||||
|
@ -59,7 +57,7 @@ export default ({ options }: TopBarChildrenProps) => {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<div data-tauri-drag-region className="flex justify-end flex-1">
|
||||
<div data-tauri-drag-region className="flex flex-1 justify-end">
|
||||
<div data-tauri-drag-region className={`flex gap-0`}>
|
||||
{options?.map((group, groupIndex) => {
|
||||
return group.map(
|
||||
|
|
|
@ -19,3 +19,4 @@ export * from './useTheme';
|
|||
export * from './useZodRouteParams';
|
||||
export * from './useZodSearchParams';
|
||||
export * from './useIsTextTruncated';
|
||||
export * from './useKeyMatcher';
|
||||
|
|
36
interface/hooks/useKeyMatcher.ts
Normal file
36
interface/hooks/useKeyMatcher.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
import { ModifierKeys, modifierSymbols } from "@sd/ui";
|
||||
import { OperatingSystem } from "..";
|
||||
import { useOperatingSystem } from "./useOperatingSystem";
|
||||
|
||||
type keysToMatch = 'Meta' | 'Alt'
|
||||
type keysOsMap = Record<keysToMatch,osKeys>
|
||||
type osKeys = Record<OperatingSystem, {key: Partial<keyof typeof ModifierKeys>, icon: string}>
|
||||
|
||||
//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') => {
|
||||
return modifierSymbols[key][os] ?? modifierSymbols[key]['Other'];
|
||||
}
|
||||
|
||||
//Match macOS keys to Windows keys and others
|
||||
const keysOsMap: keysOsMap = {
|
||||
'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') },
|
||||
},
|
||||
'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') },
|
||||
},
|
||||
} as const
|
||||
|
||||
export function useKeyMatcher(arg: keyof typeof keysOsMap): osKeys[OperatingSystem] {
|
||||
const os = useOperatingSystem();
|
||||
const key = keysOsMap[arg][os];
|
||||
return key;
|
||||
}
|
Loading…
Reference in a new issue