2
0
mirror of https://github.com/frappe/books.git synced 2024-12-23 03:19:01 +00:00

incr: add mods to shortcut class

This commit is contained in:
18alantom 2023-01-20 16:31:09 +05:30
parent 384bc28ccd
commit 67f8879551
4 changed files with 98 additions and 31 deletions

View File

@ -55,7 +55,7 @@ import { checkForUpdates } from './utils/ipcCalls';
import { updateConfigFiles } from './utils/misc';
import { Search } from './utils/search';
import { routeTo, systemLanguage } from './utils/ui';
import { Shortcuts, useKeys } from './utils/vueUtils';
import { getModKeyCode, Shortcuts, useKeys } from './utils/vueUtils';
export default {
name: 'App',
@ -69,6 +69,7 @@ export default {
companyName: '',
searcher: null,
shortcuts: null,
modKey: '',
};
},
provide() {
@ -76,6 +77,7 @@ export default {
languageDirection: computed(() => this.languageDirection),
searcher: computed(() => this.searcher),
shortcuts: computed(() => this.shortcuts),
modKey: computed(() => this.modKey),
keys: computed(() => this.keys),
};
},
@ -86,6 +88,7 @@ export default {
WindowsTitleBar,
},
async mounted() {
this.modKey = getModKeyCode(this.platform);
this.shortcuts = new Shortcuts(this.keys);
const lastSelectedFilePath = fyo.config.get(
ConfigKeys.LastSelectedFilePath,

View File

@ -5,7 +5,7 @@
<feather-icon name="search" class="w-4 h-4 me-1 text-gray-800" />
<p>{{ t`Search` }}</p>
<div class="text-gray-500 px-1 ms-4 text-sm">
{{ modKey('k') }}
{{ modKeyText('k') }}
</div>
</Button>
</div>
@ -195,7 +195,6 @@ import { getBgTextColorClass } from 'src/utils/colors';
import { openLink } from 'src/utils/ipcCalls';
import { docsPathMap } from 'src/utils/misc';
import { getGroupLabelMap, searchGroups } from 'src/utils/search';
import { getModKeyCode } from 'src/utils/vueUtils';
import { nextTick } from 'vue';
import Button from './Button.vue';
import Modal from './Modal.vue';
@ -212,7 +211,7 @@ export default {
allowedLimits: [50, 100, 500, -1],
};
},
inject: ['searcher', 'shortcuts'],
inject: ['searcher', 'shortcuts', 'modKey'],
components: { Modal, Button },
async mounted() {
if (fyo.store.isDevelopment) {
@ -233,18 +232,20 @@ export default {
openLink('https://docs.frappebooks.com/' + docsPathMap.Search);
},
getShortcuts() {
const modKey = getModKeyCode(this.platform);
const ifOpen = (cb) => () => this.openModal && cb();
const ifClose = (cb) => () => !this.openModal && cb();
const shortcuts = [
{ shortcut: ['KeyK', modKey], callback: ifClose(() => this.open()) },
{
shortcut: ['KeyK', this.modKey],
callback: ifClose(() => this.open()),
},
{ shortcut: ['Escape'], callback: ifOpen(() => this.close()) },
];
for (const i in searchGroups) {
shortcuts.push({
shortcut: [modKey, `Digit${Number(i) + 1}`],
shortcut: [this.modKey, `Digit${Number(i) + 1}`],
callback: ifOpen(() => {
const group = searchGroups[i];
const value = this.searcher.filters.groupFilters[group];
@ -261,15 +262,15 @@ export default {
},
setShortcuts() {
for (const { shortcut, callback } of this.getShortcuts()) {
this.shortcuts.set(shortcut, callback);
this.shortcuts.meta.set(shortcut, callback);
}
},
deleteShortcuts() {
for (const { shortcut } of this.getShortcuts()) {
this.shortcuts.delete(shortcut);
this.shortcuts.meta.delete(shortcut);
}
},
modKey(key) {
modKeyText(key) {
key = key.toUpperCase();
if (this.platform === 'Mac') {
return `${key}`;

View File

@ -131,6 +131,7 @@ export default {
DropdownWithActions,
},
emits: ['close'],
inject: ['shortcuts'],
provide() {
return {
schemaName: this.schemaName,

View File

@ -1,7 +1,6 @@
import { onMounted, onUnmounted, Ref, ref, watch } from 'vue';
import { onMounted, onUnmounted, reactive, ref, unref, watch } from 'vue';
interface Keys {
pressed: Set<string>;
interface ModMap {
alt: boolean;
ctrl: boolean;
meta: boolean;
@ -9,11 +8,23 @@ interface Keys {
repeat: boolean;
}
export class Shortcuts {
keys: Ref<Keys>;
shortcuts: Map<string, Function>;
type Mod = keyof ModMap;
constructor(keys?: Ref<Keys>) {
interface Keys extends ModMap {
pressed: Set<string>;
}
type ShortcutFunction = () => void;
const mods: Readonly<Mod[]> = ['alt', 'ctrl', 'meta', 'repeat', 'shift'];
export class Shortcuts {
keys: Keys;
shortcuts: Map<string, ShortcutFunction>;
modMap: Partial<Record<Mod, boolean>>;
constructor(keys?: Keys) {
this.modMap = {};
this.keys = keys ?? useKeys();
this.shortcuts = new Map();
@ -23,17 +34,22 @@ export class Shortcuts {
}
#trigger(keys: Keys) {
const key = Array.from(keys.pressed).sort().join('+');
const key = this.getKey(Array.from(keys.pressed), keys);
this.shortcuts.get(key)?.();
}
has(shortcut: string[]) {
const key = shortcut.sort().join('+');
const key = this.getKey(shortcut);
return this.shortcuts.has(key);
}
set(shortcut: string[], callback: Function, removeIfSet: boolean = true) {
const key = shortcut.sort().join('+');
set(
shortcut: string[],
callback: ShortcutFunction,
removeIfSet: boolean = true
) {
const key = this.getKey(shortcut);
if (removeIfSet) {
this.shortcuts.delete(key);
}
@ -46,13 +62,59 @@ export class Shortcuts {
}
delete(shortcut: string[]) {
const key = shortcut.sort().join('+');
const key = this.getKey(shortcut);
this.shortcuts.delete(key);
}
getKey(shortcut: string[], modMap?: Partial<ModMap>): string {
const _modMap = modMap || this.modMap;
this.modMap = {};
const shortcutString = shortcut.sort().join('+');
const modString = mods.filter((k) => _modMap[k]).join('+');
if (shortcutString && modString) {
return modString + '+' + shortcutString;
}
if (!modString) {
return shortcutString;
}
if (!shortcutString) {
return modString;
}
return '';
}
get alt() {
this.modMap['alt'] = true;
return this;
}
get ctrl() {
this.modMap['ctrl'] = true;
return this;
}
get meta() {
this.modMap['meta'] = true;
return this;
}
get shift() {
this.modMap['shift'] = true;
return this;
}
get repeat() {
this.modMap['repeat'] = true;
return this;
}
}
export function useKeys() {
const keys: Ref<Keys> = ref({
const keys: Keys = reactive({
pressed: new Set<string>(),
alt: false,
ctrl: false,
@ -62,20 +124,20 @@ export function useKeys() {
});
const keydownListener = (e: KeyboardEvent) => {
keys.value.pressed.add(e.code);
keys.value.alt = e.altKey;
keys.value.ctrl = e.ctrlKey;
keys.value.meta = e.metaKey;
keys.value.shift = e.shiftKey;
keys.value.repeat = e.repeat;
keys.pressed.add(e.code);
keys.alt = e.altKey;
keys.ctrl = e.ctrlKey;
keys.meta = e.metaKey;
keys.shift = e.shiftKey;
keys.repeat = e.repeat;
};
const keyupListener = (e: KeyboardEvent) => {
keys.value.pressed.delete(e.code);
keys.pressed.delete(e.code);
// Key up won't trigger on macOS for other keys.
if (e.code === 'MetaLeft') {
keys.value.pressed.clear();
keys.pressed.clear();
}
};