aboutsummaryrefslogtreecommitdiff
path: root/src/background/operators
diff options
context:
space:
mode:
Diffstat (limited to 'src/background/operators')
-rw-r--r--src/background/operators/impls/FindNextOperator.ts91
-rw-r--r--src/background/operators/impls/FindOperatorFactoryChain.ts49
-rw-r--r--src/background/operators/impls/FindPrevOperator.ts92
-rw-r--r--src/background/operators/impls/OperatorFactoryImpl.ts3
4 files changed, 235 insertions, 0 deletions
diff --git a/src/background/operators/impls/FindNextOperator.ts b/src/background/operators/impls/FindNextOperator.ts
new file mode 100644
index 0000000..99f1759
--- /dev/null
+++ b/src/background/operators/impls/FindNextOperator.ts
@@ -0,0 +1,91 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import FindRepository from "../../repositories/FindRepository";
+import FindClient from "../../clients/FindClient";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+import ReadyFrameRepository from "../../repositories/ReadyFrameRepository";
+
+export default class FindNextOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly findRepository: FindRepository,
+ private readonly findClient: FindClient,
+ private readonly consoleClient: ConsoleClient,
+ private readonly frameRepository: ReadyFrameRepository
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ const tabId = tab?.id;
+ if (tabId == null) {
+ return;
+ }
+
+ const frameIds = await this.frameRepository.getFrameIds(tabId);
+ if (typeof frameIds === "undefined") {
+ // No frames are ready
+ return;
+ }
+
+ const state = await this.findRepository.getLocalState(tabId);
+ if (state) {
+ const framePos = frameIds.indexOf(state.frameId);
+ if (framePos !== -1) {
+ // Start to find the keyword from the current frame which last found on,
+ // and concat it to end of frame ids to perform a wrap-search
+ //
+ // ,- keyword should be in this frame
+ // |
+ // [100, 101, 0, 100]
+ // |
+ // `- continue from frame id 100
+ //
+ const targetFrameIds = frameIds
+ .slice(framePos)
+ .concat(frameIds.slice(0, framePos), frameIds[framePos]);
+
+ for (const frameId of targetFrameIds) {
+ const found = await this.findClient.findNext(
+ tabId,
+ frameId,
+ state.keyword
+ );
+ if (found) {
+ this.findRepository.setLocalState(tabId, {
+ keyword: state.keyword,
+ frameId,
+ });
+ return;
+ }
+ this.findClient.clearSelection(tabId, frameId);
+ }
+
+ // The keyword is gone.
+ this.consoleClient.showError(
+ tabId,
+ "Pattern not found: " + state.keyword
+ );
+ return;
+ }
+ }
+
+ const keyword = await this.findRepository.getGlobalKeyword();
+ if (keyword) {
+ for (const frameId of frameIds) {
+ await this.findClient.clearSelection(tabId, frameId);
+ }
+
+ for (const frameId of frameIds) {
+ const found = await this.findClient.findNext(tabId, frameId, keyword);
+ if (found) {
+ await this.findRepository.setLocalState(tabId, { frameId, keyword });
+ await this.consoleClient.showInfo(tabId, "Pattern found: " + keyword);
+ return;
+ }
+ }
+ this.consoleClient.showError(tabId, "Pattern not found: " + keyword);
+ return;
+ }
+ await this.consoleClient.showError(tabId, "No previous search keywords");
+ }
+}
diff --git a/src/background/operators/impls/FindOperatorFactoryChain.ts b/src/background/operators/impls/FindOperatorFactoryChain.ts
new file mode 100644
index 0000000..cc169dd
--- /dev/null
+++ b/src/background/operators/impls/FindOperatorFactoryChain.ts
@@ -0,0 +1,49 @@
+import { inject, injectable } from "tsyringe";
+import Operator from "../Operator";
+import OperatorFactoryChain from "../OperatorFactoryChain";
+import TabPresenter from "../../presenters/TabPresenter";
+import * as operations from "../../../shared/operations";
+import FindNextOperator from "./FindNextOperator";
+import FindPrevOperator from "./FindPrevOperator";
+import FindRepository from "../../repositories/FindRepository";
+import FindClient from "../../clients/FindClient";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+import ReadyFrameRepository from "../../repositories/ReadyFrameRepository";
+
+@injectable()
+export default class FindOperatorFactoryChain implements OperatorFactoryChain {
+ constructor(
+ @inject("TabPresenter")
+ private readonly tabPresenter: TabPresenter,
+ @inject("FindRepository")
+ private readonly findRepository: FindRepository,
+ @inject("FindClient")
+ private readonly findClient: FindClient,
+ @inject("ConsoleClient")
+ private readonly consoleClient: ConsoleClient,
+ @inject("ReadyFrameRepository")
+ private readonly frameRepository: ReadyFrameRepository
+ ) {}
+
+ create(op: operations.Operation): Operator | null {
+ switch (op.type) {
+ case operations.FIND_NEXT:
+ return new FindNextOperator(
+ this.tabPresenter,
+ this.findRepository,
+ this.findClient,
+ this.consoleClient,
+ this.frameRepository
+ );
+ case operations.FIND_PREV:
+ return new FindPrevOperator(
+ this.tabPresenter,
+ this.findRepository,
+ this.findClient,
+ this.consoleClient,
+ this.frameRepository
+ );
+ }
+ return null;
+ }
+}
diff --git a/src/background/operators/impls/FindPrevOperator.ts b/src/background/operators/impls/FindPrevOperator.ts
new file mode 100644
index 0000000..f8506b9
--- /dev/null
+++ b/src/background/operators/impls/FindPrevOperator.ts
@@ -0,0 +1,92 @@
+import Operator from "../Operator";
+import TabPresenter from "../../presenters/TabPresenter";
+import FindRepository from "../../repositories/FindRepository";
+import FindClient from "../../clients/FindClient";
+import ConsoleClient from "../../infrastructures/ConsoleClient";
+import ReadyFrameRepository from "../../repositories/ReadyFrameRepository";
+
+export default class FindPrevOperator implements Operator {
+ constructor(
+ private readonly tabPresenter: TabPresenter,
+ private readonly findRepository: FindRepository,
+ private readonly findClient: FindClient,
+ private readonly consoleClient: ConsoleClient,
+ private readonly frameRepository: ReadyFrameRepository
+ ) {}
+
+ async run(): Promise<void> {
+ const tab = await this.tabPresenter.getCurrent();
+ const tabId = tab?.id;
+ if (tabId == null) {
+ return;
+ }
+
+ let frameIds = await this.frameRepository.getFrameIds(tabId);
+ if (typeof frameIds === "undefined") {
+ // No frames are ready
+ return;
+ }
+ frameIds = frameIds.slice(0).reverse();
+
+ const state = await this.findRepository.getLocalState(tabId);
+ if (state) {
+ const framePos = frameIds.indexOf(state.frameId);
+ if (framePos !== -1) {
+ // Start to find the keyword from the current frame which last found on,
+ // and concat it to end of frame ids to perform a wrap-search
+ //
+ // ,- keyword should be in this frame
+ // |
+ // [100, 101, 0, 100]
+ // |
+ // `- continue from frame id 100
+ //
+ const targetFrameIds = frameIds
+ .slice(framePos)
+ .concat(frameIds.slice(0, framePos), frameIds[framePos]);
+
+ for (const frameId of targetFrameIds) {
+ const found = await this.findClient.findPrev(
+ tabId,
+ frameId,
+ state.keyword
+ );
+ if (found) {
+ this.findRepository.setLocalState(tabId, {
+ keyword: state.keyword,
+ frameId,
+ });
+ return;
+ }
+ this.findClient.clearSelection(tabId, frameId);
+ }
+
+ // The keyword is gone.
+ this.consoleClient.showError(
+ tabId,
+ "Pattern not found: " + state.keyword
+ );
+ return;
+ }
+ }
+
+ const keyword = await this.findRepository.getGlobalKeyword();
+ if (keyword) {
+ for (const frameId of frameIds) {
+ await this.findClient.clearSelection(tabId, frameId);
+ }
+
+ for (const frameId of frameIds) {
+ const found = await this.findClient.findPrev(tabId, frameId, keyword);
+ if (found) {
+ await this.findRepository.setLocalState(tabId, { frameId, keyword });
+ await this.consoleClient.showInfo(tabId, "Pattern found: " + keyword);
+ return;
+ }
+ }
+ this.consoleClient.showError(tabId, "Pattern not found: " + keyword);
+ return;
+ }
+ await this.consoleClient.showError(tabId, "No previous search keywords");
+ }
+}
diff --git a/src/background/operators/impls/OperatorFactoryImpl.ts b/src/background/operators/impls/OperatorFactoryImpl.ts
index 34e7bb5..ce87491 100644
--- a/src/background/operators/impls/OperatorFactoryImpl.ts
+++ b/src/background/operators/impls/OperatorFactoryImpl.ts
@@ -8,6 +8,7 @@ import NavigateOperatorFactoryChain from "./NavigateOperatorFactoryChain";
import RepeatOperatorFactoryChain from "./RepeatOperatorFactoryChain";
import TabOperatorFactoryChain from "./TabOperatorFactoryChain";
import ZoomOperatorFactoryChain from "./ZoomOperatorFactoryChain";
+import FindOperatorFactoryChain from "./FindOperatorFactoryChain";
import * as operations from "../../../shared/operations";
@injectable()
@@ -20,6 +21,7 @@ export class OperatorFactoryImpl implements OperatorFactory {
navigateOperatorFactoryChain: NavigateOperatorFactoryChain,
tabOperatorFactoryChain: TabOperatorFactoryChain,
zoomOperatorFactoryChain: ZoomOperatorFactoryChain,
+ findOperatorFactoryChain: FindOperatorFactoryChain,
@inject(delay(() => RepeatOperatorFactoryChain))
repeatOperatorFactoryChain: RepeatOperatorFactoryChain
) {
@@ -30,6 +32,7 @@ export class OperatorFactoryImpl implements OperatorFactory {
repeatOperatorFactoryChain,
tabOperatorFactoryChain,
zoomOperatorFactoryChain,
+ findOperatorFactoryChain,
];
}