feat: make shortcuts easier to add across the app
This commit is contained in:
@@ -107,13 +107,20 @@ const handleKeyDown = async (event: KeyboardEvent) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleWindowKeyDown = async (event: KeyboardEvent) => {
|
const handleWindowKeyDown = async (event: KeyboardEvent) => {
|
||||||
if (event.ctrlKey || event.metaKey) {
|
if (event.defaultPrevented) return;
|
||||||
return;
|
if (event.ctrlKey || event.metaKey || event.altKey) return;
|
||||||
}
|
|
||||||
|
|
||||||
if (document.activeElement === document.body) {
|
if (document.activeElement === document.body) {
|
||||||
// redirect all standard keyboard input to the input field
|
const isPrintable = event.key.length === 1;
|
||||||
|
|
||||||
|
if (isPrintable) {
|
||||||
inputRef.value?.focus();
|
inputRef.value?.focus();
|
||||||
|
} else if (event.key === 'Enter') {
|
||||||
|
event.preventDefault();
|
||||||
|
handleSubmit();
|
||||||
|
inputRef.value?.focus();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,12 @@ import Settings from './Settings.vue';
|
|||||||
|
|
||||||
import { DialogType } from '~/composables/useDialog';
|
import { DialogType } from '~/composables/useDialog';
|
||||||
|
|
||||||
const { open, page, data, close, confirm } = useDialog();
|
const { open, page, data, close, confirm, openDialog } = useDialog();
|
||||||
|
const { addShortcut } = useKeyboardShortcuts();
|
||||||
|
|
||||||
|
const unbindShortcut = addShortcut(['ctrl', ','], () => {
|
||||||
|
openDialog(DialogType.Settings);
|
||||||
|
});
|
||||||
|
|
||||||
const handleKeyDown = (event: KeyboardEvent) => {
|
const handleKeyDown = (event: KeyboardEvent) => {
|
||||||
if (event.key === 'Escape') {
|
if (event.key === 'Escape') {
|
||||||
@@ -24,6 +29,7 @@ onUnmounted(() => {
|
|||||||
if (open.value) {
|
if (open.value) {
|
||||||
document.body.removeEventListener('keydown', handleKeyDown);
|
document.body.removeEventListener('keydown', handleKeyDown);
|
||||||
}
|
}
|
||||||
|
unbindShortcut();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,41 @@
|
|||||||
export const useKeyboardShortcuts = () => {
|
export const useKeyboardShortcuts = () => {
|
||||||
const { toggle: toggleSidebar } = useSidebar();
|
const shortcutsMap = new Map<string, () => void>();
|
||||||
const { toggle: openSettings, open: isSettingsOpen } = useSettings();
|
|
||||||
|
const normalize = (combo: string[]) =>
|
||||||
|
combo.map(k => k.toLowerCase()).sort().join('+');
|
||||||
|
|
||||||
|
const addShortcut = (combo: string[], callback: () => void) => {
|
||||||
|
const normalizedKey = normalize(combo);
|
||||||
|
shortcutsMap.set(normalizedKey, callback);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
shortcutsMap.delete(normalizedKey);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const handleKeyDown = (event: KeyboardEvent) => {
|
const handleKeyDown = (event: KeyboardEvent) => {
|
||||||
// Ctrl+[ to collapse sidebar
|
const isInput = ['INPUT', 'TEXTAREA'].includes((event.target as HTMLElement).tagName);
|
||||||
if (event.ctrlKey && event.key === '[') {
|
if (isInput && !event.ctrlKey && !event.metaKey && event.key !== 'Escape') {
|
||||||
event.preventDefault();
|
|
||||||
toggleSidebar();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.ctrlKey && event.key === ',') {
|
const keys: string[] = [];
|
||||||
event.preventDefault();
|
if (event.ctrlKey) keys.push('ctrl');
|
||||||
if (isSettingsOpen.value) {
|
if (event.metaKey) keys.push('meta');
|
||||||
return;
|
if (event.shiftKey) keys.push('shift');
|
||||||
|
if (event.altKey) keys.push('alt');
|
||||||
|
|
||||||
|
const mainKey = event.key.toLowerCase();
|
||||||
|
if (!['control', 'shift', 'meta', 'alt'].includes(mainKey)) {
|
||||||
|
keys.push(mainKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
openSettings();
|
const pressedCombo = normalize(keys);
|
||||||
return;
|
|
||||||
|
if (shortcutsMap.has(pressedCombo)) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
shortcutsMap.get(pressedCombo)!();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -30,6 +48,7 @@ export const useKeyboardShortcuts = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
addShortcut,
|
||||||
handleKeyDown,
|
handleKeyDown,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,14 +2,18 @@
|
|||||||
import Dialog from '~/components/Dialog/index.vue';
|
import Dialog from '~/components/Dialog/index.vue';
|
||||||
|
|
||||||
const { colorScheme } = await useUserSettings();
|
const { colorScheme } = await useUserSettings();
|
||||||
|
const { toggle: toggleSidebar } = useSidebar();
|
||||||
|
const { addShortcut } = useKeyboardShortcuts();
|
||||||
|
|
||||||
|
addShortcut(['ctrl', '['], () => {
|
||||||
|
toggleSidebar();
|
||||||
|
});
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
htmlAttrs: {
|
htmlAttrs: {
|
||||||
class: colorScheme.class
|
class: colorScheme.class
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
useKeyboardShortcuts();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
Reference in New Issue
Block a user