diff --git a/test/unit/pdf_find_controller_spec.js b/test/unit/pdf_find_controller_spec.js index bdb6ffd6e..b7f3b1861 100644 --- a/test/unit/pdf_find_controller_spec.js +++ b/test/unit/pdf_find_controller_spec.js @@ -51,7 +51,10 @@ class MockLinkService extends SimpleLinkService { } } -async function initPdfFindController(filename) { +async function initPdfFindController( + filename, + updateMatchesCountOnProgress = true +) { const loadingTask = getDocument( buildGetDocumentParams(filename || tracemonkeyFileName, { ...CMAP_PARAMS, @@ -67,6 +70,7 @@ async function initPdfFindController(filename) { const pdfFindController = new PDFFindController({ linkService, eventBus, + updateMatchesCountOnProgress, }); pdfFindController.setDocument(pdfDocument); // Enable searching. @@ -81,6 +85,7 @@ function testSearch({ selectedMatch, pageMatches = null, pageMatchesLength = null, + countUpdate = null, }) { return new Promise(function (resolve) { const eventState = Object.assign( @@ -125,6 +130,9 @@ function testSearch({ eventBus.on( "updatefindmatchescount", function onUpdateFindMatchesCount(evt) { + if (countUpdate) { + countUpdate[0] += 1; + } if (pdfFindController.pageMatches.length !== totalPages) { return; } @@ -191,6 +199,7 @@ function testEmptySearch({ eventBus, pdfFindController, state }) { describe("pdf_find_controller", function () { it("performs a normal search", async function () { const { eventBus, pdfFindController } = await initPdfFindController(); + const countUpdate = [0]; await testSearch({ eventBus, @@ -203,7 +212,34 @@ describe("pdf_find_controller", function () { pageIndex: 0, matchIndex: 0, }, + countUpdate, }); + + expect(countUpdate[0]).toBe(9); + }); + + it("performs a normal search but the total counts is only updated one time", async function () { + const { eventBus, pdfFindController } = await initPdfFindController( + null, + false + ); + const countUpdate = [0]; + + await testSearch({ + eventBus, + pdfFindController, + state: { + query: "Dynamic", + }, + matchesPerPage: [11, 5, 0, 3, 0, 0, 0, 1, 1, 1, 0, 3, 4, 4], + selectedMatch: { + pageIndex: 0, + matchIndex: 0, + }, + countUpdate, + }); + + expect(countUpdate[0]).toBe(1); }); it("performs a normal search and finds the previous result", async function () { diff --git a/web/app.js b/web/app.js index e9389632d..11b7b0f7e 100644 --- a/web/app.js +++ b/web/app.js @@ -458,6 +458,8 @@ const PDFViewerApplication = { const findController = new PDFFindController({ linkService: pdfLinkService, eventBus, + updateMatchesCountOnProgress: + typeof PDFJSDev === "undefined" || !PDFJSDev.test("GECKOVIEW"), }); this.findController = findController; diff --git a/web/pdf_find_controller.js b/web/pdf_find_controller.js index 0ea48f124..2fcfbce7d 100644 --- a/web/pdf_find_controller.js +++ b/web/pdf_find_controller.js @@ -339,18 +339,26 @@ function getOriginalIndex(diffs, pos, len) { * @typedef {Object} PDFFindControllerOptions * @property {IPDFLinkService} linkService - The navigation/linking service. * @property {EventBus} eventBus - The application event bus. + * @property {boolean} updateMatchesCountOnProgress - True if the matches + * count must be updated on progress or only when the last page is reached. + * The default value is `true`. */ /** * Provides search functionality to find a given string in a PDF document. */ class PDFFindController { + #updateMatchesCountOnProgress = true; + + #visitedPagesCount = 0; + /** * @param {PDFFindControllerOptions} options */ - constructor({ linkService, eventBus }) { + constructor({ linkService, eventBus, updateMatchesCountOnProgress = true }) { this._linkService = linkService; this._eventBus = eventBus; + this.#updateMatchesCountOnProgress = updateMatchesCountOnProgress; this.#reset(); eventBus._on("find", this.#onFind.bind(this)); @@ -489,6 +497,7 @@ class PDFFindController { this._pdfDocument = null; this._pageMatches = []; this._pageMatchesLength = []; + this.#visitedPagesCount = 0; this._state = null; // Currently selected match. this._selected = { @@ -742,8 +751,14 @@ class PDFFindController { // Update the match count. const pageMatchesCount = this._pageMatches[pageIndex].length; - if (pageMatchesCount > 0) { - this._matchesCountTotal += pageMatchesCount; + this._matchesCountTotal += pageMatchesCount; + if (this.#updateMatchesCountOnProgress) { + if (pageMatchesCount > 0) { + this.#updateUIResultsCount(); + } + } else if (++this.#visitedPagesCount === this._linkService.pagesCount) { + // For example, in GeckoView we want to have only the final update because + // the Java side provides only one object to update the counts. this.#updateUIResultsCount(); } } @@ -838,6 +853,7 @@ class PDFFindController { this._resumePageIdx = null; this._pageMatches.length = 0; this._pageMatchesLength.length = 0; + this.#visitedPagesCount = 0; this._matchesCountTotal = 0; this.#updateAllPages(); // Wipe out any previously highlighted matches.