mirror of
https://github.com/immich-app/immich.git
synced 2025-01-28 00:59:18 -05:00
feat: "add to album" shortcut and generic menu option shortcuts (#15056)
* Add shortcut prop to MenuOption * Add "add to album" shortcut in photo grid
This commit is contained in:
parent
c148a28a82
commit
fa0b352bd0
3 changed files with 45 additions and 2 deletions
|
@ -16,6 +16,26 @@ export type ShortcutOptions<T = HTMLElement> = {
|
||||||
preventDefault?: boolean;
|
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:
|
/** 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 not the same as the element which the event listener is attached to
|
||||||
* - The element dispatching the event is an input field
|
* - The element dispatching the event is an input field
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
onClick={() => (showAlbumPicker = true)}
|
onClick={() => (showAlbumPicker = true)}
|
||||||
text={shared ? $t('add_to_shared_album') : $t('add_to_album')}
|
text={shared ? $t('add_to_shared_album') : $t('add_to_album')}
|
||||||
icon={shared ? mdiShareVariantOutline : mdiImageAlbum}
|
icon={shared ? mdiShareVariantOutline : mdiImageAlbum}
|
||||||
|
shortcut={{ key: 'l', shift: shared }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{#if showAlbumPicker}
|
{#if showAlbumPicker}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
import Icon from '$lib/components/elements/icon.svelte';
|
import Icon from '$lib/components/elements/icon.svelte';
|
||||||
import { generateId } from '$lib/utils/generate-id';
|
import { generateId } from '$lib/utils/generate-id';
|
||||||
import { optionClickCallbackStore, selectedIdStore } from '$lib/stores/context-menu.store';
|
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 {
|
interface Props {
|
||||||
text: string;
|
text: string;
|
||||||
|
@ -10,6 +12,8 @@
|
||||||
activeColor?: string;
|
activeColor?: string;
|
||||||
textColor?: string;
|
textColor?: string;
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
|
shortcut?: Shortcut | null;
|
||||||
|
shortcutLabel?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
let {
|
let {
|
||||||
|
@ -19,6 +23,8 @@
|
||||||
activeColor = 'bg-slate-300',
|
activeColor = 'bg-slate-300',
|
||||||
textColor = 'text-immich-fg dark:text-immich-dark-bg',
|
textColor = 'text-immich-fg dark:text-immich-dark-bg',
|
||||||
onClick,
|
onClick,
|
||||||
|
shortcut = null,
|
||||||
|
shortcutLabel = '',
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
let id: string = generateId();
|
let id: string = generateId();
|
||||||
|
@ -29,8 +35,17 @@
|
||||||
$optionClickCallbackStore?.();
|
$optionClickCallbackStore?.();
|
||||||
onClick();
|
onClick();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (shortcut && !shortcutLabel) {
|
||||||
|
shortcutLabel = computeShortcutLabel(shortcut);
|
||||||
|
}
|
||||||
|
const bindShortcutIfSet = shortcut
|
||||||
|
? (n: HTMLElement) => bindShortcut(n, { shortcut, onShortcut: onClick })
|
||||||
|
: () => {};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<svelte:window use:bindShortcutIfSet />
|
||||||
|
|
||||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||||
<!-- svelte-ignore a11y_mouse_events_have_key_events -->
|
<!-- svelte-ignore a11y_mouse_events_have_key_events -->
|
||||||
<li
|
<li
|
||||||
|
@ -46,8 +61,15 @@
|
||||||
{#if icon}
|
{#if icon}
|
||||||
<Icon path={icon} ariaHidden={true} size="18" />
|
<Icon path={icon} ariaHidden={true} size="18" />
|
||||||
{/if}
|
{/if}
|
||||||
<div>
|
<div class="w-full">
|
||||||
{text}
|
<div class="flex justify-between">
|
||||||
|
{text}
|
||||||
|
{#if shortcutLabel}
|
||||||
|
<span class="text-gray-500 pl-4">
|
||||||
|
{shortcutLabel}
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
{#if subtitle}
|
{#if subtitle}
|
||||||
<p class="text-xs text-gray-500">
|
<p class="text-xs text-gray-500">
|
||||||
{subtitle}
|
{subtitle}
|
||||||
|
|
Loading…
Add table
Reference in a new issue