diff options
Diffstat (limited to 'src/content/operators/impls')
-rw-r--r-- | src/content/operators/impls/BackgroundOperationOperator.ts | 15 | ||||
-rw-r--r-- | src/content/operators/impls/OperatorFactoryImpl.ts | 51 | ||||
-rw-r--r-- | src/content/operators/impls/RepeatOperator.ts | 14 | ||||
-rw-r--r-- | src/content/operators/impls/addons.ts | 74 | ||||
-rw-r--r-- | src/content/operators/impls/clipboard.ts | 74 | ||||
-rw-r--r-- | src/content/operators/impls/find.ts | 45 | ||||
-rw-r--r-- | src/content/operators/impls/focus.ts | 29 | ||||
-rw-r--r-- | src/content/operators/impls/follow.ts | 37 | ||||
-rw-r--r-- | src/content/operators/impls/mark.ts | 39 | ||||
-rw-r--r-- | src/content/operators/impls/scroll.ts | 183 |
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; + } +} |