Merge pull request #12163 from Snuffleupagus/improve-PDFAttachmentViewer-render

Re-factor the dispatching of "attachmentsloaded" events, when the PDF document contains no "regular" attachments
This commit is contained in:
Tim van der Meij 2020-08-04 23:59:20 +02:00 committed by GitHub
commit 85982c45dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 30 deletions

View File

@ -55,10 +55,14 @@ class PDFAttachmentViewer {
this.container.textContent = ""; this.container.textContent = "";
if (!keepRenderedCapability) { if (!keepRenderedCapability) {
// NOTE: The *only* situation in which the `_renderedCapability` should // The only situation in which the `_renderedCapability` should *not* be
// not be replaced is when appending file attachment annotations. // replaced is when appending FileAttachment annotations.
this._renderedCapability = createPromiseCapability(); this._renderedCapability = createPromiseCapability();
} }
if (this._pendingDispatchEvent) {
clearTimeout(this._pendingDispatchEvent);
}
this._pendingDispatchEvent = null;
} }
/** /**
@ -67,6 +71,25 @@ class PDFAttachmentViewer {
_dispatchEvent(attachmentsCount) { _dispatchEvent(attachmentsCount) {
this._renderedCapability.resolve(); this._renderedCapability.resolve();
if (this._pendingDispatchEvent) {
clearTimeout(this._pendingDispatchEvent);
this._pendingDispatchEvent = null;
}
if (attachmentsCount === 0) {
// 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;
});
return;
}
this.eventBus.dispatch("attachmentsloaded", { this.eventBus.dispatch("attachmentsloaded", {
source: this, source: this,
attachmentsCount, attachmentsCount,
@ -129,23 +152,22 @@ class PDFAttachmentViewer {
* @param {PDFAttachmentViewerRenderParameters} params * @param {PDFAttachmentViewerRenderParameters} params
*/ */
render({ attachments, keepRenderedCapability = false }) { render({ attachments, keepRenderedCapability = false }) {
let attachmentsCount = 0;
if (this.attachments) { if (this.attachments) {
this.reset(keepRenderedCapability === true); this.reset(keepRenderedCapability === true);
} }
this.attachments = attachments || null; this.attachments = attachments || null;
if (!attachments) { if (!attachments) {
this._dispatchEvent(attachmentsCount); this._dispatchEvent(/* attachmentsCount = */ 0);
return; return;
} }
const names = Object.keys(attachments).sort(function (a, b) { const names = Object.keys(attachments).sort(function (a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase()); return a.toLowerCase().localeCompare(b.toLowerCase());
}); });
attachmentsCount = names.length; const attachmentsCount = names.length;
const fragment = document.createDocumentFragment();
for (let i = 0; i < attachmentsCount; i++) { for (let i = 0; i < attachmentsCount; i++) {
const item = attachments[names[i]]; const item = attachments[names[i]];
const filename = removeNullCharacters(getFilenameFromUrl(item.filename)); const filename = removeNullCharacters(getFilenameFromUrl(item.filename));
@ -164,8 +186,9 @@ class PDFAttachmentViewer {
} }
div.appendChild(button); div.appendChild(button);
this.container.appendChild(div); fragment.appendChild(div);
} }
this.container.appendChild(fragment);
this._dispatchEvent(attachmentsCount); this._dispatchEvent(attachmentsCount);
} }
@ -175,7 +198,12 @@ class PDFAttachmentViewer {
* @private * @private
*/ */
_appendAttachment({ id, filename, content }) { _appendAttachment({ id, filename, content }) {
this._renderedCapability.promise.then(() => { const renderedPromise = this._renderedCapability.promise;
renderedPromise.then(() => {
if (renderedPromise !== this._renderedCapability.promise) {
return; // The FileAttachment annotation belongs to a previous document.
}
let attachments = this.attachments; let attachments = this.attachments;
if (!attachments) { if (!attachments) {

View File

@ -445,31 +445,17 @@ class PDFSidebar {
}); });
this.eventBus._on("attachmentsloaded", evt => { this.eventBus._on("attachmentsloaded", evt => {
if (evt.attachmentsCount) { const attachmentsCount = evt.attachmentsCount;
this.attachmentsButton.disabled = false;
this.attachmentsButton.disabled = !attachmentsCount;
if (attachmentsCount) {
this._showUINotification(SidebarView.ATTACHMENTS); this._showUINotification(SidebarView.ATTACHMENTS);
return; } else if (this.active === SidebarView.ATTACHMENTS) {
// If the attachments view was opened during document load, switch away
// from it if it turns out that the document has no attachments.
this.switchView(SidebarView.THUMBS);
} }
// Attempt to avoid temporarily disabling, and switching away from, the
// attachment view for documents that do not contain proper attachments
// but *only* FileAttachment annotations. Hence we defer those operations
// slightly to allow time for parsing any FileAttachment annotations that
// may be present on the *initially* rendered page of the document.
Promise.resolve().then(() => {
if (this.attachmentsView.hasChildNodes()) {
// FileAttachment annotations were appended to the attachment view.
return;
}
this.attachmentsButton.disabled = true;
if (this.active === SidebarView.ATTACHMENTS) {
// If the attachment view was opened during document load, switch away
// from it if it turns out that the document has no attachments.
this.switchView(SidebarView.THUMBS);
}
});
}); });
// Update the thumbnailViewer, if visible, when exiting presentation mode. // Update the thumbnailViewer, if visible, when exiting presentation mode.