CommandBar.showForm never settles if an HTML view invokes a plugin command
Personne n'a encore pris cette issue.
Évaluation
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Accessibilité débutants
- 45/100
- Type d'issue
- Bug
- Clarté
- Plutôt claire
- Activité
- Active
- Stack technique
- javascript
- Domaine
- developer-experience
Piste de recherche
Start by reading np.Shared/requiredFiles/pluginToHTMLCommsBridge.js and tracing how DataStore.invokePluginCommandByName interacts with pending CommandBar.showForm calls. Reproduce with the Dashboard timer running while /convert to project awaits the form. Done means HTML view commands no longer leave the form promise pending: calls are queued until dismissal or the form settles if preempted.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Summary
CommandBar.showForm() never settles if an HTML view invokes another plugin command while the form is open. The original command stays suspended, the note is not updated, and there is no error. Closing the HTML window avoids the problem because nothing then calls back into the plugin.
Seen on NotePlan 3.22 (build 1542), macOS, 26 Oct 2026.
Repro
- Open the Dashboard HTML window (
jgclark.Dashboard, custom idjgclark.Dashboard.main) and leave it open. With the Time Block section enabled, the page runssetIntervalevery 54 seconds. - Open a normal note and run the Projects command
/convert to project(jgclark.Reviews/convertToProject). - That command reaches
await CommandBar.showForm(...)and stops. The form does not complete, and the command logs nothing further. Run it again and the same thing happens. - Close Dashboard and run the same command. The form appears, Submit writes the note frontmatter, and the command logs success.
What the plugin is doing
After a couple of checks and getReviewSettings(), the command does only this:
const formResult = await CommandBar.showForm({
title: `Convert '${title}' to a Project`,
submitText: 'Convert',
fields,
})
Every path after that await logs either cancellation, invalid data, a write failure, or success, and the catch logs exceptions. None of those lines appear on the failed runs. The promise from showForm is neither resolved nor rejected.
The same form succeeds when Dashboard is closed, so the field list is not the cause.
What the logs show
Plugin console for a failed run (16:08:32), with nothing after the settings line:
--- 2026-10-26T16:08:32Z 'convert to project' (jgclark.Reviews) ---
Executing function 'convertToProject'
INFO convertToProject :: Starting for note 'Live Translation for services' (...)
INFO getReviewSettings :: Will use Perspective 'Home', and its folder & teamspace settings
One second later, Dashboard runs because the webview posted a bridge message:
[WebView] bridge::runPluginCommand JS file in np.Shared Sending command "onMessageFromHTMLView" to NotePlan: "jgclark.Dashboard"
--- 2026-10-26T16:08:33Z 'onMessageFromHTMLView' (jgclark.Dashboard) ---
Executing function 'onMessageFromHTMLView'
INFO bridgeClickDashboardItem: refreshSomeSections
That refreshSomeSections call is the Time Block timer. It fires about every 54 seconds for as long as the Dashboard window is visible (16:02:37, 16:03:31, 16:04:25, 16:05:20, 16:06:44, 16:07:39, 16:08:33, 16:09:28, ...). Each failed /convert to project was still awaiting showForm when the next tick arrived (16:02:11 then refresh at 16:02:37; 16:03:28 then 16:03:31; 16:08:32 then 16:08:33). None of those awaits ever resumed.
The run that succeeded (16:10:49, frontmatter written at 16:10:57) fell in a gap between those ticks. The same command also succeeds whenever Dashboard is closed, so the timer never posts.
The bridge code in np.Shared/requiredFiles/pluginToHTMLCommsBridge.js is:
const code = '(async function() { await DataStore.invokePluginCommandByName("onMessageFromHTMLView", "jgclark.Dashboard", [type, data]);})()'
window.webkit.messageHandlers.jsBridge.postMessage({ code, onHandle: '', id: '1' })
So while jgclark.Reviews is suspended inside CommandBar.showForm, the webview starts a second plugin command, jgclark.Dashboard.onMessageFromHTMLView, via DataStore.invokePluginCommandByName.
What appears to go wrong in the app
showForm is waiting on the command bar. A jsBridge message then starts another plugin command on the same JavaScript context. That second command runs (refreshSomeSections does its work and returns). The first command's showForm promise is left pending: the form is gone or never committed, and no completion handler runs. The first command cannot log, write, or show an error.
This matches a modal UI promise that is dropped when a new plugin command begins, instead of being resolved with submitted: false or rejected.
The same hole would affect any await CommandBar.showForm / prompt / textPrompt while any HTML view posts invokePluginCommandByName. Dashboard's idle refresh (refreshEnabledSections) and windowResized on hide use that same bridge, so they can trip it too. The 54-second Time Block timer is the one that lined up with these logs.
Expected behavior
While a command-bar form is open, invokePluginCommandByName coming from an HTML view should be queued until the form is dismissed. If a new command must preempt the form, showForm should still settle (submitted: false, or a rejection) so the caller's await resumes. A background refresh must not swallow the form and leave the original command hung.
- Langage dominant
- JavaScript
- Étoiles
- 203
- Forks
- 81
- Merge moyen
- 52 min
- PR mergées (30 j)
- 1
Préparer son environnement
Ce projet ne fournit ni conteneur de développement, ni Dockerfile, ni guide de contribution : l'installation est à votre charge. Commencez par son README, et consultez notre guide de la première contribution pour les étapes générales.
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de NotePlan/plugins
-
Difficulté 2/5 1-3 heures Accessibilité débutants 74/100
-
Task Sorting & Tools: support other line typesPeut-être pris @dwertheimer l’a pris il y a 12 jours. Ouverteenhancement
-
getFoldersMatching adds root "/" even when it is not an inclusionPeut-être pris @jgclark l’a pris il y a 12 jours. Ouverte
NotePlan/plugins#788 · 2 commentaires · 1 personne assignée ·
-
Dashboard: Task "Comment"Ouverteenhancement question
Difficulté 5/5 Plus d'une semaine Accessibilité débutants 35/100
-
newMeetingNoteFromEventID always opens earliest occurrence for Google Calendar recurring eventsPeut-être à nouveau libre @EduardMe l’a pris il y a 138 jours, et aucune pull request n’est ouverte. Ouvertebug
Toutes les issues de NotePlan/plugins
Issues similaires
-
bug
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
swc-project/swc-next#1165 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
nhsuk/nhsuk-prototype-kit-package#439 ·
Les mainteneurs répondent en général sous 1 jour
-
Add: &TV LogoOuvertecheck:passed logos:add
Difficulté 1/5 Moins d'une heure Accessibilité débutants 74/100
-
BUG: Appointment time renders blank and PM appointment slots miscalculate vertical position in CalendarScreenPeut-être pris @aryanpatil-07 l’a pris aujourd’hui. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
AOSSIE-Org/BabyNest#297 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
Onboarding form: instructor radio never pre-selected "Yes" (permission vs permissions typo)Peut-être pris @ThakuraAnki l’a pris aujourd’hui. Ouvertebug
Difficulté 1/5 Moins d'une heure Accessibilité débutants 72/100
WikiEducationFoundation/WikiEduDashboard#7235 ·
Les mainteneurs répondent en général sous 1 jour