-
Notifications
You must be signed in to change notification settings - Fork 10.3k
[Editor] Dispatch an event when some global states are changing (bug 1777695) #15130
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
src/display/editor/editor.js
Outdated
if (event.button === 2) { | ||
// Avoid to focus this editor because of a right click. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we actually want to focus it for a middle-click, i.e. (usually) the scroll-wheel on a mouse, or do we perhaps want to avoid it receiving focus for event.button !== 0
instead?
src/display/editor/tools.js
Outdated
switch (details.name) { | ||
case "undo": | ||
this.undo(); | ||
break; | ||
case "redo": | ||
this.redo(); | ||
break; | ||
case "cut": | ||
this.cut(); | ||
break; | ||
case "copy": | ||
this.copy(); | ||
break; | ||
case "paste": | ||
this.paste(); | ||
break; | ||
case "delete": | ||
this.delete(); | ||
break; | ||
case "selectAll": | ||
this.selectAll(); | ||
break; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that the action-names seem to perfectly mimic the method-names, could we perhaps avoid a bit of duplication here?
switch (details.name) { | |
case "undo": | |
this.undo(); | |
break; | |
case "redo": | |
this.redo(); | |
break; | |
case "cut": | |
this.cut(); | |
break; | |
case "copy": | |
this.copy(); | |
break; | |
case "paste": | |
this.paste(); | |
break; | |
case "delete": | |
this.delete(); | |
break; | |
case "selectAll": | |
this.selectAll(); | |
break; | |
} | |
this[details.name]?.(); |
src/display/editor/tools.js
Outdated
* @param {Object} details | ||
*/ | ||
#dispatchUpdateStates(details) { | ||
const hasChange = Object.entries(details).some( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
const hasChange = Object.entries(details).some( | |
const hasChanged = Object.entries(details).some( |
src/display/editor/tools.js
Outdated
@@ -325,6 +416,29 @@ class AnnotationEditorUIManager { | |||
}); | |||
} | |||
|
|||
/** | |||
* Set the editing state. | |||
* It can be useful to temporarly disable it when the user is editing a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spelling-nit:
* It can be useful to temporarly disable it when the user is editing a | |
* It can be useful to temporarily disable it when the user is editing a |
src/display/editor/tools.js
Outdated
return Array.from(this.#allEditors.values()).every(editor => | ||
editor.isEmpty() | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: While it probably doesn't matter much, performance wise, it seems that this code will lead to essentially two loops and one (strictly speaking) unnecessary Array allocation.
Would it make sense to do something like the following instead?
return Array.from(this.#allEditors.values()).every(editor => | |
editor.isEmpty() | |
); | |
for (const editor of this.#allEditors.values()) { | |
if (!editor.isEmpty()) { | |
return false; | |
} | |
} | |
return true; |
web/app.js
Outdated
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) { | ||
eventBus._on( | ||
"annotationeditorstateschanged", | ||
annotationEditorStatesChanged |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency with all of the code above, please make this:
annotationEditorStatesChanged | |
webViewerAnnotationEditorStatesChanged |
web/app.js
Outdated
@@ -3074,6 +3080,10 @@ function beforeUnload(evt) { | |||
return false; | |||
} | |||
|
|||
function annotationEditorStatesChanged(data) { | |||
PDFViewerApplication.externalServices.setEditorStates(data); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For documentation purposes, please add the following dummy-method to the DefaultExternalServices
-class at the top of the file:
static updateEditorStates(data) {
throw new Error("Not implemented: updateEditorStates");
}
src/display/editor/tools.js
Outdated
constructor(eventBus) { | ||
this.#eventBus = eventBus; | ||
this.#eventBus.on("editingaction", this.#boundOnEditingAction); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use the ._on
-method for every "internal" use-case, since that helps ensure that the PDF.js code always receive events before any externally registered event listeners.
this.#eventBus.on("editingaction", this.#boundOnEditingAction); | |
eventBus._on("editingaction", this.#boundOnEditingAction); |
src/display/editor/tools.js
Outdated
this.#eventBus.dispatch("annotationeditorstateschanged", { | ||
source: this, | ||
details, | ||
}); | ||
Object.assign(this.#previousStates, details); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems, as far as I can tell, that the "shape" of the details
-Object will differ quite a lot between call-sites. Is that an issue, and if so do we perhaps want to ensure that we always send consistent data here?
You could possibly avoid that by doing something like this:
this.#eventBus.dispatch("annotationeditorstateschanged", { | |
source: this, | |
details, | |
}); | |
Object.assign(this.#previousStates, details); | |
this.#eventBus.dispatch("annotationeditorstateschanged", { | |
source: this, | |
details: Object.assign(this.#previousStates, details), | |
}); |
web/firefoxcom.js
Outdated
static setEditorStates(data) { | ||
FirefoxCom.request("setEditorStates", data); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency with existing methods, in the FirefoxExternalServices
-class, maybe use:
static setEditorStates(data) { | |
FirefoxCom.request("setEditorStates", data); | |
static updateEditorStates(data) { | |
FirefoxCom.request("updateEditorStates", data); |
src/display/editor/editor.js
Outdated
*/ | ||
mousedown(event) { | ||
if (event.button !== 0) { | ||
// Avoid to focus this editor because of a right click. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe tweak the comment slightly, now that the condition was updated above?
// Avoid to focus this editor because of a right click. | |
// Avoid to focus this editor because of a non-left click. |
constructor(eventBus) { | ||
this.#eventBus = eventBus; | ||
this.#eventBus._on("editingaction", this.#boundOnEditingAction); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't seem that anything is ever removing this listener, as far as I can tell?
That means that when multiple documents have been opened in the GENERIC viewer, there'll be a number of old (and stale) listeners still around. While "editingaction"-support will currently only be implemented in Firefox, this is nonetheless something that we should fix here to prevent any future issues.
Basically, I think that the simplest solution would be to add e.g. a destroy
-method to this class and having it run:
this.#eventBus._off("editingaction", this.#boundOnEditingAction);
Then, in the viewer, remove line
Line 902 in a1ac1a6
this.#annotationEditorUIManager = null; |
and instead add
if (this.#annotationEditorUIManager) {
this.#annotationEditorUIManager.destroy();
this.#annotationEditorUIManager = null;
}
just after line
Line 642 in a1ac1a6
} |
- this way the context menu in Firefox can take into account what we have in the clipboard, if an editor is selected, ... - when the user will click on a context menu item, an action will be triggered, hence this patch adds what is required to handle it; - some tests will be added in the Firefox' patch.
/botio integrationtest |
From: Bot.io (Linux m4)ReceivedCommand cmd_integrationtest from @Snuffleupagus received. Current queue size: 1 Live output at: http://54.241.84.105:8877/5e859836d7f1c5a/output.txt |
From: Bot.io (Windows)ReceivedCommand cmd_integrationtest from @Snuffleupagus received. Current queue size: 1 Live output at: http://54.193.163.58:8877/6684513ded1c454/output.txt |
From: Bot.io (Linux m4)SuccessFull output at http://54.241.84.105:8877/5e859836d7f1c5a/output.txt Total script time: 4.74 mins
|
From: Bot.io (Windows)FailedFull output at http://54.193.163.58:8877/6684513ded1c454/output.txt Total script time: 8.30 mins
|
have in the clipboard, if an editor is selected, ...
triggered, hence this patch adds what is required to handle it;