Skip to content

fix(local-mail): correct empty-mirror empty-state and collapse triage UI feedback#2311

Open
braden-w wants to merge 4 commits into
mainfrom
local-mail-triage-collapse
Open

fix(local-mail): correct empty-mirror empty-state and collapse triage UI feedback#2311
braden-w wants to merge 4 commits into
mainfrom
local-mail-triage-collapse

Conversation

@braden-w

@braden-w braden-w commented Jul 3, 2026

Copy link
Copy Markdown
Member

The triage list showed the wrong empty state on a freshly-synced mailbox. isFiltered was derived from selectedLabel !== null, but the list defaults to INBOX, so it was almost always true: an empty mirror rendered "No messages match / try a different label" instead of "No messages mirrored / run sync --full". The list now keys its empty state off the real signal, status.rows.messages === 0, with the icon and copy following it.

The rest is an indirection pass over the same surface. The MessageDetail outcome strip was a persistent second home for feedback the toast already carries, and since a fold usually succeeds its common state just echoed the visibly-updated label chips: the append-log surface ADR-0029 (Whispering's dictation-feedback projection) declined to build. It is removed in favor of letting the effect be the receipt (the row leaves the list, the chips update), with the transient toast kept for what the effect does not show. up.ts's handleApi became a const arrow so it inherits the post-guard non-null narrowing directly, dropping an rt/sess re-bind and its inaccurate comment. And a dead reset $effect (the pane already remounts via {#key selectedId}) plus a lastOutcome state mirror are gone.

Changelog

  • Fixed: a freshly-synced Local Mail mailbox with an empty inbox now shows "No messages mirrored / run sync" instead of the "no match" message.

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.

braden-w added 4 commits July 3, 2026 02:09
…er heuristic

selectedLabel defaults to 'INBOX', so the old isFiltered derived was almost
always true and a freshly-synced (empty) mirror showed "No messages match /
try a different label" instead of "No messages mirrored / run sync --full".
Replace the isFiltered prop with mirrorEmpty (status rows.messages === 0), the
real signal for an empty mirror; the SearchX/Inbox icons and both copy strings
follow it.
The re-bind existed to re-narrow runtime/session inside handleApi, but the real
cause was hoisting: a function declaration is checked against the widened type
because it could be called before the guard runs. Making handleApi a const
arrow (defined after the guard) inherits the const narrowing directly, so the
two aliases and their inaccurate "all closures lose narrowing" comment are gone.
Behavior unchanged.
…in MessageDetail

The parent wraps <MessageDetail> in {#key selectedId}, so the whole component
(mutation included) remounts on every selection: id is constant within an
instance, making the "reset on id change" $effect dead. And lastOutcome was
just a copy of modify.data. Delete both; the strip now reads modify.data
directly. No behavior change (the three-branch strip and the toast are
untouched); whether the strip should exist at all is left as an open UX call.
…oast

The strip was a persistent second surface for the same per-action feedback the
toast already carries, and because a fold usually succeeds its common state was
a redundant "Mirror updated" echoing the visibly-changed label chips. This is
the append-log surface ADR-0029 (Whispering's dictation-feedback projection)
declined to build: let the effect be the receipt (the row leaves the list, the
chips update) and keep a transient toast only for what the effect does not show
(the folded:false sync-lag note and errors). Also drops the now-unused CheckIcon
and a pre-existing dead Separator import.
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.

1 participant