aboutsummaryrefslogtreecommitdiffstats
path: root/docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-24 12:15:09 +0200
committerDanilo M. <danix@danix.xyz>2026-08-24 12:15:09 +0200
commit98ea0ee4691e60b430bd78eb615838da90bce244 (patch)
treed64d9d02e25f5b04044ad982beefbce3600a1503 /docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md
parent02a795abe731da908928cd08a799ad79002ff421 (diff)
downloadqtmaildir-98ea0ee4691e60b430bd78eb615838da90bce244.tar.gz
qtmaildir-98ea0ee4691e60b430bd78eb615838da90bce244.zip
feat: add a Drafts filter, and close the composer with Ctrl+W
Items 138 and 148. The query row carried Unread, Inbox, Important, Sent and Trash, and no Drafts, though the composer has been autosaving into each account's drafts folder since compose shipped. Reaching them meant typing a query by hand. Smaller than its size suggested: Account::draftsQuery() and Config::allDraftsQuery() already existed for the placeholder pane's drafts count, and builtinFilters() derives the row from kQueryGenerators, so the work was the generator entry, two resolvedQuery branches, a label and an icon. It follows TRASH rather than Sent. Folder-matched like both, because `draft` is a Maildir flag notmuch surfaces as a tag while the folder is what the user means and what the composer actually writes into. But NOT flat: Sent is flat so a thread cannot fold the user's own message back into the conversation it answers, and a draft reply belongs with its conversation for the same reason a trashed message does. An account with no drafts folder shows no button, per item 103's rule. The existing row test surfaced that by failing until its fixture configured one, which is the rule working rather than a defect. Ctrl+W closes the composer, which bound nothing at all: the only way out was the title bar. The action is parented to the composer, so it is a WindowShortcut dispatched to the active one only and the main window's namespace is untouched, exactly like the formatting shortcuts. It calls close() rather than doing anything of its own, since closeEvent() already decides whether the draft is saved and a second route out that skipped it would lose the message. The Italian gains "Bozze"; lrelease reports 478 finished, 0 unfinished.
Diffstat (limited to 'docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md')
-rw-r--r--docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md28
1 files changed, 28 insertions, 0 deletions
diff --git a/docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md b/docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md
index e5a046e..133a761 100644
--- a/docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md
+++ b/docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md
@@ -7320,3 +7320,31 @@ holding an address is a message going somewhere the sender cannot see, which is
worse than the clutter this removes. The seeding runs before `buildUi()`'s
`markDirty()` connections per the constructor's ordering comment, so whatever
decides the initial state has to read the seeded values rather than the widgets.
+
+## 138. No Drafts filter beside Sent and Trash
+
+**Observed.** The query row carries Unread, Inbox, Important, Sent and Trash.
+There is no Drafts button, though the composer has been writing drafts to each
+account's drafts folder since item 123.
+
+**Cause, verified 2026-08-23.** `kQueryGenerators` in `config.cpp:62-66` is a
+closed set of five, and `drafts` is not among them. Every account already
+carries a `drafts` key (`config.cpp:453`), read for the composer's autosave, so
+the data the filter needs is configured and unused by the query row.
+
+**Approach.** Follow `sent`, not `inbox`. A tag query would be wrong for the
+same reason it is wrong for Sent: `draft` is a Maildir flag notmuch surfaces as
+a tag, but the folder is what the user means, and a message a provider marks
+differently would disagree. `Config::allSentQuery()` composes the union over
+every account's folder and `Account::sentQuery()` the per-account half; both
+need a drafts twin. The generator string is wire format and must stay `drafts`
+in queries.json whatever the button is called in a given locale.
+
+**Constraints.** An account with no `drafts` key contributes NOTHING rather
+than an empty term, or the button shows the whole Maildir: this is
+`Config::matchNothingQuery()`'s reason for existing. The hook's carve-out
+(`assets/hooks/qtmaildirconf.py`) reads the same key, so the two now agree on
+what a drafts folder is; they are separate readers and neither should start
+importing the other.
+
+---