diff --git a/web/src/lib/actions/shortcut.ts b/web/src/lib/actions/shortcut.ts index 6348257c40..f7b3009403 100644 --- a/web/src/lib/actions/shortcut.ts +++ b/web/src/lib/actions/shortcut.ts @@ -16,6 +16,26 @@ export type ShortcutOptions = { preventDefault?: boolean; }; +export const shortcutLabel = (shortcut: Shortcut) => { + let label = ''; + + if (shortcut.ctrl) { + label += 'Ctrl '; + } + if (shortcut.alt) { + label += 'Alt '; + } + if (shortcut.meta) { + label += 'Cmd '; + } + if (shortcut.shift) { + label += '⇧'; + } + label += shortcut.key.toUpperCase(); + + return label; +}; + /** Determines whether an event should be ignored. The event will be ignored if: * - The element dispatching the event is not the same as the element which the event listener is attached to * - The element dispatching the event is an input field diff --git a/web/src/lib/components/photos-page/actions/add-to-album.svelte b/web/src/lib/components/photos-page/actions/add-to-album.svelte index 10917a1d90..e62ca9fcfe 100644 --- a/web/src/lib/components/photos-page/actions/add-to-album.svelte +++ b/web/src/lib/components/photos-page/actions/add-to-album.svelte @@ -47,6 +47,7 @@ onClick={() => (showAlbumPicker = true)} text={shared ? $t('add_to_shared_album') : $t('add_to_album')} icon={shared ? mdiShareVariantOutline : mdiImageAlbum} + shortcut={{ key: 'l', shift: shared }} /> {#if showAlbumPicker} diff --git a/web/src/lib/components/shared-components/context-menu/menu-option.svelte b/web/src/lib/components/shared-components/context-menu/menu-option.svelte index 5d3c29dc3c..b3a6d41018 100644 --- a/web/src/lib/components/shared-components/context-menu/menu-option.svelte +++ b/web/src/lib/components/shared-components/context-menu/menu-option.svelte @@ -2,6 +2,8 @@ import Icon from '$lib/components/elements/icon.svelte'; import { generateId } from '$lib/utils/generate-id'; import { optionClickCallbackStore, selectedIdStore } from '$lib/stores/context-menu.store'; + import type { Shortcut } from '$lib/actions/shortcut'; + import { shortcutLabel as computeShortcutLabel, shortcut as bindShortcut } from '$lib/actions/shortcut'; interface Props { text: string; @@ -10,6 +12,8 @@ activeColor?: string; textColor?: string; onClick: () => void; + shortcut?: Shortcut | null; + shortcutLabel?: string; } let { @@ -19,6 +23,8 @@ activeColor = 'bg-slate-300', textColor = 'text-immich-fg dark:text-immich-dark-bg', onClick, + shortcut = null, + shortcutLabel = '', }: Props = $props(); let id: string = generateId(); @@ -29,8 +35,17 @@ $optionClickCallbackStore?.(); onClick(); }; + + if (shortcut && !shortcutLabel) { + shortcutLabel = computeShortcutLabel(shortcut); + } + const bindShortcutIfSet = shortcut + ? (n: HTMLElement) => bindShortcut(n, { shortcut, onShortcut: onClick }) + : () => {}; + +
  • {/if} -
    - {text} +
    +
    + {text} + {#if shortcutLabel} + + {shortcutLabel} + + {/if} +
    {#if subtitle}

    {subtitle}