Skip to content

Commit

Permalink
Pop open a message when user deletes an annotation
Browse files Browse the repository at this point in the history
When a user deletes any number of annotations, they are notified of the action
by a popup message with an undo button. Besides that, this change reuses the
existing messageBar CSS class from the new alt-text dialog as much as possible.
  • Loading branch information
ryzokuken authored and nicolo-ribaudo committed Oct 17, 2024
1 parent 8a37d90 commit 13d7c53
Show file tree
Hide file tree
Showing 10 changed files with 193 additions and 4 deletions.
10 changes: 10 additions & 0 deletions l10n/en-US/viewer.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -493,3 +493,13 @@ pdfjs-editor-alt-text-settings-editor-title = Alt text editor
pdfjs-editor-alt-text-settings-show-dialog-button-label = Show alt text editor right away when adding an image
pdfjs-editor-alt-text-settings-show-dialog-description = Helps you make sure all your images have alt text.
pdfjs-editor-alt-text-settings-close-button = Close
# Variables:
# $type (String) - the type of annotation that was just removed with an optional quantity.
pdfjs-editor-undo-bar-message = { $type } removed
pdfjs-editor-undo-bar-undo-button =
.title = Undo
pdfjs-editor-undo-bar-undo-button-label = Undo
pdfjs-editor-undo-bar-close-button =
.title = Close
pdfjs-editor-undo-bar-close-button-label = Close
12 changes: 11 additions & 1 deletion src/display/editor/tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,8 @@ class AnnotationEditorUIManager {

#editorsToRescale = new Set();

#editorUndoBar = null;

#enableHighlightFloatingButton = false;

#enableUpdatedAddImage = false;
Expand Down Expand Up @@ -769,7 +771,8 @@ class AnnotationEditorUIManager {
enableHighlightFloatingButton,
enableUpdatedAddImage,
enableNewAltTextWhenAddingImage,
mlManager
mlManager,
editorUndoBar
) {
const signal = (this._signal = this.#abortController.signal);
this.#container = container;
Expand Down Expand Up @@ -804,6 +807,7 @@ class AnnotationEditorUIManager {
rotation: 0,
};
this.isShiftKeyDown = false;
this.#editorUndoBar = editorUndoBar;

if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) {
Object.defineProperty(this, "reset", {
Expand Down Expand Up @@ -2002,6 +2006,12 @@ class AnnotationEditorUIManager {

const editors = [...this.#selectedEditors];
const cmd = () => {
this.#editorUndoBar?.show(
undo,
editors.length > 1
? `${editors.length} annotations`
: editors[0].editorType
);
for (const editor of editors) {
editor.remove();
}
Expand Down
10 changes: 10 additions & 0 deletions web/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ import { AltTextManager } from "web-alt_text_manager";
import { AnnotationEditorParams } from "web-annotation_editor_params";
import { CaretBrowsingMode } from "./caret_browsing.js";
import { DownloadManager } from "web-download_manager";
import { EditorUndoBar } from "./editor_undo_bar.js";
import { OverlayManager } from "./overlay_manager.js";
import { PasswordPrompt } from "./password_prompt.js";
import { PDFAttachmentViewer } from "web-pdf_attachment_viewer";
Expand Down Expand Up @@ -182,6 +183,7 @@ const PDFViewerApplication = {
_isCtrlKeyDown: false,
_caretBrowsing: null,
_isScrolling: false,
editorUndoBar: null,

// Called once when the document is loaded.
async initialize(appConfig) {
Expand Down Expand Up @@ -450,6 +452,9 @@ const PDFViewerApplication = {
)
: null;
}
const editorUndoBar = (this.editorUndoBar = appConfig.editorUndoBar
? new EditorUndoBar(appConfig.editorUndoBar, eventBus)
: null);

const enableHWA = AppOptions.get("enableHWA");
const pdfViewer = new PDFViewer({
Expand All @@ -460,6 +465,7 @@ const PDFViewerApplication = {
linkService: pdfLinkService,
downloadManager,
altTextManager,
editorUndoBar,
findController,
scriptingManager:
AppOptions.get("enableScripting") && pdfScriptingManager,
Expand Down Expand Up @@ -2962,6 +2968,10 @@ function onKeyDown(evt) {
this.findBar.close();
handled = true;
}
if (this.editorUndoBar?.isOpen) {
this.editorUndoBar.hide();
handled = true;
}
break;
case 40: // down arrow
if (this.supportsCaretBrowsingMode) {
Expand Down
3 changes: 2 additions & 1 deletion web/dialog.css
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,8 @@
}

> div {
&::before, > div {
&::before,
> div {
margin-block: 4px;
}

Expand Down
71 changes: 71 additions & 0 deletions web/editor_undo_bar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/* Copyright 2024 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

class EditorUndoBar {
#container;

#controller = null;

isOpen = false;

#message;

#undoButton;

constructor({ container, message, undoButton, closeButton }, eventBus) {
this.#container = container;
this.#message = message;
this.#undoButton = undoButton;

// Caveat: we have to pick between registering these everytime the bar is
// shown and not having the ability to cleanup using AbortController.
const boundHide = this.hide.bind(this);
closeButton.addEventListener("click", boundHide);
eventBus._on("beforeprint", boundHide);
eventBus._on("download", boundHide);
}

show(action, type) {
this.hide();
this.#message.setAttribute("data-l10n-args", JSON.stringify({ type }));
this.#container.hidden = false;
this.isOpen = true;

this.#controller = new AbortController();
const opts = { signal: this.#controller.signal };

this.#undoButton.addEventListener(
"click",
() => {
action();
this.hide();
},
opts
);
this.#undoButton.focus();
}

hide() {
if (!this.isOpen) {
return;
}
this.isOpen = false;
this.#container.hidden = true;
this.#controller?.abort();
this.#controller = null;
}
}

export { EditorUndoBar };
63 changes: 63 additions & 0 deletions web/message_bar.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
/* Copyright 2024 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

.messageBar {
--closing-button-icon: url(images/messageBar_closingButton.svg);
--message-bar-close-button-color: var(--text-primary-color);
Expand Down Expand Up @@ -100,3 +115,51 @@
}
}
}

#editorUndoBar {
--message-bar-icon: url(images/secondaryToolbarButton-documentProperties.svg);
--message-bar-icon-color: #0060df;
--message-bar-bg-color: #deeafc;
--message-bar-fg-color: #15141a;
--text-primary-color: #15141a;
--message-bar-border-color: rgb(0 0 0 / 0.08);

position: fixed;
bottom: 100px;
left: 50%;
transform: translateX(-50%);

padding: 8px 8px 8px 16px;

font-family: sans-serif;
font-size: 15px;

#editorUndoBarUndoButton {
border-radius: 4px;
font-weight: 590;
line-height: 19.5px;
color: #15141a;
border: none;
padding: 4px 16px;
height: 32px;

background-color: rgba(21 20 26 / 0.07);

&:hover {
background-color: rgba(21 20 26 / 0.14);
}

&:active {
background-color: rgba(21 20 26 / 0.21);
}

&:focus {
outline: 2px solid #0060df;
outline-offset: 2px;
}
}

> div {
align-items: center;
}
}
2 changes: 1 addition & 1 deletion web/pdf_viewer.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@import url(message_bar.css);
@import url(dialog.css);
@import url(text_layer_builder.css);
@import url(annotation_layer_builder.css);
@import url(xfa_layer_builder.css);
@import url(message_bar.css);
/* Ignored in GECKOVIEW builds: */
@import url(annotation_editor_layer_builder.css);

Expand Down
6 changes: 5 additions & 1 deletion web/pdf_viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ class PDFViewer {

#containerTopLeft = null;

#editorUndoBar = null;

#enableHWA = false;

#enableHighlightFloatingButton = false;
Expand Down Expand Up @@ -280,6 +282,7 @@ class PDFViewer {
this.downloadManager = options.downloadManager || null;
this.findController = options.findController || null;
this.#altTextManager = options.altTextManager || null;
this.#editorUndoBar = options.editorUndoBar || null;

if (this.findController) {
this.findController.onIsPageVisible = pageNumber =>
Expand Down Expand Up @@ -901,7 +904,8 @@ class PDFViewer {
this.#enableHighlightFloatingButton,
this.#enableUpdatedAddImage,
this.#enableNewAltTextWhenAddingImage,
this.#mlManager
this.#mlManager,
this.#editorUndoBar
);
eventBus.dispatch("annotationeditoruimanager", {
source: this,
Expand Down
14 changes: 14 additions & 0 deletions web/viewer.html
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,20 @@
<!--#endif-->
</div> <!-- dialogContainer -->

<div id="editorUndoBar" class="messageBar" hidden>
<div>
<div>
<span id="editorUndoBarMessage" class="description" data-l10n-id="pdfjs-editor-undo-bar-message" data-l10n-args='{ "type": "Annotation" }'>[Annotation] removed</span>
</div>
<button id="editorUndoBarUndoButton" class="undoButton" type="button" tabindex="0" title="Undo" data-l10n-id="pdfjs-editor-undo-bar-undo-button">
<span data-l10n-id="pdfjs-editor-undo-bar-undo-button-label">Undo</span>
</button>
<button id="editorUndoBarCloseButton" class="closeButton" type="button" tabindex="0" title="Close" data-l10n-id="pdfjs-editor-undo-bar-close-button">
<span data-l10n-id="pdfjs-editor-undo-bar-close-button-label">Close</span>
</button>
</div>
</div> <!-- editorUndoBar -->

</div> <!-- outerContainer -->
<div id="printContainer"></div>
</body>
Expand Down
6 changes: 6 additions & 0 deletions web/viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,12 @@ function getViewerConfiguration() {
editorHighlightShowAll: document.getElementById("editorHighlightShowAll"),
},
printContainer: document.getElementById("printContainer"),
editorUndoBar: {
container: document.getElementById("editorUndoBar"),
message: document.getElementById("editorUndoBarMessage"),
undoButton: document.getElementById("editorUndoBarUndoButton"),
closeButton: document.getElementById("editorUndoBarCloseButton"),
},
};
}

Expand Down

0 comments on commit 13d7c53

Please sign in to comment.