summaryrefslogtreecommitdiffstats
path: root/docs/superpowers
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-04 11:03:19 +0200
committerDanilo M. <danix@danix.xyz>2026-08-04 12:54:46 +0200
commit272cb9de98ea387b1d73c55333e4058d1af5da47 (patch)
tree5d8270a4ba47c9b84db27b794d6759f5458d4680 /docs/superpowers
parent288733a55ef854bb125de5e0f7c7aaad6800697a (diff)
downloadqtmaildir-272cb9de98ea387b1d73c55333e4058d1af5da47.tar.gz
qtmaildir-272cb9de98ea387b1d73c55333e4058d1af5da47.zip
docs: add items 21-23 and refine item 5 from the user's notes
Four items from the user's own notes that this document did not carry. Item 5 gains two concrete sub-items: a star column for flagged threads, mirroring the paperclip, and the observation that everything looks unread. The second is recorded with a warning rather than as a defect, because bold is already conditional on isUnread() in the model; either the list really is mostly unread or bold leaks through some other path, and that has to be reproduced before the font logic is touched. Item 21, better default shortcuts, records why the defaults moved once already: a bare letter cannot be a menu accelerator, and a bare capital parses to a key no keystroke emits. Both still constrain a second pass, as does the rule against testing reachability with synthetic input. Item 22 is the translatability audit CLAUDE.md has owed since the tr() rule was written, plus the loading machinery, which does not exist at all: no QTranslator, no .ts files, no CMake rule. Those are separate sizes and the item says so. Item 23, saving a query from the UI, carries the one real design question with it: whether the write lands in the hand-edited config or the state file. Saved queries are user intent rather than machine state, which argues against the split item 1 established, so the decision is flagged rather than assumed. It also notes that item 23 may answer postponed item 10 as a side effect, since account-scoped saved queries were exactly what item 10 proposed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'docs/superpowers')
-rw-r--r--docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md109
1 files changed, 109 insertions, 0 deletions
diff --git a/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md b/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md
index 417a980..7fedaf3 100644
--- a/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md
+++ b/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md
@@ -59,6 +59,9 @@ taking that too literally.
| 18 | No visual cue that there are unsynced edits | feedback | S | open |
| 19 | No prompt to sync on exit when edits are pending | behavior | S | open |
| 20 | Thread view does not match the user's mental model | presentation | ? | open, unspecified |
+| 21 | Default shortcuts are not sensible enough | discoverability | S | open |
+| 22 | Translatability audit and i18n wiring | correctness | M | open |
+| 23 | No way to save a search query from the UI | workflow | M | open |
Sizes are rough: XS under an hour, S a sitting, M a session.
@@ -401,6 +404,26 @@ currently hardcodes `#bbb`, `#555`, `#000`, `#666`, `#ddd` and no background,
and will look wrong under a dark theme. That is arguably its own item; see
item 12 below if it gets split out.
+### Refined by the user, 2026-08-04
+
+Two concrete sub-items, from using the list rather than looking at it:
+
+- **"All items look unread (bold), maybe use regular for read items?"**
+ **Check this before changing anything.** Bold is ALREADY conditional:
+ `ThreadListModel::data()` sets it under `Qt::FontRole` only when
+ `thread.isUnread()` (`src/threadlistmodel.cpp:148-152`). So either the
+ observation is that the user's list genuinely is mostly unread, in which case
+ there is no bug and the fix is elsewhere (the density work below), or bold is
+ leaking onto read rows through some path the model does not control. Reproduce
+ against a query with a known mix, e.g. `tag:inbox and not tag:unread`, before
+ touching the font logic.
+
+- **A star column for flagged threads**, mirroring the paperclip column that
+ already exists for attachments. `ThreadSummary` carries the tags and
+ `flagged` is an ordinary notmuch tag, so this needs no new worker query, the
+ same way item 15's paperclip did not. Keep it narrow: an icon column, no
+ text.
+
## 6. Opened message stays unread
**Observed:** opening a message leaves it tagged unread; the user expects it to
@@ -897,6 +920,92 @@ cost first.
not design this item from the description above, which says only what is,
not what was wanted.
+## 21. Default shortcuts are not sensible enough
+
+**Observed (user, 2026-08-04):** "improve the default shortcuts to some sensed
+defaults."
+
+**Unspecified in detail**, so ask which bindings feel wrong before proposing a
+table. What is worth recording is the history, because the defaults have
+already moved once and the reasons still constrain any second pass.
+
+**Where the current defaults came from.** 0.1.0 used bare letters. They were
+replaced in the 0.2.0 menu work for two reasons that have not gone away: a
+single letter cannot be a menu accelerator without claiming that letter
+window-wide, and a bare capital such as `N` parses to an unshifted `Key_N`,
+which no keystroke emits, so `toggle_unread`, `flag` and `sync` were dead keys
+that appeared to be bound. See `KeyMap::defaultBindings()` and
+`normalizeSequence()`.
+
+**Constraints on any new default.**
+
+- **Do not test reachability with synthetic input.** `QTest::keyClick()` does
+ not reproduce a keyboard layout: it reported `Ctrl++` as dead when it is
+ exactly what the `+` key emits on the user's Italian layout. Verify against
+ the real keyboard, as `CLAUDE.md` records.
+- Every binding is overridable in `[keys]`, so this is about what a fresh
+ install feels like, not about what is possible.
+- `Return` is a special case already resolved: it belongs to `open_thread` but
+ the query bar claims it back while focused, so a proposal that moves it must
+ not resurrect that bug.
+
+## 22. Translatability audit and i18n wiring
+
+**Observed (user, 2026-08-04):** "a full check of the codebase and wiring up of
+the i18n system."
+
+**This is a debt `CLAUDE.md` already records.** The rule that every user-facing
+string must be wrapped in `tr()` was added while building query completion, and
+that file states plainly that "pre-existing code has not been audited against
+this rule". This item is that audit, plus the loading machinery which does not
+exist at all.
+
+**Two halves, and they are different sizes.**
+
+- *The audit.* Every user-visible string in `src/` checked for `tr()`, with the
+ translation context correct: a string in a free function needs
+ `Q_DECLARE_TR_FUNCTIONS`, since calling `QObject::tr()` compiles but files it
+ under the wrong context. `lupdate` output is the evidence here, not reading.
+- *The wiring.* Nothing loads a `.qm` file today: there is no `QTranslator` in
+ `main.cpp`, no `.ts` files in the tree, and no CMake rule to build or install
+ them. Until that exists, a translated string has nowhere to come from.
+
+**Constraint:** query syntax is not user-facing text. notmuch keywords such as
+`tag:` and `date:` are wire format and must never be translated, only the prose
+describing them. The completion vocabulary is exactly this trap: the values are
+literal, the descriptions are prose.
+
+**Verification:** run `lupdate` and read the generated `.ts`. A string that
+does not appear there is not translatable, whatever the source looks like.
+
+## 23. No way to save a search query from the UI
+
+**Observed (user, 2026-08-04):** saved queries live in the config file only.
+There is no way to keep a query you have just written without editing
+`qtmaildir.conf` by hand.
+
+**Approach, and one real design question.**
+
+- A "save this query" action that names the current query bar contents and adds
+ it to `[queries]`.
+- The user's own suggestion for presentation: **a few sensible ones as buttons,
+ the rest behind a menu.** Today `SavedQueryBar` shows them all, which does not
+ scale past a handful.
+
+**The design question is where the write goes.** `qtmaildir.conf` is hand-edited
+and owned by the user, and item 1 established the rule that machine-written
+state belongs in `uistate.conf` instead, precisely because QSettings preserves
+neither comments nor key order and would quietly reformat the file on write.
+Saved queries are not machine state though: they are user intent, they belong
+with the hand-written ones, and splitting them across two files so the UI can
+avoid touching one would be worse than either option. Decide explicitly, and
+say so in the README whichever way it goes.
+
+**Relation to item 10.** Item 10 is postponed, but its second half proposed
+exactly this: "saved queries that carry their own account scope, so one action
+gets there". If saved queries gain an account scope here, item 10 may be
+answered as a side effect rather than needing its own work.
+
---
## Deferred, unsized, or split out