diff options
| -rw-r--r-- | ext/fg/js/float.js | 15 | ||||
| -rw-r--r-- | ext/mixed/js/display.js | 178 | 
2 files changed, 77 insertions, 116 deletions
| diff --git a/ext/fg/js/float.js b/ext/fg/js/float.js index 17af03d3..2debdeff 100644 --- a/ext/fg/js/float.js +++ b/ext/fg/js/float.js @@ -40,14 +40,11 @@ class DisplayFloat extends Display {              ['setContentScale',    {handler: this._onMessageSetContentScale.bind(this)}]          ]); -        this.setOnKeyDownHandlers([ -            ['C', (e) => { -                if (e.ctrlKey && !window.getSelection().toString()) { -                    this._copySelection(); -                    return true; -                } -                return false; -            }] +        this.registerActions([ +            ['copy-host-selection', () => this._copySelection()] +        ]); +        this.registerHotkeys([ +            {key: 'C', modifiers: ['ctrl'], action: 'copy-host-selection'}          ]);      } @@ -168,7 +165,9 @@ class DisplayFloat extends Display {      // Private      _copySelection() { +        if (window.getSelection().toString()) { return false; }          this._invoke('copySelection'); +        return true;      }      _clearAutoPlayTimer() { diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index 2ab1b871..7dc63e65 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -56,108 +56,40 @@ class Display {          this._mediaLoader = new MediaLoader();          this._displayGenerator = new DisplayGenerator({mediaLoader: this._mediaLoader});          this._windowScroll = new WindowScroll(); -        this._onKeyDownHandlers = new Map([ -            ['Escape', () => { -                this.onEscape(); -                return true; -            }], -            ['PageUp', (e) => { -                if (e.altKey) { -                    this._entryScrollIntoView(this._index - 3, null, true); -                    return true; -                } -                return false; -            }], -            ['PageDown', (e) => { -                if (e.altKey) { -                    this._entryScrollIntoView(this._index + 3, null, true); -                    return true; -                } -                return false; -            }], -            ['End', (e) => { -                if (e.altKey) { -                    this._entryScrollIntoView(this._definitions.length - 1, null, true); -                    return true; -                } -                return false; -            }], -            ['Home', (e) => { -                if (e.altKey) { -                    this._entryScrollIntoView(0, null, true); -                    return true; -                } -                return false; -            }], -            ['ArrowUp', (e) => { -                if (e.altKey) { -                    this._entryScrollIntoView(this._index - 1, null, true); -                    return true; -                } -                return false; -            }], -            ['ArrowDown', (e) => { -                if (e.altKey) { -                    this._entryScrollIntoView(this._index + 1, null, true); -                    return true; -                } -                return false; -            }], -            ['B', (e) => { -                if (e.altKey) { -                    this._sourceTermView(); -                    return true; -                } -                return false; -            }], -            ['F', (e) => { -                if (e.altKey) { -                    this._nextTermView(); -                    return true; -                } -                return false; -            }], -            ['E', (e) => { -                if (e.altKey) { -                    this._noteTryAdd('term-kanji'); -                    return true; -                } -                return false; -            }], -            ['K', (e) => { -                if (e.altKey) { -                    this._noteTryAdd('kanji'); -                    return true; -                } -                return false; -            }], -            ['R', (e) => { -                if (e.altKey) { -                    this._noteTryAdd('term-kana'); -                    return true; -                } -                return false; -            }], -            ['P', (e) => { -                if (e.altKey) { -                    const index = this._index; -                    if (index < 0 || index >= this._definitions.length) { return; } - -                    const entry = this._getEntry(index); -                    if (entry !== null && entry.dataset.type === 'term') { -                        this._audioPlay(this._definitions[index], this._getFirstExpressionIndex(), index); -                    } -                    return true; -                } -                return false; -            }], -            ['V', (e) => { -                if (e.altKey) { -                    this._noteTryView(); -                    return true; -                } -                return false; -            }] +        this._hotkeys = new Map(); +        this._actions = new Map(); + +        this.registerActions([ +            ['close',               () => { this.onEscape(); }], +            ['next-entry',          () => { this._entryScrollIntoView(this._index + 1, null, true); }], +            ['next-entry-x3',       () => { this._entryScrollIntoView(this._index + 3, null, true); }], +            ['previous-entry',      () => { this._entryScrollIntoView(this._index - 1, null, true); }], +            ['previous-entry-x3',   () => { this._entryScrollIntoView(this._index - 3, null, true); }], +            ['last-entry',          () => { this._entryScrollIntoView(this._definitions.length - 1, null, true); }], +            ['first-entry',         () => { this._entryScrollIntoView(0, null, true); }], +            ['history-backward',    () => { this._sourceTermView(); }], +            ['history-forward',     () => { this._nextTermView(); }], +            ['add-note-kanji',      () => { this._noteTryAdd('kanji'); }], +            ['add-note-term-kanji', () => { this._noteTryAdd('term-kanji'); }], +            ['add-note-term-kana',  () => { this._noteTryAdd('term-kana'); }], +            ['view-note',           () => { this._noteTryView(); }], +            ['play-audio',          () => { this._playAudioCurrent(); }] +        ]); +        this.registerHotkeys([ +            {key: 'Escape',    modifiers: [],      action: 'close'}, +            {key: 'PageUp',    modifiers: ['alt'], action: 'previous-entry-x3'}, +            {key: 'PageDown',  modifiers: ['alt'], action: 'next-entry-x3'}, +            {key: 'End',       modifiers: ['alt'], action: 'last-entry'}, +            {key: 'Home',      modifiers: ['alt'], action: 'first-entry'}, +            {key: 'ArrowUp',   modifiers: ['alt'], action: 'previous-entry'}, +            {key: 'ArrowDown', modifiers: ['alt'], action: 'next-entry'}, +            {key: 'B',         modifiers: ['alt'], action: 'history-backward'}, +            {key: 'F',         modifiers: ['alt'], action: 'history-forward'}, +            {key: 'K',         modifiers: ['alt'], action: 'add-note-kanji'}, +            {key: 'E',         modifiers: ['alt'], action: 'add-note-term-kanji'}, +            {key: 'R',         modifiers: ['alt'], action: 'add-note-term-kana'}, +            {key: 'P',         modifiers: ['alt'], action: 'play-audio'}, +            {key: 'V',         modifiers: ['alt'], action: 'view-note'}          ]);      } @@ -181,9 +113,18 @@ class Display {      onKeyDown(e) {          const key = DOM.getKeyFromEvent(e); -        const handler = this._onKeyDownHandlers.get(key); -        if (typeof handler === 'function') { -            if (handler(e)) { +        const handlers = this._hotkeys.get(key); +        if (typeof handlers === 'undefined') { return false; } + +        const eventModifiers = DOM.getActiveModifiers(e); +        for (const {modifiers, action} of handlers) { +            if (getSetDifference(modifiers, eventModifiers).size !== 0) { continue; } + +            const actionHandler = this._actions.get(action); +            if (typeof actionHandler === 'undefined') { continue; } + +            const result = actionHandler(e); +            if (result !== false) {                  e.preventDefault();                  return true;              } @@ -276,9 +217,20 @@ class Display {          }      } -    setOnKeyDownHandlers(handlers) { -        for (const [key, handler] of handlers) { -            this._onKeyDownHandlers.set(key, handler); +    registerActions(actions) { +        for (const [name, handler] of actions) { +            this._actions.set(name, handler); +        } +    } + +    registerHotkeys(hotkeys) { +        for (const {key, modifiers, action} of hotkeys) { +            let handlers = this._hotkeys.get(key); +            if (typeof handlers === 'undefined') { +                handlers = []; +                this._hotkeys.set(key, handlers); +            } +            handlers.push({modifiers: new Set(modifiers), action});          }      } @@ -982,4 +934,14 @@ class Display {              }          };      } + +    _playAudioCurrent() { +        const index = this._index; +        if (index < 0 || index >= this._definitions.length) { return; } + +        const entry = this._getEntry(index); +        if (entry !== null && entry.dataset.type === 'term') { +            this._audioPlay(this._definitions[index], this._getFirstExpressionIndex(), index); +        } +    }  } |