From dacea5296651a349cf1b6cdfce133811335cf8dd Mon Sep 17 00:00:00 2001
From: Jonas Jenwald <jonas.jenwald@gmail.com>
Date: Sat, 7 May 2022 11:37:46 +0200
Subject: [PATCH] Try to fix dispatching of "attachmentsloaded"-events, when
 the document contains no "regular" attachments (PR 8788, 12163 follow-up)

*This patch can be tested, in the viewer, using the `annotation-fileattachment.pdf` document from the test-suite.*

It seems that the code to delay dispatching of the "attachmentsloaded"-event, when `attachmentsCount === 0`, is now effectively broken.[1]
Rather than only using an arbitrary timeout, the new code will instead wait for an "annotationlayerrendered"-event and only *fallback* to using a timeout.

---
[1] The timing of the annotationLayer-rendering changed slightly in PR 14247, and the old code in `PDFAttachmentViewer` wasn't good enough to handle that.
---
 web/pdf_attachment_viewer.js | 32 +++++++++++++++-----------------
 1 file changed, 15 insertions(+), 17 deletions(-)

diff --git a/web/pdf_attachment_viewer.js b/web/pdf_attachment_viewer.js
index 5cf138728..bc5ecacb5 100644
--- a/web/pdf_attachment_viewer.js
+++ b/web/pdf_attachment_viewer.js
@@ -15,6 +15,7 @@
 
 import { createPromiseCapability, getFilenameFromUrl } from "pdfjs-lib";
 import { BaseTreeViewer } from "./base_tree_viewer.js";
+import { waitOnEventOrTimeout } from "./event_utils.js";
 
 /**
  * @typedef {Object} PDFAttachmentViewerOptions
@@ -51,36 +52,33 @@ class PDFAttachmentViewer extends BaseTreeViewer {
       // replaced is when appending FileAttachment annotations.
       this._renderedCapability = createPromiseCapability();
     }
-    if (this._pendingDispatchEvent) {
-      clearTimeout(this._pendingDispatchEvent);
-    }
-    this._pendingDispatchEvent = null;
+    this._pendingDispatchEvent = false;
   }
 
   /**
    * @private
    */
-  _dispatchEvent(attachmentsCount) {
+  async _dispatchEvent(attachmentsCount) {
     this._renderedCapability.resolve();
 
-    if (this._pendingDispatchEvent) {
-      clearTimeout(this._pendingDispatchEvent);
-      this._pendingDispatchEvent = null;
-    }
-    if (attachmentsCount === 0) {
+    if (attachmentsCount === 0 && !this._pendingDispatchEvent) {
       // Delay the event when no "regular" attachments exist, to allow time for
       // parsing of any FileAttachment annotations that may be present on the
       // *initially* rendered page; this reduces the likelihood of temporarily
       // disabling the attachmentsView when the `PDFSidebar` handles the event.
-      this._pendingDispatchEvent = setTimeout(() => {
-        this.eventBus.dispatch("attachmentsloaded", {
-          source: this,
-          attachmentsCount: 0,
-        });
-        this._pendingDispatchEvent = null;
+      this._pendingDispatchEvent = true;
+
+      await waitOnEventOrTimeout({
+        target: this.eventBus,
+        name: "annotationlayerrendered",
+        delay: 1000,
       });
-      return;
+
+      if (!this._pendingDispatchEvent) {
+        return; // There was already another `_dispatchEvent`-call`.
+      }
     }
+    this._pendingDispatchEvent = false;
 
     this.eventBus.dispatch("attachmentsloaded", {
       source: this,