Skip to content

Commit 7e5e227

Browse files
committed
[Editor] Add a sidebar allowing the user to navigate between the comments in a pdf (bug 1985567)
This implements what has been specified but it's still not done: we have to handle editing a comment or an annotation containing one.
1 parent 13ba311 commit 7e5e227

File tree

12 files changed

+757
-8
lines changed

12 files changed

+757
-8
lines changed

l10n/en-US/viewer.ftl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,10 @@ pdfjs-comment-floating-button =
328328
.title = Comment
329329
.aria-label = Comment
330330
pdfjs-comment-floating-button-label = Comment
331+
pdfjs-editor-comment-button =
332+
.title = Comment
333+
.aria-label = Comment
334+
pdfjs-editor-comment-button-label = Comment
331335
pdfjs-editor-signature-button =
332336
.title = Add signature
333337
pdfjs-editor-signature-button-label = Add signature
@@ -395,6 +399,23 @@ pdfjs-free-text2 =
395399
.aria-label = Text Editor
396400
.default-content = Start typing…
397401
402+
# Used to show how many comments are present in the pdf file.
403+
# Variables:
404+
# $count (Number) - the number of comments.
405+
pdfjs-editor-comments-sidebar-title =
406+
{ $count ->
407+
[one] Comment
408+
*[other] Comments
409+
}
410+
411+
pdfjs-editor-comments-sidebar-close-button =
412+
.title = Close the sidebar
413+
.aria-label = Close the sidebar
414+
pdfjs-editor-comments-sidebar-close-button-label = Close the sidebar
415+
416+
# Instructional copy to add a comment by selecting text or an annotations.
417+
pdfjs-editor-comments-sidebar-no-comments = Add a comment by selecting text or an annotation.
418+
398419
## Alt-text dialog
399420

400421
# Alternative text (alt text) helps when people can't see the image.

