diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/background/controllers/OperationController.ts | 2 | ||||
-rw-r--r-- | src/background/usecases/TabUseCase.ts | 6 | ||||
-rw-r--r-- | src/content/presenters/ScrollPresenter.ts | 2 | ||||
-rw-r--r-- | src/settings/keymaps.ts | 12 | ||||
-rw-r--r-- | src/shared/SettingData.ts | 3 | ||||
-rw-r--r-- | src/shared/Settings.ts | 3 | ||||
-rw-r--r-- | src/shared/operations.ts | 31 |
7 files changed, 42 insertions, 17 deletions
diff --git a/src/background/controllers/OperationController.ts b/src/background/controllers/OperationController.ts index 51cff28..7a10ad6 100644 --- a/src/background/controllers/OperationController.ts +++ b/src/background/controllers/OperationController.ts @@ -32,7 +32,7 @@ export default class OperationController { doOperation(operation: operations.Operation): Promise<any> { switch (operation.type) { case operations.TAB_CLOSE: - return this.tabUseCase.close(false); + return this.tabUseCase.close(false, operation.select === 'left'); case operations.TAB_CLOSE_RIGHT: return this.tabUseCase.closeRight(); case operations.TAB_CLOSE_FORCE: diff --git a/src/background/usecases/TabUseCase.ts b/src/background/usecases/TabUseCase.ts index 31112a9..386307e 100644 --- a/src/background/usecases/TabUseCase.ts +++ b/src/background/usecases/TabUseCase.ts @@ -12,11 +12,15 @@ export default class TabUseCase { ) { } - async close(force: boolean): Promise<any> { + async close(force: boolean, selectLeft = false): Promise<any> { let tab = await this.tabPresenter.getCurrent(); if (!force && tab.pinned) { return Promise.resolve(); } + if (selectLeft && tab.index > 0) { + let tabs = await this.tabPresenter.getAll(); + await this.tabPresenter.select(tabs[tab.index - 1].id as number); + } return this.tabPresenter.remove([tab.id as number]); } diff --git a/src/content/presenters/ScrollPresenter.ts b/src/content/presenters/ScrollPresenter.ts index c06efca..e83f172 100644 --- a/src/content/presenters/ScrollPresenter.ts +++ b/src/content/presenters/ScrollPresenter.ts @@ -90,7 +90,7 @@ class Scroller { clearTimeout(lastTimeoutId); lastTimeoutId = null; } - lastTimeoutId = setTimeout(resetScrolling, 100); + lastTimeoutId = window.setTimeout(resetScrolling, 100); } } diff --git a/src/settings/keymaps.ts b/src/settings/keymaps.ts index 33ad26d..24ba1a5 100644 --- a/src/settings/keymaps.ts +++ b/src/settings/keymaps.ts @@ -18,11 +18,11 @@ const fields = [ ['mark.set.prefix', 'Set mark at current position'], ['mark.jump.prefix', 'Jump to the mark'], ], [ - ['tabs.close', 'Close a tab'], - ['tabs.close.right', 'Close tabs to the right'], + ['tabs.close?{"select":"right"}', 'Close a tab'], + ['tabs.close.right', 'Close all tabs to the right'], ['tabs.reopen', 'Reopen closed tab'], - ['tabs.next', 'Select next Tab'], - ['tabs.prev', 'Select prev Tab'], + ['tabs.next', 'Select next tab'], + ['tabs.prev', 'Select prev tab'], ['tabs.first', 'Select first tab'], ['tabs.last', 'Select last tab'], ['tabs.reload?{"cache":false}', 'Reload current tab'], @@ -50,8 +50,8 @@ const fields = [ ['command.show', 'Open console'], ['command.show.open?{"alter":false}', 'Open URL'], ['command.show.open?{"alter":true}', 'Alter URL'], - ['command.show.tabopen?{"alter":false}', 'Open URL in new Tab'], - ['command.show.tabopen?{"alter":true}', 'Alter URL in new Tab'], + ['command.show.tabopen?{"alter":false}', 'Open URL in new tab'], + ['command.show.tabopen?{"alter":true}', 'Alter URL in new tab'], ['command.show.winopen?{"alter":false}', 'Open URL in new window'], ['command.show.winopen?{"alter":true}', 'Alter URL in new window'], ['command.show.buffer', 'Open buffer command'], diff --git a/src/shared/SettingData.ts b/src/shared/SettingData.ts index 1c085cf..14a7d35 100644 --- a/src/shared/SettingData.ts +++ b/src/shared/SettingData.ts @@ -353,7 +353,8 @@ export const DefaultSettingData: SettingData = SettingData.valueOf({ "G": { "type": "scroll.bottom" }, "$": { "type": "scroll.end" }, "d": { "type": "tabs.close" }, - "D": { "type": "tabs.close.right" }, + "D": { "type": "tabs.close", "select": "left" }, + "x$": { "type": "tabs.close.right" }, "!d": { "type": "tabs.close.force" }, "u": { "type": "tabs.reopen" }, "K": { "type": "tabs.prev" }, diff --git a/src/shared/Settings.ts b/src/shared/Settings.ts index 0bef342..2a392df 100644 --- a/src/shared/Settings.ts +++ b/src/shared/Settings.ts @@ -146,7 +146,8 @@ export const DefaultSetting: Settings = { 'G': { 'type': 'scroll.bottom' }, '$': { 'type': 'scroll.end' }, 'd': { 'type': 'tabs.close' }, - 'D': { 'type': 'tabs.close.right' }, + 'D': { 'type': 'tabs.close', 'select': 'left' }, + 'x$': { 'type': 'tabs.close.right' }, '!d': { 'type': 'tabs.close.force' }, 'u': { 'type': 'tabs.reopen' }, 'K': { 'type': 'tabs.prev' }, diff --git a/src/shared/operations.ts b/src/shared/operations.ts index 2b03d9d..2df2e67 100644 --- a/src/shared/operations.ts +++ b/src/shared/operations.ts @@ -201,6 +201,7 @@ export interface PageHomeOperation { export interface TabCloseOperation { type: typeof TAB_CLOSE; + select?: 'left' | 'right'; } export interface TabCloseForceOperation { @@ -367,28 +368,41 @@ export type Operation = const assertOptionalBoolean = (obj: any, name: string) => { if (Object.prototype.hasOwnProperty.call(obj, name) && typeof obj[name] !== 'boolean') { - throw new TypeError(`Not a boolean parameter '${name}'`); + throw new TypeError(`Not a boolean parameter: '${name}'`); + } +}; + +const assertOptionalString = (obj: any, name: string, values?: string[]) => { + if (Object.prototype.hasOwnProperty.call(obj, name)) { + let value = obj[name]; + if (typeof value !== 'string') { + throw new TypeError(`Not a string parameter: '${name}'`); + } + if (values && values.length && values.indexOf(value) === -1) { + // eslint-disable-next-line max-len + throw new TypeError(`Invalid parameter for '${name}': '${value}'`); + } } }; const assertRequiredNumber = (obj: any, name: string) => { if (!Object.prototype.hasOwnProperty.call(obj, name) || typeof obj[name] !== 'number') { - throw new TypeError(`Missing number parameter '${name}`); + throw new TypeError(`Missing number parameter: '${name}`); } }; const assertRequiredString = (obj: any, name: string) => { if (!Object.prototype.hasOwnProperty.call(obj, name) || typeof obj[name] !== 'string') { - throw new TypeError(`Missing string parameter '${name}`); + throw new TypeError(`Missing string parameter: '${name}`); } }; // eslint-disable-next-line complexity, max-lines-per-function export const valueOf = (o: any): Operation => { if (!Object.prototype.hasOwnProperty.call(o, 'type')) { - throw new TypeError(`missing 'type' field`); + throw new TypeError(`Missing 'type' field`); } switch (o.type) { case COMMAND_SHOW_OPEN: @@ -416,6 +430,12 @@ export const valueOf = (o: any): Operation => { type: PAGE_HOME, newTab: Boolean(typeof o.newTab === undefined ? false : o.newTab), }; + case TAB_CLOSE: + assertOptionalString(o, 'select', ['left', 'right']); + return { + type: TAB_CLOSE, + select: (typeof o.select === undefined ? 'right' : o.select), + }; case TAB_RELOAD: assertOptionalBoolean(o, 'cache'); return { @@ -458,7 +478,6 @@ export const valueOf = (o: any): Operation => { case NAVIGATE_ROOT: case FOCUS_INPUT: case PAGE_SOURCE: - case TAB_CLOSE: case TAB_CLOSE_FORCE: case TAB_CLOSE_RIGHT: case TAB_REOPEN: @@ -483,5 +502,5 @@ export const valueOf = (o: any): Operation => { case REPEAT_LAST: return { type: o.type }; } - throw new TypeError('unknown operation type: ' + o.type); + throw new TypeError('Unknown operation type: ' + o.type); }; |