aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShin'ya Ueoka <ueokande@i-beam.org>2021-07-05 21:31:58 +0900
committerShin'ya Ueoka <ueokande@i-beam.org>2021-07-05 21:32:47 +0900
commit05a19373e90976b82c2bd81626aee27a79eb4b2d (patch)
tree1b25a30fdd99ee97f2d833ec4c1d4a3d1dc3e070 /src
parent65cf6f0842d8d5933dc13b3767b1baf398d68cd5 (diff)
Implement backwards find
Diffstat (limited to 'src')
-rw-r--r--src/background/clients/FindClient.ts15
-rw-r--r--src/background/operators/impls/FindPrevOperator.ts86
2 files changed, 95 insertions, 6 deletions
diff --git a/src/background/clients/FindClient.ts b/src/background/clients/FindClient.ts
index 863c5ad..b46b964 100644
--- a/src/background/clients/FindClient.ts
+++ b/src/background/clients/FindClient.ts
@@ -3,6 +3,8 @@ import * as messages from "../../shared/messages";
export default interface FindClient {
findNext(tabId: number, frameId: number, keyword: string): Promise<boolean>;
+ findPrev(tabId: number, frameId: number, keyword: string): Promise<boolean>;
+
clearSelection(tabId: number, frameId: number): Promise<void>;
}
@@ -20,6 +22,19 @@ export class FindClientImpl implements FindClient {
return found;
}
+ async findPrev(
+ tabId: number,
+ frameId: number,
+ keyword: string
+ ): Promise<boolean> {
+ const found = (await browser.tabs.sendMessage(
+ tabId,
+ { type: messages.FIND_PREV, keyword },
+ { frameId }
+ )) as boolean;
+ return found;
+ }
+
clearSelection(tabId: number, frameId: number): Promise<void> {
return browser.tabs.sendMessage(
tabId,
diff --git a/src/background/operators/impls/FindPrevOperator.ts b/src/background/operators/impls/FindPrevOperator.ts
index 28238f6..822c386 100644
--- a/src/background/operators/impls/FindPrevOperator.ts
+++ b/src/background/operators/impls/FindPrevOperator.ts
@@ -7,14 +7,88 @@ import FramePresenter from "../../presenters/FramePresenter";
export default class FindPrevOperator implements Operator {
constructor(
- _tabPresenter: TabPresenter,
- _findRepository: FindRepository,
- _findClient: FindClient,
- _consoleClient: ConsoleClient,
- _framePresenter: FramePresenter
+ private readonly tabPresenter: TabPresenter,
+ private readonly findRepository: FindRepository,
+ private readonly findClient: FindClient,
+ private readonly consoleClient: ConsoleClient,
+ private readonly framePresenter: FramePresenter
) {}
async run(): Promise<void> {
- throw new Error("not implemented");
+ const tab = await this.tabPresenter.getCurrent();
+ const tabId = tab?.id;
+ if (tabId == null) {
+ return;
+ }
+
+ const state = await this.findRepository.getLocalState(tabId);
+ if (state) {
+ // 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 = state.frameIds
+ .slice(state.framePos)
+ .concat(
+ state.frameIds.slice(0, state.framePos),
+ state.frameIds[state.framePos]
+ );
+
+ for (let i = targetFrameIds.length - 1; i >= 0; --i) {
+ const found = await this.findClient.findPrev(
+ tabId,
+ targetFrameIds[i],
+ state.keyword
+ );
+ if (found) {
+ this.findRepository.setLocalState(tabId, {
+ ...state,
+ framePos: (i + state.framePos) % state.frameIds.length, // save current frame position or first
+ });
+ return;
+ }
+ this.findClient.clearSelection(tabId, targetFrameIds[i]);
+ }
+
+ // The keyword is gone.
+ this.consoleClient.showError(
+ tabId,
+ "Pattern not found: " + state.keyword
+ );
+ return;
+ }
+
+ const keyword = await this.findRepository.getGlobalKeyword();
+ if (keyword) {
+ const frameIds = await this.framePresenter.getAllFrameIds(tabId);
+ for (const frameId of frameIds) {
+ await this.findClient.clearSelection(tabId, frameId);
+ }
+
+ for (let framePos = frameIds.length - 1; framePos >= 0; --framePos) {
+ const found = await this.findClient.findPrev(
+ tabId,
+ frameIds[framePos],
+ keyword
+ );
+ if (found) {
+ await this.findRepository.setLocalState(tabId, {
+ frameIds,
+ framePos,
+ 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");
}
}