aboutsummaryrefslogtreecommitdiff
path: root/src/background/operators/impls
diff options
context:
space:
mode:
authorShin'ya Ueoka <ueokande@i-beam.org>2020-12-10 12:52:17 +0000
committerGitHub <noreply@github.com>2020-12-10 12:52:17 +0000
commit5a0444d7bb7eae27fdca5c2be8fc3ec6c36d53bd (patch)
tree46d70e19f9720d237f4423c1debfcacdd088ce0b /src/background/operators/impls
parenta3c34a309c4b1421eb4914c3fbeba327a5400021 (diff)
parentd2fb674566393d9a8b88d71dba9f5081786b118c (diff)
Merge pull request #917 from ueokande/operation-as-a-operator
refactor: Make each operation as an operator
Diffstat (limited to 'src/background/operators/impls')
-rw-r--r--src/background/operators/impls/CancelOperator.ts15
-rw-r--r--src/background/operators/impls/CloseTabOperator.ts22
-rw-r--r--src/background/operators/impls/CloseTabRightOperator.ts21
-rw-r--r--src/background/operators/impls/CommandOperatorFactoryChain.ts63
-rw-r--r--src/background/operators/impls/DuplicateTabOperator.ts11
-rw-r--r--src/background/operators/impls/InternalOpenURLOperator.ts24
-rw-r--r--src/background/operators/impls/InternalOperatorFactoryChain.ts38
-rw-r--r--src/background/operators/impls/NavigateHistoryNextOperator.ts15
-rw-r--r--src/background/operators/impls/NavigateHistoryPrevOperator.ts15
-rw-r--r--src/background/operators/impls/NavigateLinkNextOperator.ts15
-rw-r--r--src/background/operators/impls/NavigateLinkPrevOperator.ts15
-rw-r--r--src/background/operators/impls/NavigateOperatorFactoryChain.ts66
-rw-r--r--src/background/operators/impls/NavigateParentOperator.ts25
-rw-r--r--src/background/operators/impls/NavigateRootOperator.ts12
-rw-r--r--src/background/operators/impls/OpenHomeOperator.ts29
-rw-r--r--src/background/operators/impls/OpenSourceOperator.ts12
-rw-r--r--src/background/operators/impls/OperatorFactoryImpl.ts45
-rw-r--r--src/background/operators/impls/PinTabOperator.ts11
-rw-r--r--src/background/operators/impls/ReloadTabOperator.ts14
-rw-r--r--src/background/operators/impls/ReopenTabOperator.ts10
-rw-r--r--src/background/operators/impls/RepeatLastOperator.ts18
-rw-r--r--src/background/operators/impls/RepeatOperatorFactoryChain.ts29
-rw-r--r--src/background/operators/impls/ResetZoomOperator.ts10
-rw-r--r--src/background/operators/impls/SelectFirstTabOperator.ts11
-rw-r--r--src/background/operators/impls/SelectLastTabOperator.ts11
-rw-r--r--src/background/operators/impls/SelectPreviousSelectedTabOperator.ts14
-rw-r--r--src/background/operators/impls/SelectTabNextOperator.ts19
-rw-r--r--src/background/operators/impls/SelectTabPrevOperator.ts19
-rw-r--r--src/background/operators/impls/ShowAddBookmarkOperator.ts20
-rw-r--r--src/background/operators/impls/ShowBufferCommandOperator.ts16
-rw-r--r--src/background/operators/impls/ShowCommandOperator.ts15
-rw-r--r--src/background/operators/impls/ShowOpenCommandOperator.ts20
-rw-r--r--src/background/operators/impls/ShowTabOpenCommandOperator.ts20
-rw-r--r--src/background/operators/impls/ShowWinOpenCommandOperator.ts20
-rw-r--r--src/background/operators/impls/StartFindOperator.ts15
-rw-r--r--src/background/operators/impls/TabOperatorFactoryChain.ts64
-rw-r--r--src/background/operators/impls/TogglePinnedTabOperator.ts11
-rw-r--r--src/background/operators/impls/UnpinTabOperator.ts11
-rw-r--r--src/background/operators/impls/ZoomInOperator.ts10
-rw-r--r--src/background/operators/impls/ZoomOperatorFactoryChain.ts28
-rw-r--r--src/background/operators/impls/ZoomOutOperator.ts10
41 files changed, 869 insertions, 0 deletions
diff --git a/src/background/operators/impls/CancelOperator.ts b/src/background/operators/impls/CancelOperator.ts
new file mode 100644
index 0000000..7ab09fb
--- /dev/null
+++ b/src/background/operators/impls/CancelOperator.ts
@@ -0,0 +1,15 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+
+export default class CancelOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly consoleClient: ConsoleClient
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ return this.consoleClient.hide(tab.id as number);
+ }
+}
diff --git a/src/background/operators/impls/CloseTabOperator.ts b/src/background/operators/impls/CloseTabOperator.ts
new file mode 100644
index 0000000..5d8e80b
--- /dev/null
+++ b/src/background/operators/impls/CloseTabOperator.ts
@@ -0,0 +1,22 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class CloseTabOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly force: boolean = false,
+ private readonly selectLeft: boolean = false
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ if (!this.force && tab.pinned) {
+ return Promise.resolve();
+ }
+ if (this.selectLeft && tab.index > 0) {
+ const 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/background/operators/impls/CloseTabRightOperator.ts b/src/background/operators/impls/CloseTabRightOperator.ts
new file mode 100644
index 0000000..f36930e
--- /dev/null
+++ b/src/background/operators/impls/CloseTabRightOperator.ts
@@ -0,0 +1,21 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class CloseTabRightOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tabs = await this.tabPresenter.getAll();
+ tabs.sort((t1, t2) => t1.index - t2.index);
+ const index = tabs.findIndex((t) => t.active);
+ if (index < 0) {
+ return;
+ }
+ for (let i = index + 1; i < tabs.length; ++i) {
+ const tab = tabs[i];
+ if (!tab.pinned) {
+ await this.tabPresenter.remove([tab.id as number]);
+ }
+ }
+ }
+}
diff --git a/src/background/operators/impls/CommandOperatorFactoryChain.ts b/src/background/operators/impls/CommandOperatorFactoryChain.ts
new file mode 100644
index 0000000..680a384
--- /dev/null
+++ b/src/background/operators/impls/CommandOperatorFactoryChain.ts
@@ -0,0 +1,63 @@
+import { inject, injectable } from "tsyringe";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import ShowCommandOperator from "./ShowCommandOperator";
+import ShowOpenCommandOperator from "./ShowOpenCommandOperator";
+import ShowTabOpenCommandOperator from "./ShowTabOpenCommandOperator";
+import ShowWinOpenCommandOperator from "./ShowWinOpenCommandOperator";
+import ShowBufferCommandOperator from "./ShowBufferCommandOperator";
+import ShowAddBookmarkOperator from "./ShowAddBookmarkOperator";
+import TabPresenter from "../../presenters/TabPresenter";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+import * as operations from "../../../shared/operations";
+import StartFindOperator from "./StartFindOperator";
+
+@injectable()
+export default class CommandOperatorFactoryChain
+ implements OperatorFactoryChain {
+ constructor(
+ @inject("TabPresenter")
+ private readonly tabPresenter: TabPresenter,
+ @inject("ConsoleClient")
+ private readonly consoleClient: ConsoleClient
+ ) {}
+
+ create(op: operations.Operation): Operator | null {
+ switch (op.type) {
+ case operations.COMMAND_SHOW:
+ return new ShowCommandOperator(this.tabPresenter, this.consoleClient);
+ case operations.COMMAND_SHOW_OPEN:
+ return new ShowOpenCommandOperator(
+ this.tabPresenter,
+ this.consoleClient,
+ op.alter
+ );
+ case operations.COMMAND_SHOW_TABOPEN:
+ return new ShowTabOpenCommandOperator(
+ this.tabPresenter,
+ this.consoleClient,
+ op.alter
+ );
+ case operations.COMMAND_SHOW_WINOPEN:
+ return new ShowWinOpenCommandOperator(
+ this.tabPresenter,
+ this.consoleClient,
+ op.alter
+ );
+ case operations.COMMAND_SHOW_BUFFER:
+ return new ShowBufferCommandOperator(
+ this.tabPresenter,
+ this.consoleClient
+ );
+ case operations.COMMAND_SHOW_ADDBOOKMARK:
+ return new ShowAddBookmarkOperator(
+ this.tabPresenter,
+ this.consoleClient,
+ op.alter
+ );
+ case operations.FIND_START:
+ return new StartFindOperator(this.tabPresenter, this.consoleClient);
+ }
+ return null;
+ }
+}
diff --git a/src/background/operators/impls/DuplicateTabOperator.ts b/src/background/operators/impls/DuplicateTabOperator.ts
new file mode 100644
index 0000000..7737cfa
--- /dev/null
+++ b/src/background/operators/impls/DuplicateTabOperator.ts
@@ -0,0 +1,11 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class DuplicateTabOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ await this.tabPresenter.duplicate(tab.id as number);
+ }
+}
diff --git a/src/background/operators/impls/InternalOpenURLOperator.ts b/src/background/operators/impls/InternalOpenURLOperator.ts
new file mode 100644
index 0000000..6bf513b
--- /dev/null
+++ b/src/background/operators/impls/InternalOpenURLOperator.ts
@@ -0,0 +1,24 @@
+import Operator from "../Operator";
+import WindowPresenter from "../../presenters/WindowPresenter";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class InternalOpenURLOperator implements Operator {
+ constructor(
+ private readonly windowPresenter: WindowPresenter,
+ private readonly tabPresenter: TabPresenter,
+ private readonly url: string,
+ private readonly newTab?: boolean,
+ private readonly newWindow?: boolean
+ ) {}
+
+ async run(): Promise<void> {
+ if (this.newWindow) {
+ await this.windowPresenter.create(this.url);
+ } else if (this.newTab) {
+ await this.tabPresenter.create(this.url);
+ } else {
+ const tab = await this.tabPresenter.getCurrent();
+ await this.tabPresenter.open(this.url, tab.id);
+ }
+ }
+}
diff --git a/src/background/operators/impls/InternalOperatorFactoryChain.ts b/src/background/operators/impls/InternalOperatorFactoryChain.ts
new file mode 100644
index 0000000..05615f6
--- /dev/null
+++ b/src/background/operators/impls/InternalOperatorFactoryChain.ts
@@ -0,0 +1,38 @@
+import { inject, injectable } from "tsyringe";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import CancelOperator from "./CancelOperator";
+import InternalOpenURLOperator from "./InternalOpenURLOperator";
+import TabPresenter from "../../presenters/TabPresenter";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+import WindowPresenter from "../../presenters/WindowPresenter";
+import * as operations from "../../../shared/operations";
+
+@injectable()
+export default class InternalOperatorFactoryChain
+ implements OperatorFactoryChain {
+ constructor(
+ @inject("WindowPresenter")
+ private readonly windowPresenter: WindowPresenter,
+ @inject("TabPresenter")
+ private readonly tabPresenter: TabPresenter,
+ @inject("ConsoleClient")
+ private readonly consoleClient: ConsoleClient
+ ) {}
+
+ create(op: operations.Operation): Operator | null {
+ switch (op.type) {
+ case operations.CANCEL:
+ return new CancelOperator(this.tabPresenter, this.consoleClient);
+ case operations.INTERNAL_OPEN_URL:
+ return new InternalOpenURLOperator(
+ this.windowPresenter,
+ this.tabPresenter,
+ op.url,
+ op.newTab,
+ op.newWindow
+ );
+ }
+ return null;
+ }
+}
diff --git a/src/background/operators/impls/NavigateHistoryNextOperator.ts b/src/background/operators/impls/NavigateHistoryNextOperator.ts
new file mode 100644
index 0000000..b092c48
--- /dev/null
+++ b/src/background/operators/impls/NavigateHistoryNextOperator.ts
@@ -0,0 +1,15 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import NavigateClient from "../../clients/NavigateClient";
+
+export default class NavigateHistoryNextOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly navigateClient: NavigateClient
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ await this.navigateClient.historyNext(tab.id!);
+ }
+}
diff --git a/src/background/operators/impls/NavigateHistoryPrevOperator.ts b/src/background/operators/impls/NavigateHistoryPrevOperator.ts
new file mode 100644
index 0000000..27d4ee9
--- /dev/null
+++ b/src/background/operators/impls/NavigateHistoryPrevOperator.ts
@@ -0,0 +1,15 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import NavigateClient from "../../clients/NavigateClient";
+
+export default class NavigateHistoryPrevOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly navigateClient: NavigateClient
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ await this.navigateClient.historyPrev(tab.id!);
+ }
+}
diff --git a/src/background/operators/impls/NavigateLinkNextOperator.ts b/src/background/operators/impls/NavigateLinkNextOperator.ts
new file mode 100644
index 0000000..dbbcc45
--- /dev/null
+++ b/src/background/operators/impls/NavigateLinkNextOperator.ts
@@ -0,0 +1,15 @@
+import Operator from "../Operator";
+import NavigateClient from "../../clients/NavigateClient";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class NavigateLinkNextOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly navigateClient: NavigateClient
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ await this.navigateClient.linkNext(tab.id!);
+ }
+}
diff --git a/src/background/operators/impls/NavigateLinkPrevOperator.ts b/src/background/operators/impls/NavigateLinkPrevOperator.ts
new file mode 100644
index 0000000..fe41ee6
--- /dev/null
+++ b/src/background/operators/impls/NavigateLinkPrevOperator.ts
@@ -0,0 +1,15 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import NavigateClient from "../../clients/NavigateClient";
+
+export default class NavigateLinkPrevOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly navigateClient: NavigateClient
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ await this.navigateClient.linkPrev(tab.id!);
+ }
+}
diff --git a/src/background/operators/impls/NavigateOperatorFactoryChain.ts b/src/background/operators/impls/NavigateOperatorFactoryChain.ts
new file mode 100644
index 0000000..618db45
--- /dev/null
+++ b/src/background/operators/impls/NavigateOperatorFactoryChain.ts
@@ -0,0 +1,66 @@
+import { inject, injectable } from "tsyringe";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import NavigateHistoryPrevOperator from "./NavigateHistoryPrevOperator";
+import NavigateHistoryNextOperator from "./NavigateHistoryNextOperator";
+import NavigateLinkPrevOperator from "./NavigateLinkPrevOperator";
+import NavigateLinkNextOperator from "./NavigateLinkNextOperator";
+import NavigateParentOperator from "./NavigateParentOperator";
+import NavigateRootOperator from "./NavigateRootOperator";
+import OpenSourceOperator from "./OpenSourceOperator";
+import OpenHomeOperator from "./OpenHomeOperator";
+import TabPresenter from "../../presenters/TabPresenter";
+import NavigateClient from "../../clients/NavigateClient";
+import BrowserSettingRepository from "../../repositories/BrowserSettingRepository";
+import * as operations from "../../../shared/operations";
+
+@injectable()
+export default class NavigateOperatorFactoryChain
+ implements OperatorFactoryChain {
+ constructor(
+ @inject("TabPresenter")
+ private readonly tabPresenter: TabPresenter,
+ @inject("NavigateClient")
+ private readonly navigateClient: NavigateClient,
+ @inject("BrowserSettingRepository")
+ private readonly browserSettingRepository: BrowserSettingRepository
+ ) {}
+
+ create(op: operations.Operation): Operator | null {
+ switch (op.type) {
+ case operations.NAVIGATE_HISTORY_PREV:
+ return new NavigateHistoryPrevOperator(
+ this.tabPresenter,
+ this.navigateClient
+ );
+ case operations.NAVIGATE_HISTORY_NEXT:
+ return new NavigateHistoryNextOperator(
+ this.tabPresenter,
+ this.navigateClient
+ );
+ case operations.NAVIGATE_LINK_PREV:
+ return new NavigateLinkPrevOperator(
+ this.tabPresenter,
+ this.navigateClient
+ );
+ case operations.NAVIGATE_LINK_NEXT:
+ return new NavigateLinkNextOperator(
+ this.tabPresenter,
+ this.navigateClient
+ );
+ case operations.NAVIGATE_PARENT:
+ return new NavigateParentOperator(this.tabPresenter);
+ case operations.NAVIGATE_ROOT:
+ return new NavigateRootOperator(this.tabPresenter);
+ case operations.PAGE_SOURCE:
+ return new OpenSourceOperator(this.tabPresenter);
+ case operations.PAGE_HOME:
+ return new OpenHomeOperator(
+ this.tabPresenter,
+ this.browserSettingRepository,
+ op.newTab
+ );
+ }
+ return null;
+ }
+}
diff --git a/src/background/operators/impls/NavigateParentOperator.ts b/src/background/operators/impls/NavigateParentOperator.ts
new file mode 100644
index 0000000..652cfb8
--- /dev/null
+++ b/src/background/operators/impls/NavigateParentOperator.ts
@@ -0,0 +1,25 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class NavigateParentOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ const url = new URL(tab.url!);
+ if (url.hash.length > 0) {
+ url.hash = "";
+ } else if (url.search.length > 0) {
+ url.search = "";
+ } else {
+ const basenamePattern = /\/[^/]+$/;
+ const lastDirPattern = /\/[^/]+\/$/;
+ if (basenamePattern.test(url.pathname)) {
+ url.pathname = url.pathname.replace(basenamePattern, "/");
+ } else if (lastDirPattern.test(url.pathname)) {
+ url.pathname = url.pathname.replace(lastDirPattern, "/");
+ }
+ }
+ await this.tabPresenter.open(url.href);
+ }
+}
diff --git a/src/background/operators/impls/NavigateRootOperator.ts b/src/background/operators/impls/NavigateRootOperator.ts
new file mode 100644
index 0000000..b140156
--- /dev/null
+++ b/src/background/operators/impls/NavigateRootOperator.ts
@@ -0,0 +1,12 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class NavigateRootOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ const url = new URL(tab.url!);
+ await this.tabPresenter.open(url.origin);
+ }
+}
diff --git a/src/background/operators/impls/OpenHomeOperator.ts b/src/background/operators/impls/OpenHomeOperator.ts
new file mode 100644
index 0000000..4773be6
--- /dev/null
+++ b/src/background/operators/impls/OpenHomeOperator.ts
@@ -0,0 +1,29 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import BrowserSettingRepository from "../../repositories/BrowserSettingRepository";
+
+export default class OpenHomeOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly browserSettingRepository: BrowserSettingRepository,
+ private readonly newTab: boolean
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ const urls = await this.browserSettingRepository.getHomepageUrls();
+ if (urls.length === 1 && urls[0] === "about:home") {
+ // eslint-disable-next-line max-len
+ throw new Error(
+ "Cannot open Firefox Home (about:home) by WebExtensions, set your custom URLs"
+ );
+ }
+ if (urls.length === 1 && !this.newTab) {
+ await this.tabPresenter.open(urls[0], tab.id);
+ return;
+ }
+ for (const url of urls) {
+ await this.tabPresenter.create(url);
+ }
+ }
+}
diff --git a/src/background/operators/impls/OpenSourceOperator.ts b/src/background/operators/impls/OpenSourceOperator.ts
new file mode 100644
index 0000000..9185ba5
--- /dev/null
+++ b/src/background/operators/impls/OpenSourceOperator.ts
@@ -0,0 +1,12 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class OpenSourceOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ const url = "view-source:" + tab.url;
+ await this.tabPresenter.create(url);
+ }
+}
diff --git a/src/background/operators/impls/OperatorFactoryImpl.ts b/src/background/operators/impls/OperatorFactoryImpl.ts
new file mode 100644
index 0000000..34e7bb5
--- /dev/null
+++ b/src/background/operators/impls/OperatorFactoryImpl.ts
@@ -0,0 +1,45 @@
+import { inject, delay, injectable } from "tsyringe";
+import Operator from "../Operator";
+import OperatorFactory from "../OperatorFactory";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import CommandOperatorFactoryChain from "./CommandOperatorFactoryChain";
+import InternalOperatorFactoryChain from "./InternalOperatorFactoryChain";
+import NavigateOperatorFactoryChain from "./NavigateOperatorFactoryChain";
+import RepeatOperatorFactoryChain from "./RepeatOperatorFactoryChain";
+import TabOperatorFactoryChain from "./TabOperatorFactoryChain";
+import ZoomOperatorFactoryChain from "./ZoomOperatorFactoryChain";
+import * as operations from "../../../shared/operations";
+
+@injectable()
+export class OperatorFactoryImpl implements OperatorFactory {
+ private readonly factoryChains: OperatorFactoryChain[];
+
+ constructor(
+ commandOperatorFactoryChain: CommandOperatorFactoryChain,
+ internalOperatorFactoryChain: InternalOperatorFactoryChain,
+ navigateOperatorFactoryChain: NavigateOperatorFactoryChain,
+ tabOperatorFactoryChain: TabOperatorFactoryChain,
+ zoomOperatorFactoryChain: ZoomOperatorFactoryChain,
+ @inject(delay(() => RepeatOperatorFactoryChain))
+ repeatOperatorFactoryChain: RepeatOperatorFactoryChain
+ ) {
+ this.factoryChains = [
+ commandOperatorFactoryChain,
+ internalOperatorFactoryChain,
+ navigateOperatorFactoryChain,
+ repeatOperatorFactoryChain,
+ tabOperatorFactoryChain,
+ zoomOperatorFactoryChain,
+ ];
+ }
+
+ create(op: operations.Operation): Operator {
+ for (const chain of this.factoryChains) {
+ const operator = chain.create(op);
+ if (operator !== null) {
+ return operator;
+ }
+ }
+ throw new Error("unknown operation: " + op.type);
+ }
+}
diff --git a/src/background/operators/impls/PinTabOperator.ts b/src/background/operators/impls/PinTabOperator.ts
new file mode 100644
index 0000000..8121725
--- /dev/null
+++ b/src/background/operators/impls/PinTabOperator.ts
@@ -0,0 +1,11 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class PinTabOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ return this.tabPresenter.setPinned(tab.id as number, true);
+ }
+}
diff --git a/src/background/operators/impls/ReloadTabOperator.ts b/src/background/operators/impls/ReloadTabOperator.ts
new file mode 100644
index 0000000..db3389e
--- /dev/null
+++ b/src/background/operators/impls/ReloadTabOperator.ts
@@ -0,0 +1,14 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class ReloadTabOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly cache: boolean
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ return this.tabPresenter.reload(tab.id as number, this.cache);
+ }
+}
diff --git a/src/background/operators/impls/ReopenTabOperator.ts b/src/background/operators/impls/ReopenTabOperator.ts
new file mode 100644
index 0000000..507b4a8
--- /dev/null
+++ b/src/background/operators/impls/ReopenTabOperator.ts
@@ -0,0 +1,10 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class ReopenTabOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ run(): Promise<void> {
+ return this.tabPresenter.reopen();
+ }
+}
diff --git a/src/background/operators/impls/RepeatLastOperator.ts b/src/background/operators/impls/RepeatLastOperator.ts
new file mode 100644
index 0000000..d46daab
--- /dev/null
+++ b/src/background/operators/impls/RepeatLastOperator.ts
@@ -0,0 +1,18 @@
+import Operator from "../Operator";
+import RepeatRepository from "../../repositories/RepeatRepository";
+import OperatorFactory from "../OperatorFactory";
+
+export default class RepeatLastOperator implements Operator {
+ constructor(
+ private readonly repeatRepository: RepeatRepository,
+ private readonly operatorFactory: OperatorFactory
+ ) {}
+
+ run(): Promise<void> {
+ const op = this.repeatRepository.getLastOperation();
+ if (typeof op === "undefined") {
+ return Promise.resolve();
+ }
+ return this.operatorFactory.create(op).run();
+ }
+}
diff --git a/src/background/operators/impls/RepeatOperatorFactoryChain.ts b/src/background/operators/impls/RepeatOperatorFactoryChain.ts
new file mode 100644
index 0000000..5038d48
--- /dev/null
+++ b/src/background/operators/impls/RepeatOperatorFactoryChain.ts
@@ -0,0 +1,29 @@
+import { inject, injectable } from "tsyringe";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import RepeatLastOperator from "./RepeatLastOperator";
+import RepeatRepository from "../../repositories/RepeatRepository";
+import OperatorFactory from "../OperatorFactory";
+import * as operations from "../../../shared/operations";
+
+@injectable()
+export default class RepeatOperatorFactoryChain
+ implements OperatorFactoryChain {
+ constructor(
+ @inject("RepeatRepository")
+ private readonly repeatRepository: RepeatRepository,
+ @inject("OperatorFactory")
+ private readonly operatorFactory: OperatorFactory
+ ) {}
+
+ create(op: operations.Operation): Operator | null {
+ switch (op.type) {
+ case operations.REPEAT_LAST:
+ return new RepeatLastOperator(
+ this.repeatRepository,
+ this.operatorFactory
+ );
+ }
+ return null;
+ }
+}
diff --git a/src/background/operators/impls/ResetZoomOperator.ts b/src/background/operators/impls/ResetZoomOperator.ts
new file mode 100644
index 0000000..96af733
--- /dev/null
+++ b/src/background/operators/impls/ResetZoomOperator.ts
@@ -0,0 +1,10 @@
+import Operator from "../Operator";
+import ZoomPresenter from "../../presenters/ZoomPresenter";
+
+export default class ResetZoomOperator implements Operator {
+ constructor(private readonly zoomPresenter: ZoomPresenter) {}
+
+ run(): Promise<void> {
+ return this.zoomPresenter.resetZoom();
+ }
+}
diff --git a/src/background/operators/impls/SelectFirstTabOperator.ts b/src/background/operators/impls/SelectFirstTabOperator.ts
new file mode 100644
index 0000000..c04b8a9
--- /dev/null
+++ b/src/background/operators/impls/SelectFirstTabOperator.ts
@@ -0,0 +1,11 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class SelectFirstTabOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tabs = await this.tabPresenter.getAll();
+ return this.tabPresenter.select(tabs[0].id as number);
+ }
+}
diff --git a/src/background/operators/impls/SelectLastTabOperator.ts b/src/background/operators/impls/SelectLastTabOperator.ts
new file mode 100644
index 0000000..e16d406
--- /dev/null
+++ b/src/background/operators/impls/SelectLastTabOperator.ts
@@ -0,0 +1,11 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class SelectLastTabOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tabs = await this.tabPresenter.getAll();
+ return this.tabPresenter.select(tabs[tabs.length - 1].id as number);
+ }
+}
diff --git a/src/background/operators/impls/SelectPreviousSelectedTabOperator.ts b/src/background/operators/impls/SelectPreviousSelectedTabOperator.ts
new file mode 100644
index 0000000..03a778d
--- /dev/null
+++ b/src/background/operators/impls/SelectPreviousSelectedTabOperator.ts
@@ -0,0 +1,14 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class SelectPreviousSelectedTabOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tabId = await this.tabPresenter.getLastSelectedId();
+ if (tabId === null || typeof tabId === "undefined") {
+ return Promise.resolve();
+ }
+ return this.tabPresenter.select(tabId);
+ }
+}
diff --git a/src/background/operators/impls/SelectTabNextOperator.ts b/src/background/operators/impls/SelectTabNextOperator.ts
new file mode 100644
index 0000000..34d37ff
--- /dev/null
+++ b/src/background/operators/impls/SelectTabNextOperator.ts
@@ -0,0 +1,19 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class SelectTabNextOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tabs = await this.tabPresenter.getAll();
+ if (tabs.length < 2) {
+ return;
+ }
+ const tab = tabs.find((t) => t.active);
+ if (!tab) {
+ return;
+ }
+ const select = (tab.index + 1) % tabs.length;
+ return this.tabPresenter.select(tabs[select].id as number);
+ }
+}
diff --git a/src/background/operators/impls/SelectTabPrevOperator.ts b/src/background/operators/impls/SelectTabPrevOperator.ts
new file mode 100644
index 0000000..3776c1a
--- /dev/null
+++ b/src/background/operators/impls/SelectTabPrevOperator.ts
@@ -0,0 +1,19 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class SelectTabPrevOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tabs = await this.tabPresenter.getAll();
+ if (tabs.length < 2) {
+ return;
+ }
+ const tab = tabs.find((t) => t.active);
+ if (!tab) {
+ return;
+ }
+ const select = (tab.index - 1 + tabs.length) % tabs.length;
+ return this.tabPresenter.select(tabs[select].id as number);
+ }
+}
diff --git a/src/background/operators/impls/ShowAddBookmarkOperator.ts b/src/background/operators/impls/ShowAddBookmarkOperator.ts
new file mode 100644
index 0000000..cce4879
--- /dev/null
+++ b/src/background/operators/impls/ShowAddBookmarkOperator.ts
@@ -0,0 +1,20 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+
+export default class ShowAddBookmarkOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly consoleClient: ConsoleClient,
+ private readonly alter: boolean
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ let command = "addbookmark ";
+ if (this.alter) {
+ command += tab.title || "";
+ }
+ return this.consoleClient.showCommand(tab.id as number, command);
+ }
+}
diff --git a/src/background/operators/impls/ShowBufferCommandOperator.ts b/src/background/operators/impls/ShowBufferCommandOperator.ts
new file mode 100644
index 0000000..e1246e4
--- /dev/null
+++ b/src/background/operators/impls/ShowBufferCommandOperator.ts
@@ -0,0 +1,16 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+
+export default class ShowBufferCommandOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly consoleClient: ConsoleClient
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ const command = "buffer ";
+ return this.consoleClient.showCommand(tab.id as number, command);
+ }
+}
diff --git a/src/background/operators/impls/ShowCommandOperator.ts b/src/background/operators/impls/ShowCommandOperator.ts
new file mode 100644
index 0000000..a5e1765
--- /dev/null
+++ b/src/background/operators/impls/ShowCommandOperator.ts
@@ -0,0 +1,15 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+
+export default class ShowCommandOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly consoleClient: ConsoleClient
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ return this.consoleClient.showCommand(tab.id as number, "");
+ }
+}
diff --git a/src/background/operators/impls/ShowOpenCommandOperator.ts b/src/background/operators/impls/ShowOpenCommandOperator.ts
new file mode 100644
index 0000000..1e78e5f
--- /dev/null
+++ b/src/background/operators/impls/ShowOpenCommandOperator.ts
@@ -0,0 +1,20 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+
+export default class ShowOpenCommandOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly consoleClient: ConsoleClient,
+ private readonly alter: boolean
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ let command = "open ";
+ if (this.alter) {
+ command += tab.url || "";
+ }
+ return this.consoleClient.showCommand(tab.id as number, command);
+ }
+}
diff --git a/src/background/operators/impls/ShowTabOpenCommandOperator.ts b/src/background/operators/impls/ShowTabOpenCommandOperator.ts
new file mode 100644
index 0000000..d734da1
--- /dev/null
+++ b/src/background/operators/impls/ShowTabOpenCommandOperator.ts
@@ -0,0 +1,20 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+
+export default class ShowTabOpenCommandOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly consoleClient: ConsoleClient,
+ private readonly alter: boolean
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ let command = "tabopen ";
+ if (this.alter) {
+ command += tab.url || "";
+ }
+ return this.consoleClient.showCommand(tab.id as number, command);
+ }
+}
diff --git a/src/background/operators/impls/ShowWinOpenCommandOperator.ts b/src/background/operators/impls/ShowWinOpenCommandOperator.ts
new file mode 100644
index 0000000..3c5e639
--- /dev/null
+++ b/src/background/operators/impls/ShowWinOpenCommandOperator.ts
@@ -0,0 +1,20 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+
+export default class ShowWinOpenCommandOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly consoleClient: ConsoleClient,
+ private readonly alter: boolean
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ let command = "winopen ";
+ if (this.alter) {
+ command += tab.url || "";
+ }
+ return this.consoleClient.showCommand(tab.id as number, command);
+ }
+}
diff --git a/src/background/operators/impls/StartFindOperator.ts b/src/background/operators/impls/StartFindOperator.ts
new file mode 100644
index 0000000..284ac9b
--- /dev/null
+++ b/src/background/operators/impls/StartFindOperator.ts
@@ -0,0 +1,15 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+
+export default class StartFindOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly consoleClient: ConsoleClient
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ return this.consoleClient.showFind(tab.id as number);
+ }
+}
diff --git a/src/background/operators/impls/TabOperatorFactoryChain.ts b/src/background/operators/impls/TabOperatorFactoryChain.ts
new file mode 100644
index 0000000..edd3eaf
--- /dev/null
+++ b/src/background/operators/impls/TabOperatorFactoryChain.ts
@@ -0,0 +1,64 @@
+import { inject, injectable } from "tsyringe";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import * as operations from "../../../shared/operations";
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import CloseTabOperator from "./CloseTabOperator";
+import CloseTabRightOperator from "./CloseTabRightOperator";
+import ReopenTabOperator from "./ReopenTabOperator";
+import SelectTabPrevOperator from "./SelectTabPrevOperator";
+import SelectTabNextOperator from "./SelectTabNextOperator";
+import SelectFirstTabOperator from "./SelectFirstTabOperator";
+import SelectLastTabOperator from "./SelectLastTabOperator";
+import SelectPreviousSelectedTabOperator from "./SelectPreviousSelectedTabOperator";
+import ReloadTabOperator from "./ReloadTabOperator";
+import PinTabOperator from "./PinTabOperator";
+import UnpinTabOperator from "./UnpinTabOperator";
+import TogglePinnedTabOperator from "./TogglePinnedTabOperator";
+import DuplicateTabOperator from "./DuplicateTabOperator";
+
+@injectable()
+export default class TabOperatorFactoryChain implements OperatorFactoryChain {
+ constructor(
+ @inject("TabPresenter")
+ private readonly tabPresenter: TabPresenter
+ ) {}
+
+ create(op: operations.Operation): Operator | null {
+ switch (op.type) {
+ case operations.TAB_CLOSE:
+ return new CloseTabOperator(
+ this.tabPresenter,
+ false,
+ op.select === "left"
+ );
+ case operations.TAB_CLOSE_RIGHT:
+ return new CloseTabRightOperator(this.tabPresenter);
+ case operations.TAB_CLOSE_FORCE:
+ return new CloseTabOperator(this.tabPresenter, true, false);
+ case operations.TAB_REOPEN:
+ return new ReopenTabOperator(this.tabPresenter);
+ case operations.TAB_PREV:
+ return new SelectTabPrevOperator(this.tabPresenter);
+ case operations.TAB_NEXT:
+ return new SelectTabNextOperator(this.tabPresenter);
+ case operations.TAB_FIRST:
+ return new SelectFirstTabOperator(this.tabPresenter);
+ case operations.TAB_LAST:
+ return new SelectLastTabOperator(this.tabPresenter);
+ case operations.TAB_PREV_SEL:
+ return new SelectPreviousSelectedTabOperator(this.tabPresenter);
+ case operations.TAB_RELOAD:
+ return new ReloadTabOperator(this.tabPresenter, op.cache);
+ case operations.TAB_PIN:
+ return new PinTabOperator(this.tabPresenter);
+ case operations.TAB_UNPIN:
+ return new UnpinTabOperator(this.tabPresenter);
+ case operations.TAB_TOGGLE_PINNED:
+ return new TogglePinnedTabOperator(this.tabPresenter);
+ case operations.TAB_DUPLICATE:
+ return new DuplicateTabOperator(this.tabPresenter);
+ }
+ return null;
+ }
+}
diff --git a/src/background/operators/impls/TogglePinnedTabOperator.ts b/src/background/operators/impls/TogglePinnedTabOperator.ts
new file mode 100644
index 0000000..c4fd4ba
--- /dev/null
+++ b/src/background/operators/impls/TogglePinnedTabOperator.ts
@@ -0,0 +1,11 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class TogglePinnedTabOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ return this.tabPresenter.setPinned(tab.id as number, !tab.pinned);
+ }
+}
diff --git a/src/background/operators/impls/UnpinTabOperator.ts b/src/background/operators/impls/UnpinTabOperator.ts
new file mode 100644
index 0000000..fa50145
--- /dev/null
+++ b/src/background/operators/impls/UnpinTabOperator.ts
@@ -0,0 +1,11 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+
+export default class UnpinTabOperator implements Operator {
+ constructor(private readonly tabPresenter: TabPresenter) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ return this.tabPresenter.setPinned(tab.id as number, false);
+ }
+}
diff --git a/src/background/operators/impls/ZoomInOperator.ts b/src/background/operators/impls/ZoomInOperator.ts
new file mode 100644
index 0000000..e900f0d
--- /dev/null
+++ b/src/background/operators/impls/ZoomInOperator.ts
@@ -0,0 +1,10 @@
+import Operator from "../Operator";
+import ZoomPresenter from "../../presenters/ZoomPresenter";
+
+export default class ZoomInOperator implements Operator {
+ constructor(private readonly zoomPresenter: ZoomPresenter) {}
+
+ run(): Promise<void> {
+ return this.zoomPresenter.zoomIn();
+ }
+}
diff --git a/src/background/operators/impls/ZoomOperatorFactoryChain.ts b/src/background/operators/impls/ZoomOperatorFactoryChain.ts
new file mode 100644
index 0000000..bf930a7
--- /dev/null
+++ b/src/background/operators/impls/ZoomOperatorFactoryChain.ts
@@ -0,0 +1,28 @@
+import { inject, injectable } from "tsyringe";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import ZoomInOperator from "./ZoomInOperator";
+import ZoomOutOperator from "./ZoomOutOperator";
+import ResetZoomOperator from "./ResetZoomOperator";
+import ZoomPresenter from "../../presenters/ZoomPresenter";
+import * as operations from "../../../shared/operations";
+
+@injectable()
+export default class ZoomOperatorFactoryChain implements OperatorFactoryChain {
+ constructor(
+ @inject("ZoomPresenter")
+ private readonly zoomPresenter: ZoomPresenter
+ ) {}
+
+ create(op: operations.Operation): Operator | null {
+ switch (op.type) {
+ case operations.ZOOM_IN:
+ return new ZoomInOperator(this.zoomPresenter);
+ case operations.ZOOM_OUT:
+ return new ZoomOutOperator(this.zoomPresenter);
+ case operations.ZOOM_NEUTRAL:
+ return new ResetZoomOperator(this.zoomPresenter);
+ }
+ return null;
+ }
+}
diff --git a/src/background/operators/impls/ZoomOutOperator.ts b/src/background/operators/impls/ZoomOutOperator.ts
new file mode 100644
index 0000000..0c0389e
--- /dev/null
+++ b/src/background/operators/impls/ZoomOutOperator.ts
@@ -0,0 +1,10 @@
+import Operator from "../Operator";
+import ZoomPresenter from "../../presenters/ZoomPresenter";
+
+export default class ZoomOutOperator implements Operator {
+ constructor(private readonly zoomPresenter: ZoomPresenter) {}
+
+ run(): Promise<void> {
+ return this.zoomPresenter.zoomOut();
+ }
+}