mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-22 16:18:08 +02:00
[api-minor][Editor] When switching to editing mode, redraw pages containing editable annotations
Right now, editable annotations are using their own canvas when they're drawn, but it induces several issues: - if the annotation has to be composed with the page then the canvas must be correctly composed with its parent. That means we should move the canvas under canvasWrapper and we should extract composing info from the drawing instructions... Currently it's the case with highlight annotations. - we use some extra memory for those canvas even if the user will never edit them, which the case for example when opening a pdf in Fenix. So with this patch, all the editable annotations are drawn on the canvas. When the user switches to editing mode, then the pages with some editable annotations are redrawn but without them: they'll be replaced by their counterpart in the annotation editor layer.
This commit is contained in:
parent
75129fd61a
commit
64635f3b35
13 changed files with 358 additions and 103 deletions
|
@ -182,6 +182,10 @@ class AnnotationLayerBuilder {
|
|||
this.div.hidden = true;
|
||||
}
|
||||
|
||||
hasEditableAnnotations() {
|
||||
return !!this.annotationLayer?.hasEditableAnnotations();
|
||||
}
|
||||
|
||||
#updatePresentationModeState(state) {
|
||||
if (!this.div) {
|
||||
return;
|
||||
|
|
|
@ -119,6 +119,8 @@ class PDFPageView {
|
|||
|
||||
#hasRestrictedScaling = false;
|
||||
|
||||
#isEditing = false;
|
||||
|
||||
#layerProperties = null;
|
||||
|
||||
#loadingId = null;
|
||||
|
@ -354,6 +356,10 @@ class PDFPageView {
|
|||
this.pdfPage?.cleanup();
|
||||
}
|
||||
|
||||
hasEditableAnnotations() {
|
||||
return !!this.annotationLayer?.hasEditableAnnotations();
|
||||
}
|
||||
|
||||
get _textHighlighter() {
|
||||
return shadow(
|
||||
this,
|
||||
|
@ -582,6 +588,20 @@ class PDFPageView {
|
|||
}
|
||||
}
|
||||
|
||||
toggleEditingMode(isEditing) {
|
||||
if (!this.hasEditableAnnotations()) {
|
||||
return;
|
||||
}
|
||||
this.#isEditing = isEditing;
|
||||
this.reset({
|
||||
keepZoomLayer: true,
|
||||
keepAnnotationLayer: true,
|
||||
keepAnnotationEditorLayer: true,
|
||||
keepXfaLayer: true,
|
||||
keepTextLayer: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} PDFPageViewUpdateParameters
|
||||
* @property {number} [scale] The new scale, if specified.
|
||||
|
@ -1037,6 +1057,7 @@ class PDFPageView {
|
|||
optionalContentConfigPromise: this._optionalContentConfigPromise,
|
||||
annotationCanvasMap: this._annotationCanvasMap,
|
||||
pageColors,
|
||||
isEditing: this.#isEditing,
|
||||
};
|
||||
const renderTask = (this.renderTask = pdfPage.render(renderContext));
|
||||
renderTask.onContinue = renderContinueCallback;
|
||||
|
|
|
@ -223,6 +223,10 @@ class PDFViewer {
|
|||
|
||||
#mlManager = null;
|
||||
|
||||
#onPageRenderedCallback = null;
|
||||
|
||||
#switchAnnotationEditorModeTimeoutId = null;
|
||||
|
||||
#getAllTextInProgress = false;
|
||||
|
||||
#hiddenCopyElement = null;
|
||||
|
@ -1117,6 +1121,10 @@ class PDFViewer {
|
|||
|
||||
this.#hiddenCopyElement?.remove();
|
||||
this.#hiddenCopyElement = null;
|
||||
|
||||
this.#onPageRenderedCallback = null;
|
||||
clearTimeout(this.#switchAnnotationEditorModeTimeoutId);
|
||||
this.#switchAnnotationEditorModeTimeoutId = null;
|
||||
}
|
||||
|
||||
#ensurePageViewVisible() {
|
||||
|
@ -1653,6 +1661,32 @@ class PDFViewer {
|
|||
});
|
||||
}
|
||||
|
||||
#switchToEditAnnotationMode() {
|
||||
const visible = this._getVisiblePages();
|
||||
const pagesToRefresh = [];
|
||||
const { ids, views } = visible;
|
||||
for (const page of views) {
|
||||
const { view } = page;
|
||||
if (!view.hasEditableAnnotations()) {
|
||||
ids.delete(view.id);
|
||||
continue;
|
||||
}
|
||||
pagesToRefresh.push(page);
|
||||
}
|
||||
|
||||
if (pagesToRefresh.length === 0) {
|
||||
return null;
|
||||
}
|
||||
this.renderingQueue.renderHighestPriority({
|
||||
first: pagesToRefresh[0],
|
||||
last: pagesToRefresh.at(-1),
|
||||
views: pagesToRefresh,
|
||||
ids,
|
||||
});
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
containsElement(element) {
|
||||
return this.container.contains(element);
|
||||
}
|
||||
|
@ -2259,13 +2293,56 @@ class PDFViewer {
|
|||
if (!this.pdfDocument) {
|
||||
return;
|
||||
}
|
||||
this.#annotationEditorMode = mode;
|
||||
this.eventBus.dispatch("annotationeditormodechanged", {
|
||||
source: this,
|
||||
mode,
|
||||
});
|
||||
|
||||
this.#annotationEditorUIManager.updateMode(mode, editId, isFromKeyboard);
|
||||
const { eventBus } = this;
|
||||
const updater = () => {
|
||||
if (this.#onPageRenderedCallback) {
|
||||
eventBus._off("pagerendered", this.#onPageRenderedCallback);
|
||||
this.#onPageRenderedCallback = null;
|
||||
}
|
||||
if (this.#switchAnnotationEditorModeTimeoutId !== null) {
|
||||
clearTimeout(this.#switchAnnotationEditorModeTimeoutId);
|
||||
this.#switchAnnotationEditorModeTimeoutId = null;
|
||||
}
|
||||
this.#annotationEditorMode = mode;
|
||||
eventBus.dispatch("annotationeditormodechanged", {
|
||||
source: this,
|
||||
mode,
|
||||
});
|
||||
this.#annotationEditorUIManager.updateMode(mode, editId, isFromKeyboard);
|
||||
};
|
||||
|
||||
if (
|
||||
mode === AnnotationEditorType.NONE ||
|
||||
this.#annotationEditorMode === AnnotationEditorType.NONE
|
||||
) {
|
||||
const isEditing = mode !== AnnotationEditorType.NONE;
|
||||
if (!isEditing) {
|
||||
this.pdfDocument.annotationStorage.resetModifiedIds();
|
||||
}
|
||||
for (const pageView of this._pages) {
|
||||
pageView.toggleEditingMode(isEditing);
|
||||
}
|
||||
// We must call #switchToEditAnnotationMode unconditionally to ensure that
|
||||
// page is rendered if it's useful or not.
|
||||
const idsToRefresh = this.#switchToEditAnnotationMode();
|
||||
if (isEditing && editId && idsToRefresh) {
|
||||
// We're editing an existing annotation so we must switch to editing
|
||||
// mode when the rendering is done.
|
||||
const { signal } = this.#eventAbortController;
|
||||
this.#onPageRenderedCallback = ({ pageNumber }) => {
|
||||
idsToRefresh.delete(pageNumber);
|
||||
if (idsToRefresh.size === 0) {
|
||||
eventBus._off("pagerendered", this.#onPageRenderedCallback);
|
||||
this.#onPageRenderedCallback = null;
|
||||
this.#switchAnnotationEditorModeTimeoutId = setTimeout(updater, 0);
|
||||
}
|
||||
};
|
||||
eventBus._on("pagerendered", this.#onPageRenderedCallback, { signal });
|
||||
return;
|
||||
}
|
||||
}
|
||||
updater();
|
||||
}
|
||||
|
||||
// eslint-disable-next-line accessor-pairs
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue