diff options
Diffstat (limited to 'src/content')
-rw-r--r-- | src/content/client/OperationClient.ts | 6 | ||||
-rw-r--r-- | src/content/controllers/KeymapController.ts | 83 | ||||
-rw-r--r-- | src/content/usecases/KeymapUseCase.ts | 12 |
3 files changed, 49 insertions, 52 deletions
diff --git a/src/content/client/OperationClient.ts b/src/content/client/OperationClient.ts index 5dbe555..06077dc 100644 --- a/src/content/client/OperationClient.ts +++ b/src/content/client/OperationClient.ts @@ -2,7 +2,7 @@ import * as operations from '../../shared/operations'; import * as messages from '../../shared/messages'; export default interface OperationClient { - execBackgroundOp(op: operations.Operation): Promise<void>; + execBackgroundOp(count: number, op: operations.Operation): Promise<void>; internalOpenUrl( url: string, newTab?: boolean, background?: boolean, @@ -10,9 +10,10 @@ export default interface OperationClient { } export class OperationClientImpl implements OperationClient { - execBackgroundOp(op: operations.Operation): Promise<void> { + execBackgroundOp(count: number, op: operations.Operation): Promise<void> { return browser.runtime.sendMessage({ type: messages.BACKGROUND_OPERATION, + count, operation: op, }); } @@ -22,6 +23,7 @@ export class OperationClientImpl implements OperationClient { ): Promise<void> { return browser.runtime.sendMessage({ type: messages.BACKGROUND_OPERATION, + count: 1, operation: { type: operations.INTERNAL_OPEN_URL, url, diff --git a/src/content/controllers/KeymapController.ts b/src/content/controllers/KeymapController.ts index cf59ae5..b8069f9 100644 --- a/src/content/controllers/KeymapController.ts +++ b/src/content/controllers/KeymapController.ts @@ -23,7 +23,7 @@ export default class KeymapController { private markKeyUseCase: MarkKeyyUseCase, @inject('OperationClient') - private backgroundClient: OperationClient, + private operationClient: OperationClient, @inject('FollowMasterClient') private followMasterClient: FollowMasterClient, @@ -32,74 +32,69 @@ export default class KeymapController { // eslint-disable-next-line complexity, max-lines-per-function press(key: Key): boolean { - let ops = this.keymapUseCase.nextOps(key); - if (ops.length === 0) { + let nextOp = this.keymapUseCase.nextOps(key); + if (nextOp === null) { return false; } - // 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. - for (let op of ops) { + if (!operations.isNRepeatable(nextOp.op.type)) { + nextOp.count = 1; + } + + const doFunc = ((op: operations.Operation) => { switch (op.type) { case operations.ADDON_ENABLE: - this.addonEnabledUseCase.enable(); - break; + return () => this.addonEnabledUseCase.enable(); case operations.ADDON_DISABLE: - this.addonEnabledUseCase.disable(); - break; + return () => this.addonEnabledUseCase.disable(); case operations.ADDON_TOGGLE_ENABLED: - this.addonEnabledUseCase.toggle(); - break; + return () => this.addonEnabledUseCase.toggle(); case operations.FIND_NEXT: - this.findSlaveUseCase.findNext(); - break; + return () => this.findSlaveUseCase.findNext(); case operations.FIND_PREV: - this.findSlaveUseCase.findPrev(); - break; + return () => this.findSlaveUseCase.findPrev(); case operations.SCROLL_VERTICALLY: - this.scrollUseCase.scrollVertically(op.count); - break; + return () => this.scrollUseCase.scrollVertically(op.count); case operations.SCROLL_HORIZONALLY: - this.scrollUseCase.scrollHorizonally(op.count); - break; + return () => this.scrollUseCase.scrollHorizonally(op.count); case operations.SCROLL_PAGES: - this.scrollUseCase.scrollPages(op.count); - break; + return () => this.scrollUseCase.scrollPages(op.count); case operations.SCROLL_TOP: - this.scrollUseCase.scrollToTop(); - break; + return () => this.scrollUseCase.scrollToTop(); case operations.SCROLL_BOTTOM: - this.scrollUseCase.scrollToBottom(); - break; + return () => this.scrollUseCase.scrollToBottom(); case operations.SCROLL_HOME: - this.scrollUseCase.scrollToHome(); - break; + return () => this.scrollUseCase.scrollToHome(); case operations.SCROLL_END: - this.scrollUseCase.scrollToEnd(); - break; + return () => this.scrollUseCase.scrollToEnd(); case operations.FOLLOW_START: - this.followMasterClient.startFollow(op.newTab, op.background); - break; + return () => this.followMasterClient.startFollow( + op.newTab, op.background); case operations.MARK_SET_PREFIX: - this.markKeyUseCase.enableSetMode(); - break; + return () => this.markKeyUseCase.enableSetMode(); case operations.MARK_JUMP_PREFIX: - this.markKeyUseCase.enableJumpMode(); - break; + return () => this.markKeyUseCase.enableJumpMode(); case operations.FOCUS_INPUT: - this.focusUseCase.focusFirstInput(); - break; + return () => this.focusUseCase.focusFirstInput(); case operations.URLS_YANK: - this.clipbaordUseCase.yankCurrentURL(); - break; + return () => this.clipbaordUseCase.yankCurrentURL(); case operations.URLS_PASTE: - this.clipbaordUseCase.openOrSearch( + return () => this.clipbaordUseCase.openOrSearch( op.newTab ? op.newTab : false, ); - break; default: - this.backgroundClient.execBackgroundOp(op); + 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.count, nextOp.op); + } else { + for (let i = 0; i < nextOp.count; ++i) { + doFunc(); } } return true; diff --git a/src/content/usecases/KeymapUseCase.ts b/src/content/usecases/KeymapUseCase.ts index f7de334..fab13f5 100644 --- a/src/content/usecases/KeymapUseCase.ts +++ b/src/content/usecases/KeymapUseCase.ts @@ -36,13 +36,13 @@ export default class KeymapUseCase { } // eslint-disable-next-line max-statements - nextOps(key: Key): operations.Operation[] { + nextOps(key: Key): { count: number, op: operations.Operation } | null { let sequence = this.repository.enqueueKey(key); let baseSequence = sequence.trimNumericPrefix(); if (baseSequence.length() === 1 && this.blacklistKey(key)) { // ignore if the input starts with black list keys this.repository.clear(); - return []; + return null; } let keymaps = this.keymapEntityMap(); @@ -53,21 +53,21 @@ export default class KeymapUseCase { sequence.length() === matched[0][0].length()) { // keys are matched with an operation this.repository.clear(); - return [matched[0][1]]; + return { count: 1, op: matched[0][1] }; } else if ( baseMatched.length === 1 && baseSequence.length() === baseMatched[0][0].length()) { // keys are matched with an operation with a numeric prefix this.repository.clear(); - return Array(sequence.repeatCount()).fill(baseMatched[0][1]); + return { count: sequence.repeatCount(), op: baseMatched[0][1] }; } else if (matched.length >= 1 || baseMatched.length >= 1) { // keys are matched with an operation's prefix - return []; + return null; } // matched with no operations this.repository.clear(); - return []; + return null; } private keymapEntityMap(): [KeySequence, operations.Operation][] { |