src/display/editor/tools.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,8 @@ class AnnotationEditorUIManager {
585585

586586
#activeEditor = null;
587587

588+
#allEditableAnnotations = null;
589+
588590
#allEditors = new Map();
589591

590592
#allLayers = new Map();
@@ -663,6 +665,8 @@ class AnnotationEditorUIManager {
663665

664666
#showAllStates = null;
665667

668+
#pdfDocument = null;
669+
666670
#previousStates = {
667671
isEditing: false,
668672
isEmpty: true,
@@ -846,6 +850,7 @@ class AnnotationEditorUIManager {
846850
this.#altTextManager = altTextManager;
847851
this.#commentManager = commentManager;
848852
this.#signatureManager = signatureManager;
853+
this.#pdfDocument = pdfDocument;
849854
this._eventBus = eventBus;
850855
eventBus._on("editingaction", this.onEditingAction.bind(this), { signal });
851856
eventBus._on("pagechanging", this.onPageChanging.bind(this), { signal });
@@ -928,6 +933,7 @@ class AnnotationEditorUIManager {
928933
this.#floatingToolbar = null;
929934
this.#mainHighlightColorPicker?.destroy();
930935
this.#mainHighlightColorPicker = null;
936+
this.#allEditableAnnotations = null;
931937
if (this.#focusMainContainerTimeoutId) {
932938
clearTimeout(this.#focusMainContainerTimeoutId);
933939
this.#focusMainContainerTimeoutId = null;
@@ -937,6 +943,7 @@ class AnnotationEditorUIManager {
937943
this.#translationTimeoutId = null;
938944
}
939945
this._editorUndoBar?.destroy();
946+
this.#pdfDocument = null;
940947
}
941948

942949
combinedSignal(ac) {
@@ -1790,6 +1797,10 @@ class AnnotationEditorUIManager {
17901797
this.#updateModeCapability = Promise.withResolvers();
17911798
this.#currentDrawingSession?.commitOrRemove();
17921799

1800+
if (this.#mode === AnnotationEditorType.POPUP) {
1801+
this.#commentManager?.hideSidebar();
1802+
}
1803+
17931804
this.#mode = mode;
17941805
if (mode === AnnotationEditorType.NONE) {
17951806
this.setEditingState(false);
@@ -1800,9 +1811,18 @@ class AnnotationEditorUIManager {
18001811
this.#updateModeCapability.resolve();
18011812
return;
18021813
}
1814+
18031815
if (mode === AnnotationEditorType.SIGNATURE) {
18041816
await this.#signatureManager?.loadSignatures();
18051817
}
1818+
if (mode === AnnotationEditorType.POPUP) {
1819+
this.#allEditableAnnotations ||=
1820+
await this.#pdfDocument.getAnnotationsByType(
1821+
new Set(this.#editorTypes.map(editorClass => editorClass._editorType))
1822+
);
1823+
this.#commentManager?.showSidebar(this.#allEditableAnnotations);
1824+
}
1825+
18061826
this.setEditingState(true);
18071827
await this.#enableAll();
18081828
this.unselectAll();

src/shared/util.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ const AnnotationEditorType = {
7575
HIGHLIGHT: 9,
7676
STAMP: 13,
7777
INK: 15,
78+
POPUP: 16,
7879
SIGNATURE: 101,
7980
COMMENT: 102,
8081
};

web/app.js

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,30 @@ const PDFViewerApplication = {
493493
: null;
494494
const commentManager =
495495
AppOptions.get("enableComment") && appConfig.editCommentDialog
496-
? new CommentManager(appConfig.editCommentDialog, overlayManager)
496+
? new CommentManager(
497+
appConfig.editCommentDialog,
498+
{
499+
sidebar:
500+
appConfig.annotationEditorParams?.editorCommentsSidebar || null,
501+
commentsList:
502+
appConfig.annotationEditorParams?.editorCommentsSidebarList ||
503+
null,
504+
commentCount:
505+
appConfig.annotationEditorParams?.editorCommentsSidebarCount ||
506+
null,
507+
sidebarTitle:
508+
appConfig.annotationEditorParams?.editorCommentsSidebarTitle ||
509+
null,
510+
closeButton:
511+
appConfig.annotationEditorParams
512+
?.editorCommentsSidebarCloseButton || null,
513+
commentToolbarButton:
514+
appConfig.toolbar?.editorCommentButton || null,
515+
},
516+
eventBus,
517+
linkService,
518+
overlayManager
519+
)
497520
: null;
498521

499522
const enableHWA = AppOptions.get("enableHWA"),
@@ -589,6 +612,10 @@ const PDFViewerApplication = {
589612
if (editorSignatureButton && AppOptions.get("enableSignatureEditor")) {
590613
editorSignatureButton.parentElement.hidden = false;
591614
}
615+
const editorCommentButton = appConfig.toolbar?.editorCommentButton;
616+
if (editorCommentButton && AppOptions.get("enableComment")) {
617+
editorCommentButton.parentElement.hidden = false;
618+
}
592619
this.annotationEditorParams = new AnnotationEditorParams(
593620
appConfig.annotationEditorParams,
594621
eventBus

web/comment_manager.css

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,3 +351,237 @@
351351
}
352352
}
353353
}
354+
355+
#editorCommentsSidebar {
356+
--comment-close-button-icon: url(images/comment-closeButton.svg);
357+
358+
--comment-date-fg-color: light-dark(
359+
rgb(21 20 26 / 0.69),
360+
rgb(251 251 254 / 0.69)
361+
);
362+
--comment-bg-color: light-dark(#f9f9fb, #1c1b22);
363+
--comment-hover-bg-color: light-dark(
364+
rgb(21 20 26 / 0.14),
365+
rgb(251 251 254 / 0.14)
366+
);
367+
--comment-active-bg-color: light-dark(
368+
rgb(21 20 26 / 0.21),
369+
rgb(251 251 254 / 0.21)
370+
);
371+
--comment-border-color: light-dark(#f0f0f4, #52525e);
372+
--comment-focus-outline-color: light-dark(#0062fa, #00cadb);
373+
--comment-fg-color: light-dark(#15141a, #fbfbfe);
374+
--comment-count-bg-color: light-dark(#e2f7ff, #00317e);
375+
--comment-indicator-active-fg-color: light-dark(#0041a4, #a6ecf4);
376+
--comment-indicator-focus-fg-color: light-dark(#5b5b66, #fbfbfe);
377+
--comment-indicator-hover-fg-color: light-dark(#0053cb, #61dce9);
378+
--comment-indicator-selected-fg-color: light-dark(#0062fa, #00cadb);
379+
380+
@media screen and (forced-colors: active) {
381+
--comment-date-fg-color: CanvasText;
382+
--comment-bg-color: Canvas;
383+
--comment-hover-bg-color: SelectedItemText;
384+
--comment-active-bg-color: SelectedItemText;
385+
--comment-border-color: CanvasText;
386+
--comment-fg-color: CanvasText;
387+
--comment-count-bg-color: Canvas;
388+
--comment-indicator-active-fg-color: SelectedItem;
389+
--comment-indicator-focus-fg-color: CanvasText;
390+
--comment-indicator-hover-fg-color: CanvasText;
391+
--comment-indicator-selected-fg-color: SelectedItem;
392+
}
393+
394+
display: flex;
395+
width: 239px;
396+
height: auto;
397+
min-width: 180px;
398+
max-width: 632px;
399+
padding-bottom: 16px;
400+
flex-direction: column;
401+
align-items: flex-start;
402+
403+
#editorCommentsSidebarHeader {
404+
width: 100%;
405+
box-sizing: border-box;
406+
padding: 16px;
407+
display: flex;
408+
align-items: center;
409+
justify-content: space-between;
410+
411+
.commentCount {
412+
display: flex;
413+
align-items: baseline;
414+
gap: 6px;
415+
user-select: none;
416+
417+
#editorCommentsSidebarTitle {
418+
font: menu;
419+
font-style: normal;
420+
font-weight: 590;
421+
line-height: normal;
422+
font-size: 17px;
423+
color: var(--comment-fg-color);
424+
}
425+
426+
#editorCommentsSidebarCount {
427+
padding: 0 4px;
428+
border-radius: 4px;
429+
background-color: var(--comment-count-bg-color);
430+
431+
color: var(--comment-fg-color);
432+
text-align: center;
433+
434+
font: menu;
435+
font-size: 13px;
436+
font-style: normal;
437+
font-weight: 400;
438+
line-height: normal;
439+
}
440+
}
441+
442+
#editorCommentsSidebarCloseButton {
443+
width: 32px;
444+
height: 32px;
445+
padding: 8px;
446+
border: none;
447+
background: none;
448+
cursor: pointer;
449+
450+
&::before {
451+
content: "";
452+
display: inline-block;
453+
width: 100%;
454+
height: 100%;
455+
mask-repeat: no-repeat;
456+
mask-position: center;
457+
mask-image: var(--comment-close-button-icon);
458+
background-color: var(--comment-fg-color);
459+
}
460+
461+
&:hover {
462+
background-color: var(--comment-hover-bg-color);
463+
}
464+
465+
&:active {
466+
background-color: var(--comment-active-bg-color);
467+
}
468+
469+
> span {
470+
display: inline-block;
471+
width: 0;
472+
height: 0;
473+
overflow: hidden;
474+
}
475+
}
476+
}
477+
478+
#editorCommentsSidebarList {
479+
display: flex;
480+
width: auto;
481+
padding: 1px 16px 0;
482+
gap: 10px;
483+
flex: 1 0 0;
484+
align-self: stretch;
485+
align-items: flex-start;
486+
flex-direction: column;
487+
488+
.sidebarComment {
489+
display: flex;
490+
width: auto;
491+
padding: 8px 16px 16px;
492+
flex-direction: column;
493+
align-items: flex-start;
494+
align-self: stretch;
495+
gap: 4px;
496+
497+
border-radius: 8px;
498+
border: 0.5px solid var(--comment-border-color);
499+
background-color: var(--comment-bg-color);
500+
501+
&:hover {
502+
background-color: var(--comment-hover-bg-color);
503+
504+
time::after {
505+
display: inline-block;
506+
background-color: var(--comment-indicator-hover-fg-color);
507+
}
508+
}
509+
510+
&:active {
511+
background-color: var(--comment-active-bg-color);
512+
513+
time::after {
514+
display: inline-block;
515+
background-color: var(--comment-indicator-active-fg-color);
516+
}
517+
}
518+
519+
&:is(:focus, :focus-visible) time::after {
520+
display: inline-block;
521+
background-color: var(--comment-indicator-focus-fg-color);
522+
}
523+
524+
&:focus-visible {
525+
outline: 2px solid var(--comment-focus-outline-color);
526+
outline-offset: 2px;
527+
}
528+
529+
&.selected {
530+
.sidebarCommentText {
531+
max-height: fit-content;
532+
-webkit-line-clamp: unset;
533+
}
534+
535+
time::after {
536+
display: inline-block;
537+
background-color: var(--comment-indicator-selected-fg-color);
538+
}
539+
}
540+
541+
.sidebarCommentText {
542+
font: menu;
543+
font-style: normal;
544+
font-weight: 400;
545+
line-height: normal;
546+
font-size: 15px;
547+
width: 100%;
548+
height: fit-content;
549+
max-height: 80px;
550+
display: -webkit-box;
551+
-webkit-box-orient: vertical;
552+
-webkit-line-clamp: 2;
553+
overflow: hidden;
554+
overflow-wrap: break-word;
555+
556+
&.noComments {
557+
max-height: fit-content;
558+
-webkit-line-clamp: unset;
559+
user-select: none;
560+
}
561+
}
562+
563+
time {
564+
width: 100%;
565+
display: inline-flex;
566+
align-items: center;
567+
justify-content: space-between;
568+
569+
font: menu;
570+
font-style: normal;
571+
font-weight: 400;
572+
line-height: normal;
573+
font-size: 13px;
574+
575+
&::after {
576+
content: "";
577+
display: none;
578+
width: 16px;
579+
height: 16px;
580+
mask-repeat: no-repeat;
581+
mask-position: center;
582+
mask-image: var(--comment-edit-button-icon);
583+
}
584+
}
585+
}
586+
}
587+
}

0 commit comments

Comments
 (0)