aboutsummaryrefslogtreecommitdiff
path: root/src/content/operators/impls
diff options
context:
space:
mode:
Diffstat (limited to 'src/content/operators/impls')
-rw-r--r--src/content/operators/impls/BackgroundOperationOperator.ts15
-rw-r--r--src/content/operators/impls/OperatorFactoryImpl.ts51
-rw-r--r--src/content/operators/impls/RepeatOperator.ts14
-rw-r--r--src/content/operators/impls/addons.ts74
-rw-r--r--src/content/operators/impls/clipboard.ts74
-rw-r--r--src/content/operators/impls/find.ts45
-rw-r--r--src/content/operators/impls/focus.ts29
-rw-r--r--src/content/operators/impls/follow.ts37
-rw-r--r--src/content/operators/impls/mark.ts39
-rw-r--r--src/content/operators/impls/scroll.ts183
10 files changed, 561 insertions, 0 deletions
diff --git a/src/content/operators/impls/BackgroundOperationOperator.ts b/src/content/operators/impls/BackgroundOperationOperator.ts
new file mode 100644
index 0000000..dd86559
--- /dev/null
+++ b/src/content/operators/impls/BackgroundOperationOperator.ts
@@ -0,0 +1,15 @@
+import Operator from "../Operator";
+import OperationClient from "../../client/OperationClient";
+import * as operations from "../../../shared/operations";
+
+export default class BackgroundOperationOperator implements Operator {
+ constructor(
+ private readonly operationClient: OperationClient,
+ private readonly repeat: number,
+ private readonly op: operations.Operation
+ ) {}
+
+ async run(): Promise<void> {
+ await this.operationClient.execBackgroundOp(this.repeat, this.op);
+ }
+}
diff --git a/src/content/operators/impls/OperatorFactoryImpl.ts b/src/content/operators/impls/OperatorFactoryImpl.ts
new file mode 100644
index 0000000..f1aa3bc
--- /dev/null
+++ b/src/content/operators/impls/OperatorFactoryImpl.ts
@@ -0,0 +1,51 @@
+import { inject, injectable } from "tsyringe";
+import OperatorFactory from "../OperatorFactory";
+import { AddonOperatorFactoryChain } from "./addons";
+import { ClipboardOperatorFactoryChain } from "./clipboard";
+import { FindOperatorFactoryChain } from "./find";
+import { FocusOperatorFactoryChain } from "./focus";
+import { MarkOperatorFactoryChain } from "./mark";
+import { ScrollOperatorFactoryChain } from "./scroll";
+import { FollowOperatorFactoryChain } from "./follow";
+import BackgroundOperationOperator from "./BackgroundOperationOperator";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import { Operation } from "../../../shared/operations";
+import OperationClient from "../../client/OperationClient";
+
+@injectable()
+export default class OperatorFactoryImpl implements OperatorFactory {
+ private readonly factoryChains: OperatorFactoryChain[];
+
+ constructor(
+ addonOperatorFactoryChain: AddonOperatorFactoryChain,
+ clipboardOperatorFactoryChain: ClipboardOperatorFactoryChain,
+ findOperatorFactoryChain: FindOperatorFactoryChain,
+ focusOperatorFactoryChain: FocusOperatorFactoryChain,
+ followOperatorFactoryChain: FollowOperatorFactoryChain,
+ markOperatorFactoryChain: MarkOperatorFactoryChain,
+ scrollOperatorFactoryChain: ScrollOperatorFactoryChain,
+ @inject("OperationClient")
+ private readonly operationClient: OperationClient
+ ) {
+ this.factoryChains = [
+ addonOperatorFactoryChain,
+ clipboardOperatorFactoryChain,
+ findOperatorFactoryChain,
+ focusOperatorFactoryChain,
+ followOperatorFactoryChain,
+ markOperatorFactoryChain,
+ scrollOperatorFactoryChain,
+ ];
+ }
+
+ create(op: Operation, repeat: number): Operator {
+ for (const chain of this.factoryChains) {
+ const operator = chain.create(op, repeat);
+ if (operator != null) {
+ return operator;
+ }
+ }
+ return new BackgroundOperationOperator(this.operationClient, repeat, op);
+ }
+}
diff --git a/src/content/operators/impls/RepeatOperator.ts b/src/content/operators/impls/RepeatOperator.ts
new file mode 100644
index 0000000..efe2faf
--- /dev/null
+++ b/src/content/operators/impls/RepeatOperator.ts
@@ -0,0 +1,14 @@
+import Operator from "../Operator";
+
+export default class RepeatOperator implements Operator {
+ constructor(
+ private readonly operator: Operator,
+ private readonly repeat: number
+ ) {}
+
+ async run(): Promise<void> {
+ for (let i = 0; i < this.repeat; ++i) {
+ this.operator.run();
+ }
+ }
+}
diff --git a/src/content/operators/impls/addons.ts b/src/content/operators/impls/addons.ts
new file mode 100644
index 0000000..959da43
--- /dev/null
+++ b/src/content/operators/impls/addons.ts
@@ -0,0 +1,74 @@
+import { inject, injectable } from "tsyringe";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import AddonIndicatorClient from "../../client/AddonIndicatorClient";
+import AddonEnabledRepository from "../../repositories/AddonEnabledRepository";
+import * as operations from "../../../shared/operations";
+
+export class EnableAddonOperator implements Operator {
+ constructor(
+ private readonly indicator: AddonIndicatorClient,
+ private readonly repository: AddonEnabledRepository
+ ) {}
+
+ async run(): Promise<void> {
+ this.repository.set(true);
+ await this.indicator.setEnabled(true);
+ }
+}
+
+export class DisableAddonOperator implements Operator {
+ constructor(
+ private readonly indicator: AddonIndicatorClient,
+ private readonly repository: AddonEnabledRepository
+ ) {}
+
+ async run(): Promise<void> {
+ this.repository.set(false);
+ await this.indicator.setEnabled(false);
+ }
+}
+
+export class ToggleAddonOperator implements Operator {
+ constructor(
+ private readonly indicator: AddonIndicatorClient,
+ private readonly repository: AddonEnabledRepository
+ ) {}
+
+ async run(): Promise<void> {
+ const current = this.repository.get();
+ this.repository.set(!current);
+ await this.indicator.setEnabled(!current);
+ }
+}
+
+@injectable()
+export class AddonOperatorFactoryChain implements OperatorFactoryChain {
+ constructor(
+ @inject("AddonIndicatorClient")
+ private readonly addonIndicatorClient: AddonIndicatorClient,
+ @inject("AddonEnabledRepository")
+ private readonly addonEnabledRepository: AddonEnabledRepository
+ ) {}
+
+ create(op: operations.Operation, _repeat: number): Operator | null {
+ switch (op.type) {
+ case operations.ADDON_ENABLE:
+ return new EnableAddonOperator(
+ this.addonIndicatorClient,
+ this.addonEnabledRepository
+ );
+ case operations.ADDON_DISABLE:
+ return new DisableAddonOperator(
+ this.addonIndicatorClient,
+ this.addonEnabledRepository
+ );
+ case operations.ADDON_TOGGLE_ENABLED:
+ return new ToggleAddonOperator(
+ this.addonIndicatorClient,
+ this.addonEnabledRepository
+ );
+ }
+ return null;
+ }
+}
diff --git a/src/content/operators/impls/clipboard.ts b/src/content/operators/impls/clipboard.ts
new file mode 100644
index 0000000..26bdba0
--- /dev/null
+++ b/src/content/operators/impls/clipboard.ts
@@ -0,0 +1,74 @@
+import { inject, injectable } from "tsyringe";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import ClipboardRepository from "../../repositories/ClipboardRepository";
+import SettingRepository from "../../repositories/SettingRepository";
+import ConsoleClient from "../../client/ConsoleClient";
+import OperationClient from "../../client/OperationClient";
+import * as urls from "../../../shared/urls";
+import * as operations from "../../../shared/operations";
+
+export class YankURLOperator implements Operator {
+ constructor(
+ private readonly repository: ClipboardRepository,
+ private readonly consoleClient: ConsoleClient
+ ) {}
+
+ async run(): Promise<void> {
+ const url = window.location.href;
+ this.repository.write(url);
+ await this.consoleClient.info("Yanked " + url);
+ }
+}
+
+export class PasteOperator implements Operator {
+ constructor(
+ private readonly repository: ClipboardRepository,
+ private readonly settingRepository: SettingRepository,
+ private readonly operationClient: OperationClient,
+ private readonly newTab: boolean
+ ) {}
+
+ async run(): Promise<void> {
+ const search = this.settingRepository.get().search;
+ const text = this.repository.read();
+ const url = urls.searchUrl(text, search);
+
+ // NOTE: Repeat pasting from clipboard instead of opening a certain url.
+ // 'Repeat last' command is implemented in the background script and cannot
+ // access to clipboard until Firefox 63.
+ await this.operationClient.internalOpenUrl(url, this.newTab);
+ }
+}
+
+@injectable()
+export class ClipboardOperatorFactoryChain implements OperatorFactoryChain {
+ constructor(
+ @inject("ClipboardRepository")
+ private readonly clipboardRepository: ClipboardRepository,
+ @inject("ConsoleClient")
+ private readonly consoleClient: ConsoleClient,
+ @inject("OperationClient")
+ private readonly operationClinet: OperationClient,
+ @inject("SettingRepository")
+ private readonly settingRepository: SettingRepository
+ ) {}
+
+ create(op: operations.Operation, _repeat: number): Operator | null {
+ switch (op.type) {
+ case operations.URLS_YANK:
+ return new YankURLOperator(
+ this.clipboardRepository,
+ this.consoleClient
+ );
+ case operations.URLS_PASTE:
+ return new PasteOperator(
+ this.clipboardRepository,
+ this.settingRepository,
+ this.operationClinet,
+ op.newTab
+ );
+ }
+ return null;
+ }
+}
diff --git a/src/content/operators/impls/find.ts b/src/content/operators/impls/find.ts
new file mode 100644
index 0000000..82310bc
--- /dev/null
+++ b/src/content/operators/impls/find.ts
@@ -0,0 +1,45 @@
+import { inject, injectable } from "tsyringe";
+import RepeatOperator from "./RepeatOperator";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import FindMasterClient from "../../client/FindMasterClient";
+import * as operations from "../../../shared/operations";
+
+export class FindNextOperator implements Operator {
+ constructor(private readonly findMasterClient: FindMasterClient) {}
+
+ async run(): Promise<void> {
+ this.findMasterClient.findNext();
+ }
+}
+
+export class FindPrevOperator implements Operator {
+ constructor(private readonly findMasterClient: FindMasterClient) {}
+
+ async run(): Promise<void> {
+ this.findMasterClient.findPrev();
+ }
+}
+
+@injectable()
+export class FindOperatorFactoryChain implements OperatorFactoryChain {
+ constructor(
+ @inject("FindMasterClient")
+ private readonly findMasterClient: FindMasterClient
+ ) {}
+ create(op: operations.Operation, repeat: number): Operator | null {
+ switch (op.type) {
+ case operations.FIND_NEXT:
+ return new RepeatOperator(
+ new FindNextOperator(this.findMasterClient),
+ repeat
+ );
+ case operations.FIND_PREV:
+ return new RepeatOperator(
+ new FindPrevOperator(this.findMasterClient),
+ repeat
+ );
+ }
+ return null;
+ }
+}
diff --git a/src/content/operators/impls/focus.ts b/src/content/operators/impls/focus.ts
new file mode 100644
index 0000000..ea8e27d
--- /dev/null
+++ b/src/content/operators/impls/focus.ts
@@ -0,0 +1,29 @@
+import { inject, injectable } from "tsyringe";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import FocusPresenter from "../../presenters/FocusPresenter";
+import * as operations from "../../../shared/operations";
+
+export class FocusOperator implements Operator {
+ constructor(private readonly presenter: FocusPresenter) {}
+
+ async run(): Promise<void> {
+ this.presenter.focusFirstElement();
+ }
+}
+
+@injectable()
+export class FocusOperatorFactoryChain implements OperatorFactoryChain {
+ constructor(
+ @inject("FocusPresenter")
+ private readonly focusPresenter: FocusPresenter
+ ) {}
+
+ create(op: operations.Operation, _repeat: number): Operator | null {
+ switch (op.type) {
+ case operations.FOCUS_INPUT:
+ return new FocusOperator(this.focusPresenter);
+ }
+ return null;
+ }
+}
diff --git a/src/content/operators/impls/follow.ts b/src/content/operators/impls/follow.ts
new file mode 100644
index 0000000..6d3fadc
--- /dev/null
+++ b/src/content/operators/impls/follow.ts
@@ -0,0 +1,37 @@
+import { inject, injectable } from "tsyringe";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import FollowMasterClient from "../../client/FollowMasterClient";
+import * as operations from "../../../shared/operations";
+
+export class StartFollowOperator implements Operator {
+ constructor(
+ private readonly followMasterClient: FollowMasterClient,
+ private readonly newTab: boolean,
+ private readonly background: boolean
+ ) {}
+
+ async run(): Promise<void> {
+ this.followMasterClient.startFollow(this.newTab, this.background);
+ }
+}
+
+@injectable()
+export class FollowOperatorFactoryChain implements OperatorFactoryChain {
+ constructor(
+ @inject("FollowMasterClient")
+ private followMasterClient: FollowMasterClient
+ ) {}
+
+ create(op: operations.Operation, _repeat: number): Operator | null {
+ switch (op.type) {
+ case operations.FOLLOW_START:
+ return new StartFollowOperator(
+ this.followMasterClient,
+ op.newTab,
+ op.background
+ );
+ }
+ return null;
+ }
+}
diff --git a/src/content/operators/impls/mark.ts b/src/content/operators/impls/mark.ts
new file mode 100644
index 0000000..d90aba9
--- /dev/null
+++ b/src/content/operators/impls/mark.ts
@@ -0,0 +1,39 @@
+import { inject, injectable } from "tsyringe";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import MarkKeyRepository from "../../repositories/MarkKeyRepository";
+import * as operations from "../../../shared/operations";
+
+export class EnableSetMarkOperator implements Operator {
+ constructor(private readonly repository: MarkKeyRepository) {}
+
+ async run(): Promise<void> {
+ this.repository.enableSetMode();
+ }
+}
+
+export class EnableJumpMarkOperator implements Operator {
+ constructor(private readonly repository: MarkKeyRepository) {}
+
+ async run(): Promise<void> {
+ this.repository.enableJumpMode();
+ }
+}
+
+@injectable()
+export class MarkOperatorFactoryChain implements OperatorFactoryChain {
+ constructor(
+ @inject("MarkKeyRepository")
+ private readonly markKeyRepository: MarkKeyRepository
+ ) {}
+
+ create(op: operations.Operation, _repeat: number): Operator | null {
+ switch (op.type) {
+ case operations.MARK_SET_PREFIX:
+ return new EnableSetMarkOperator(this.markKeyRepository);
+ case operations.MARK_JUMP_PREFIX:
+ return new EnableJumpMarkOperator(this.markKeyRepository);
+ }
+ return null;
+ }
+}
diff --git a/src/content/operators/impls/scroll.ts b/src/content/operators/impls/scroll.ts
new file mode 100644
index 0000000..96963be
--- /dev/null
+++ b/src/content/operators/impls/scroll.ts
@@ -0,0 +1,183 @@
+import { inject, injectable } from "tsyringe";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import ScrollPresenter from "../../presenters/ScrollPresenter";
+import SettingRepository from "../../repositories/SettingRepository";
+import * as operations from "../../../shared/operations";
+
+class AbstractScrollOperator {
+ constructor(private readonly settingRepository: SettingRepository) {}
+
+ protected getSmoothScroll(): boolean {
+ const settings = this.settingRepository.get();
+ return settings.properties.smoothscroll;
+ }
+}
+
+export class VerticalScrollOperator
+ extends AbstractScrollOperator
+ implements Operator {
+ constructor(
+ private readonly presenter: ScrollPresenter,
+ settingRepository: SettingRepository,
+ private readonly count: number
+ ) {
+ super(settingRepository);
+ }
+
+ async run(): Promise<void> {
+ const smooth = this.getSmoothScroll();
+ this.presenter.scrollVertically(this.count, smooth);
+ }
+}
+
+export class HorizonalScrollOperator
+ extends AbstractScrollOperator
+ implements Operator {
+ constructor(
+ private readonly presenter: ScrollPresenter,
+ settingRepository: SettingRepository,
+ private readonly count: number
+ ) {
+ super(settingRepository);
+ }
+
+ async run(): Promise<void> {
+ const smooth = this.getSmoothScroll();
+ this.presenter.scrollHorizonally(this.count, smooth);
+ }
+}
+
+export class PageScrollOperator
+ extends AbstractScrollOperator
+ implements Operator {
+ constructor(
+ private readonly presenter: ScrollPresenter,
+ settingRepository: SettingRepository,
+ private readonly count: number
+ ) {
+ super(settingRepository);
+ }
+
+ async run(): Promise<void> {
+ const smooth = this.getSmoothScroll();
+ this.presenter.scrollPages(this.count, smooth);
+ }
+}
+
+export class ScrollToTopOperator
+ extends AbstractScrollOperator
+ implements Operator {
+ constructor(
+ private readonly presenter: ScrollPresenter,
+ settingRepository: SettingRepository
+ ) {
+ super(settingRepository);
+ }
+
+ async run(): Promise<void> {
+ const smooth = this.getSmoothScroll();
+ this.presenter.scrollToTop(smooth);
+ }
+}
+
+export class ScrollToBottomOperator
+ extends AbstractScrollOperator
+ implements Operator {
+ constructor(
+ private readonly presenter: ScrollPresenter,
+ settingRepository: SettingRepository
+ ) {
+ super(settingRepository);
+ }
+
+ async run(): Promise<void> {
+ const smooth = this.getSmoothScroll();
+ this.presenter.scrollToBottom(smooth);
+ }
+}
+
+export class ScrollToHomeOperator
+ extends AbstractScrollOperator
+ implements Operator {
+ constructor(
+ private readonly presenter: ScrollPresenter,
+ settingRepository: SettingRepository
+ ) {
+ super(settingRepository);
+ }
+
+ async run(): Promise<void> {
+ const smooth = this.getSmoothScroll();
+ this.presenter.scrollToHome(smooth);
+ }
+}
+
+export class ScrollToEndOperator
+ extends AbstractScrollOperator
+ implements Operator {
+ constructor(
+ private readonly presenter: ScrollPresenter,
+ settingRepository: SettingRepository
+ ) {
+ super(settingRepository);
+ }
+
+ async run(): Promise<void> {
+ const smooth = this.getSmoothScroll();
+ this.presenter.scrollToEnd(smooth);
+ }
+}
+
+@injectable()
+export class ScrollOperatorFactoryChain implements OperatorFactoryChain {
+ constructor(
+ @inject("ScrollPresenter")
+ private readonly scrollPresenter: ScrollPresenter,
+ @inject("SettingRepository")
+ private readonly settingRepository: SettingRepository
+ ) {}
+ create(op: operations.Operation, repeat: number): Operator | null {
+ switch (op.type) {
+ case operations.SCROLL_VERTICALLY:
+ return new VerticalScrollOperator(
+ this.scrollPresenter,
+ this.settingRepository,
+ op.count * repeat
+ );
+ case operations.SCROLL_HORIZONALLY:
+ return new HorizonalScrollOperator(
+ this.scrollPresenter,
+ this.settingRepository,
+ op.count * repeat
+ );
+ case operations.SCROLL_PAGES:
+ return new PageScrollOperator(
+ this.scrollPresenter,
+ this.settingRepository,
+ op.count * repeat
+ );
+ case operations.SCROLL_TOP:
+ return new ScrollToTopOperator(
+ this.scrollPresenter,
+ this.settingRepository
+ );
+ case operations.SCROLL_BOTTOM:
+ return new ScrollToBottomOperator(
+ this.scrollPresenter,
+ this.settingRepository
+ );
+ case operations.SCROLL_HOME:
+ return new ScrollToHomeOperator(
+ this.scrollPresenter,
+ this.settingRepository
+ );
+ case operations.SCROLL_END:
+ return new ScrollToEndOperator(
+ this.scrollPresenter,
+ this.settingRepository
+ );
+ }
+ return null;
+ }
+}