import { injectable, inject } from 'tsyringe'; import * as operations from '../../shared/operations'; import KeymapUseCase from '../usecases/KeymapUseCase'; import AddonEnabledUseCase from '../usecases/AddonEnabledUseCase'; import FindSlaveUseCase from '../usecases/FindSlaveUseCase'; import ScrollUseCase from '../usecases/ScrollUseCase'; import FocusUseCase from '../usecases/FocusUseCase'; import ClipboardUseCase from '../usecases/ClipboardUseCase'; import OperationClient from '../client/OperationClient'; import MarkKeyyUseCase from '../usecases/MarkKeyUseCase'; import FollowMasterClient from '../client/FollowMasterClient'; import Key from '../../shared/settings/Key'; @injectable() export default class KeymapController { constructor( private keymapUseCase: KeymapUseCase, private addonEnabledUseCase: AddonEnabledUseCase, private findSlaveUseCase: FindSlaveUseCase, private scrollUseCase: ScrollUseCase, private focusUseCase: FocusUseCase, private clipbaordUseCase: ClipboardUseCase, private markKeyUseCase: MarkKeyyUseCase, @inject('OperationClient') private operationClient: OperationClient, @inject('FollowMasterClient') private followMasterClient: FollowMasterClient, ) { } // eslint-disable-next-line complexity, max-lines-per-function press(key: Key): boolean { const nextOp = this.keymapUseCase.nextOps(key); if (nextOp === null) { return false; } if (!operations.isNRepeatable(nextOp.op.type)) { nextOp.repeat = 1; } const doFunc = ((op: operations.Operation) => { switch (op.type) { case operations.ADDON_ENABLE: return () => this.addonEnabledUseCase.enable(); case operations.ADDON_DISABLE: return () => this.addonEnabledUseCase.disable(); case operations.ADDON_TOGGLE_ENABLED: return () => this.addonEnabledUseCase.toggle(); case operations.FIND_NEXT: return () => this.findSlaveUseCase.findNext(); case operations.FIND_PREV: return () => this.findSlaveUseCase.findPrev(); case operations.SCROLL_VERTICALLY: return () => this.scrollUseCase.scrollVertically(op.count); case operations.SCROLL_HORIZONALLY: return () => this.scrollUseCase.scrollHorizonally(op.count); case operations.SCROLL_PAGES: return () => this.scrollUseCase.scrollPages(op.count); case operations.SCROLL_TOP: return () => this.scrollUseCase.scrollToTop(); case operations.SCROLL_BOTTOM: return () => this.scrollUseCase.scrollToBottom(); case operations.SCROLL_HOME: return () => this.scrollUseCase.scrollToHome(); case operations.SCROLL_END: return () => this.scrollUseCase.scrollToEnd(); case operations.FOLLOW_START: return () => this.followMasterClient.startFollow( op.newTab, op.background); case operations.MARK_SET_PREFIX: return () => this.markKeyUseCase.enableSetMode(); case operations.MARK_JUMP_PREFIX: return () => this.markKeyUseCase.enableJumpMode(); case operations.FOCUS_INPUT: return () => this.focusUseCase.focusFirstInput(); case operations.URLS_YANK: return () => this.clipbaordUseCase.yankCurrentURL(); case operations.URLS_PASTE: return () => this.clipbaordUseCase.openOrSearch( op.newTab ? op.newTab : false, ); default: return null; } })(nextOp.op); if (doFunc === null) { // Do not await asynchronous methods to return a boolean immidiately. The // caller requires the synchronous response from the callback to identify // to continue of abandon the event propagations. this.operationClient.execBackgroundOp(nextOp.repeat, nextOp.op); } else { for (let i = 0; i < nextOp.repeat; ++i) { doFunc(); } } return true; } onBlurWindow() { this.keymapUseCase.cancel(); } }