Skip to content

fix(compose): degrade honestly in a plain-text composer - #14

Merged
Schleuse merged 2 commits into
mainfrom
fix/13-plain-text-degrades-honestly
Sep 9, 2026
Merged

Schleuse merged 2 commits into
mainfrom
fix/13-plain-text-degrades-honestly

Conversation

@Schleuse

@Schleuse Schleuse commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

Closes #13.

The compose body's context menu offered Insert as code block in every
composer, whatever its format. In a plain-text one the click parked the
selection and called composeAction.openPopup(), which anchors to a button in
a toolbar Thunderbird hides there, so the panel opened and rolled straight back
up. The other two routes already degraded quietly - the button is hidden with
its toolbar and Ctrl+Shift+C is inert - so this item was the only route that
advertised itself and then did nothing.

#12 settled that a plain-text composer having no route in is the add-on's scope
rather than a bug. This is the cleanup after that decision.

The item

  • menus.onShown asks the composer what format it is in and sets the item's
    visibility with the answer. The item is therefore created hidden and revealed
    for an HTML composer, not the other way round: created visible, it would be
    in the menu for as long as the answer took to arrive, in exactly the composer
    where the offer is false.
  • A menu counter and menus.onHidden keep a late answer from being applied to
    the next menu instead of its own.
  • menus.onClicked asks again rather than trusting the item to be hidden.
    Visibility is state Thunderbird holds between one menu and the next, so a
    click can come from a menu drawn before the add-on had its say - and a
    refusal that parked a selection would leave it for the next popup this tab
    opened by another route.

No manifest change: compose_action.default_area stays formattoolbar, and
the compose permission the add-on already holds covers getComposeDetails.

The tests

Ten node-tier assertions, and one Thunderbird-tier test that asserts both
halves in one run and in one order - the HTML composer's menu leaves the item
visible, so the plain-text menu has to take it out rather than finding it
already gone. Mutation-checked: forcing the add-on to always offer the item
fails it with expected [ { …(2) } ] to deeply equal [].

Reading that menu now waits for a stated number of the add-on's items
(openBodyContextMenu({ expecting })) and ignores hidden ones, because the
add-on decides after the menu is on screen and a menu read as it opens still
shows what the last one left behind.

The documents

The README's harness limits, the release checklist's plain-text item, the
harness's own list and the insertion test's format-toolbar workaround all
described this as a defect awaiting work. They now describe it as scope, the
workaround is justified as permanent, and the README says out loud that a code
block goes into an HTML compose window only. No #12 references remain.

Not in this

The plain-text insert path (isPlainText through the popup, the insertion
function and the code-block seam) is untouched, as the issue asked.

pnpm test 211 passed · pnpm test:thunderbird 18 passed against a real
Thunderbird 128 ESR · pnpm lint 0 errors.

🤖 Generated with Claude Code

Schleuse and others added 2 commits September 9, 2026 13:43
The compose body's context menu offered "Insert as code block" in every
composer, whatever its format. In a plain-text one the click parked the
selection and opened a popup anchored to a button in a toolbar Thunderbird
hides there, so the panel opened and rolled straight back up. The item is
now shown only where the insert can happen.

`menus.onShown` asks the composer what format it is in and sets the item's
visibility with the answer, so the item is created hidden and revealed for
an HTML composer rather than the other way round: created visible, it would
be in the menu for as long as the answer took to arrive, in exactly the
composer where the offer is false. A menu counter and `menus.onHidden`
keep a late answer from being applied to the next menu instead of its own.

`menus.onClicked` asks again rather than trusting the item to be hidden.
Visibility is state Thunderbird holds between one menu and the next, so a
click can come from a menu drawn before the add-on had its say, and a
refusal that parked a selection would leave it for the next popup this tab
opened by another route.

The Thunderbird tier asserts both halves in one test, in one order: the
HTML composer's menu leaves the item visible, so the plain-text menu has to
take it out rather than finding it already gone. Reading that menu now
waits for a stated number of the add-on's items, because the add-on decides
after the menu is on screen and a menu read as it opens still shows what
the last one left behind.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The README's harness limits, the release checklist's plain-text item and
the harness's own list all described the unreachable popup as a defect
awaiting work. #12 settled that it is not: the button belongs among the
formatting controls, and a composer with no format toolbar is a composer
this add-on has nothing to offer. Said as scope rather than as a pending
fix, and the README now says out loud that a code block goes into an HTML
compose window only.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Schleuse
Schleuse merged commit 872ce2b into main Sep 9, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Degrade honestly in a plain-text composer

1 participant