Improved keyboard shortcuts handling

This commit is contained in:
djmaze 2021-08-13 10:03:13 +02:00
parent 5f21fcc100
commit 2a6a1ff799
7 changed files with 58 additions and 77 deletions

View file

@ -9,7 +9,7 @@ const
i18n = (str, def) => rl.i18n(str) || def,
ctrlKey = shortcuts.getMetaKey().replace('meta','⌘') + ' + ',
ctrlKey = shortcuts.getMetaKey() + ' + ',
tpl = doc.createElement('template'),
clr = doc.createElement('input'),

View file

@ -1213,8 +1213,8 @@ class ComposePopupView extends AbstractViewPopup {
shortcuts.add('q', 'meta', Scope.Compose, ()=>false);
shortcuts.add('w', 'meta', Scope.Compose, ()=>false);
shortcuts.add('m,contextmenu', '', Scope.Compose, e => this.popupMenu(e));
shortcuts.add('m', 'ctrl', Scope.Compose, e => this.popupMenu(e));
shortcuts.add('contextmenu', '', Scope.Compose, e => this.popupMenu(e));
shortcuts.add('m', 'meta', Scope.Compose, e => this.popupMenu(e));
shortcuts.add('escape,close', '', Scope.Compose, () => {
this.skipCommand();
@ -1229,7 +1229,7 @@ class ComposePopupView extends AbstractViewPopup {
this.saveCommand();
return false;
});
shortcuts.add('save', Scope.Compose, () => {
shortcuts.add('save', '', Scope.Compose, () => {
this.saveCommand();
return false;
});

View file

@ -2,9 +2,10 @@ import { Scope } from 'Common/Enums';
import { AbstractViewPopup } from 'Knoin/AbstractViews';
class KeyboardShortcutsHelpPopupView extends AbstractViewPopup {
export class KeyboardShortcutsHelpPopupView extends AbstractViewPopup {
constructor() {
super('KeyboardShortcutsHelp');
this.metaKey = shortcuts.getMetaKey();
}
onBuild(dom) {
@ -49,5 +50,3 @@ class KeyboardShortcutsHelpPopupView extends AbstractViewPopup {
);
}
}
export { KeyboardShortcutsHelpPopupView, KeyboardShortcutsHelpPopupView as default };

View file

@ -99,9 +99,8 @@ class PluginPopupView extends AbstractViewPopup {
shortcuts.add('escape', '', Scope.All, () => {
if (this.modalVisibility()) {
this.tryToClosePopup();
return false;
}
return false;
});
}
}

21
dev/bootstrap.js vendored
View file

@ -5,27 +5,6 @@ import { root } from 'Common/Links';
export default App => {
addEventListener('keydown', event => {
event = event || window.event;
if (event && event.ctrlKey && !event.shiftKey && !event.altKey) {
if ('S' == event.key) {
event.preventDefault();
} else if ('A' == event.key) {
const sender = event.target;
if (
sender &&
('true' === '' + sender.contentEditable || (sender.matches && sender.matches('INPUT,TEXTAREA')))
) {
return;
}
getSelection().removeAllRanges();
event.preventDefault();
}
}
});
addEventListener('click', ()=>rl.Dropdowns.detectVisibility());
rl.app = App;

View file

@ -1,20 +1,63 @@
(win => {
let
scope = {},
_scope = 'all';
const
doc = document,
// On Mac we use ⌘ else the Ctrl key
meta = /Mac OS X/.test(navigator.userAgent) ? 'meta' : 'ctrl',
_scopes = {
all: {}
},
toArray = v => Array.isArray(v) ? v : v.split(/\s*,\s*/),
// ignore keydown in any element that supports keyboard input
filter = node => !(!node.closest || node.closest('input,select,textarea,[contenteditable]')),
shortcuts = {
on: () => doc.addEventListener('keydown', keydown),
off: () => doc.removeEventListener('keydown', keydown),
add: (keys, modifiers, scopes, method) => {
if (method === undefined) {
method = scopes;
scopes = 'all';
}
toArray(scopes).forEach(scope => {
if (!_scopes[scope]) {
_scopes[scope] = {};
}
toArray(keys).forEach(key => {
key = key.toLowerCase();
if (!_scopes[scope][key]) {
_scopes[scope][key] = {};
}
modifiers = toArray(modifiers)
.map(key => 'meta' == key ? meta : key)
.unique().sort().join('+');
if (!_scopes[scope][key][modifiers]) {
_scopes[scope][key][modifiers] = [];
}
_scopes[scope][key][modifiers].push(method);
});
});
},
setScope: value => {
_scope = value || 'all';
scope = _scopes[_scope] || {};
},
getScope: () => _scope,
getMetaKey: () => 'meta' === meta ? '⌘' : 'Ctrl'
},
keydown = event => {
let key = (event.key || '').toLowerCase().replace(' ','space'),
scopes = [];
scope[key] && scopes.push(scope[key]);
_scope !== 'all' && _scopes.all[key] && scopes.push(_scopes.all[key]);
if (scopes.length && win.shortcuts.filter(event.target)) {
if (scopes.length && filter(event.target)) {
let modifiers = ['alt','ctrl','meta','shift'].filter(v => event[v+'Key']).join('+');
scopes.forEach(actions => {
// for each potential shortcut
@ -33,47 +76,8 @@ const
}
};
let
scope = {},
_scope = 'all';
win.shortcuts = shortcuts;
win.shortcuts = {
on: () => doc.addEventListener('keydown', keydown),
off: () => doc.removeEventListener('keydown', keydown),
add: (keys, modifiers, scopes, method) => {
if (method === undefined) {
method = scopes;
scopes = 'all';
}
toArray(scopes).forEach(scope => {
if (!_scopes[scope]) {
_scopes[scope] = {};
}
toArray(keys).forEach(key => {
key = key.toLowerCase();
if (!_scopes[scope][key]) {
_scopes[scope][key] = {};
}
modifiers = toArray(modifiers)
.map(key => 'meta' == key ? meta : key)
.unique().sort().join('+');
if (!_scopes[scope][key][modifiers]) {
_scopes[scope][key][modifiers] = [];
}
_scopes[scope][key][modifiers].push(method);
});
});
},
setScope: value => {
_scope = value || 'all';
scope = _scopes[_scope] || {};
},
getScope: () => _scope,
getMetaKey: () => meta,
// ignore keydown in any element that supports keyboard input
filter: node => !(!node.closest || node.closest('input,select,textarea,[contenteditable]'))
};
win.shortcuts.on();
shortcuts.on();
})(this);