aboutsummaryrefslogtreecommitdiff
path: root/src/background/operators/impls/FindPrevOperator.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/background/operators/impls/FindPrevOperator.ts')
-rw-r--r--src/background/operators/impls/FindPrevOperator.ts86
1 files changed, 80 insertions, 6 deletions
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");
}
}