-
-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Desktop: Resolves #11687: Plugins: Allow editor plugins to support multiple windows #12041
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
base: dev
Are you sure you want to change the base?
Conversation
…all windows Note: This pull request currently uses global desktop app reducer state to resolve the conflict. This will likely need refactoring (as editor plugins should eventually made to work on mobile).
…r-plugins-with-multi-window-support
…or-plugins-with-multi-window-support' into pr/desktop/fix-editor-plugins-with-multi-window-support
…r-plugins-with-multi-window-support
…r-plugins-with-multi-window-support
…r-plugins-with-multi-window-support
mobile and desktop
Previously, editor plugins visibility was saved based on the view ID of the plugin. This, however, was problematic because the view ID is based on the window ID. As a result, editor plugins in secondary windows were initially shown/hidden in a way that might be unexpected. With this change, editor plugin visibility is based on the view type ID. This type ID is the same as the view ID, but excludes the part that's determined by the window ID. As a result, editor plugins are shown/hidden based on the last change to that plugin's visibility in any window.
Fixes an issue where making a change in the current window that matches the last editor plugin saved note content in another window would cause the emitUpdate event to be skipped.
I'm converting this to a draft until the editor plugin API matches something similar to the following: API redesign suggestion (edit: This particular redesign is not possible with the current plugin IPC logic on desktop. The implemented API is a bit different.)Edit: See joplin/plugin-yesyoukan#42 (comment). Possible API redesign:
Example: joplin.editors.register('test-plugin', async (handle) => {
await joplin.editors.setHtml(handle, `...`);
await joplin.editors.addScript(handle, './path/to/script.js');
await joplin.editors.onMessage(handle, message => {
if (message.kind === 'save') {
const editingId = message.id;
const bodyToSave = message.body;
joplin.editors.save(handle, { id: editingId, body: bodyToSave });
}
});
return {
onActivationCheck: async (event) => {
return true; // Always allow users to enable
},
onUpdate: async (event) => {
joplin.editors.postMessage(handle, { type: 'update', content: event.newBody });
},
};
}); |
doesn't support returning functions within objects
It's more convenient to first call onUpdate within the required onSetup handler -- this allows storing the last information from an onUpdate event in a local variable that can be shared with the onMessage and similar callbacks registered within onSetup.
}); | ||
}); | ||
}, | ||
|
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.
Add an onSave
callback to the main object instead of what's currently here:
onSave(event) { | |
event.noteId, event.handle | |
} |
Calling editors.saveNote()
then calls the onSave
callback.
…r-plugins-with-multi-window-support
Summary
This pull request makes it possible to resolve joplin/plugin-yesyoukan#41.
Resolves #11687.
Notes
joplin.views.editor.create
. This works around a race condition in which the activation check event was fired before the activation check callback was registered.Updated plugin API
Summary of changes
This pull request makes changes to the editor plugin API to add support for multiple windows:
editor.create
witheditor.register
: Editor view handles are now created and managed by Joplin. Required callbacks are passed directly toeditor.register
.editor.create
is now deprecated, but still exists.editors.onActivationCheck
:onActivationCheck
is a required callback — it should be specified for all editor views. It should now be specified in the options provided toeditor.register
.editors.onUpdate
:editors.onUpdate
is now called more frequently.onUpdate
is now called whenever the content of the current note is changed by a different editor or source.editors.onUpdate
is called when the current note is changed from an external editor, sync, or editor in a different window.editors.onUpdate
was called only when switching notes.workspace.selectedNote
. However,workspace.selectedNote
only returns information about the note in the currently active window. As a result, editor plugins in background windows previously could load an incorrect note. Information about the selected note should now be obtained from the event passed toonUpdate
.editors.saveNote
: Previously, plugins saved note content through the data API. This was problematic because Joplin couldn't tell which editor saved the note. Without this information, Joplin can't determine whetheronUpdate
should be called for the current editor or not.Using the new API
Registering an editor plugin
Use
joplin.views.editors.register
, providingonSetup
andonActivationCheck
callbacks:Implementing
onSetup
The
onSetup
callback should:The editor cannot become active until after
onSetup
completes.Example 1: Editor plugin that displays a static message
Above, Joplin calls
onSetup
when Joplin creates a new view for the editor. This happens, for example, when a new window with a new editor is created.Similarly,
onActivationCheck
is called when the user opens a new window or switches notes. Here,onActivationCheck
always returnstrue
to indicate that the plugin supports all notes.Notice that the
setHtml
API is identical to the API used to set the initial HTML in dialogs and panels.Example 2: Editor plugin that allows changing the current note's content (but not reading it)
The above example:
setHtml
.addScript
. This script (not included above) is responsible for registering click handlers for the clear<button
.onUpdate
and stores the editor's note ID in a variable.addScript
. This is done usingonMessage
.clearNote
message, clears the note's content witheditors.saveNote
.onSetup
completes.Note:
onSetup
can be called multiple times by Joplin with different viewhandle
s. As a result, it's important that thenoteId
variable is local toonSetup
.Implementing
onActivationCheck
The
onActivationCheck
callback should returntrue
when the providedActivationCheckEvent
describes a note supported by the editor.For example, mark all notes containing "test" as supported (and no others):
Screen recording
Screencast.from.2025-04-01.13-30-53.webm
In this screen recording,
To-do
editors.onActivationCheck
without requiring users to specify the activation check callback as an argument tojoplin.views.create
.Testing
Automated tests
This pull request adds two new automated Playwright regression tests:
editors.saveNote
API works. See commit for further details.