diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-14 17:14:33 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-14 17:14:33 +0200 |
| commit | a79725e055699524ec57d09bd484f274ea4a961e (patch) | |
| tree | 8ca944300b3f8e2650940154df73aa8b561bb3b8 /docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md | |
| parent | e876e509b0770a243725b63ea55c9ccf3e41b1bf (diff) | |
| parent | bbf3c570215688c553fd70d8f372ae215725ca02 (diff) | |
| download | qtmaildir-a79725e055699524ec57d09bd484f274ea4a961e.tar.gz qtmaildir-a79725e055699524ec57d09bd484f274ea4a961e.zip | |
Merge: searching from the message pane (item 85)
Five surfaces in the message pane offer a search built from what they show:
the header's subject and date, its sender and recipients on a single-message
thread, a tag chip, a body selection, and every header per message in the
details dialog. Each offers Search for this, which replaces the query, and
Add to search, which narrows it.
The details dialog became labelled rows along the way, which the user wanted
independently of this feature.
Hand tested through every surface, including the case the parenthesising
exists for: adding a sender to 'tag:inbox or tag:flagged' narrows it rather
than widening it.
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.md | 61 |
1 files changed, 61 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 8cfa6b0..8ae8dff 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 @@ -4741,3 +4741,64 @@ how this was found: the suite ran past its two-minute timeout with no output. The cause is not the account at all, it is `showWarnings()` raising a modal from the MainWindow constructor for any config problem, with nothing offscreen to dismiss it. Filed as item 84. + +## 85. Nothing on screen can be searched for by right-clicking it + +**Observed (2026-08-14).** The user asked, while discussing item 78, to be able +to right-click a sender, a subject, a date, a tag chip or a piece of selected +body text and be offered a search built from it, both replacing the query bar +and narrowing what is already in it. The narrowing case decided the shape: a +query returning a thousand threads is refined by adding a second condition, and +before this that meant retyping a query the user never typed. + +**Cause.** Not a defect, unbuilt. `MessageView` had no context menu on any +surface, and `TagStrip` painted chips with no hit test and no signals. + +**Done 2026-08-14**, designed in +`specs/2026-08-14-search-from-message-design.md` and built over eight tasks. +Five surfaces offer **Search for this** and **Add to search**: the header's +subject and date, its From/To/Cc for a single-message thread, a tag chip, a +body selection, and every header per message in the details dialog. + +**What is worth keeping from it.** + +`SearchTerm` (`src/searchterm.h`) owns the whole query grammar and holds no +widget, so the quoting is tested without a painter or a web engine. That +matters because **a mis-quoted notmuch query is not an error, it matches zero**: +nothing downstream would ever report the feature being broken. `extend()` +parenthesises both sides, since `a or b AND c` binds as `a or (b AND c)` and +silently WIDENS a search the user asked to narrow. + +**`Qt::RFC2822Date` validates the weekday against the date**, so `Thu, 14 Aug +2026` parses as invalid: that day is a Friday. Two test fixtures carried a wrong +weekday, one of them pre-existing, and the failure is indistinguishable from the +trailing-comment trap `MimeParser::parseDate` exists to handle. Check a date +fixture with `date -d <yyyy-mm-dd> +%A` rather than writing one from memory. + +The Date: parse was **extracted** into `MimeParser::parseDate` rather than +rewritten, because the existing copy inside a file-local function already +carried the fix for `Qt::RFC2822Date` rejecting a string with a trailing +timezone comment. A second parser without it would have lost the date on a +large share of real mail, showing up only as a menu entry that never appears. + +**The header lists its fields rather than hit-testing them.** It is one +rich-text `QLabel` of up to four lines, and mapping a point through laid-out +rich text breaks as soon as the label wraps. From/To/Cc are offered exactly when +the header displays them, which is a single-message thread, so the menu can +never name a value the header is withholding. + +**The details dialog stopped being a `QPlainTextEdit`**, which the user had +disliked independently. Its plain-textness was a security property rather than a +style: header values come from strangers and plain text cannot interpret markup. +Every value label therefore states `Qt::PlainText` explicitly, because a +`QLabel` guesses under `Qt::AutoText`, and a test enumerates every label and +asserts the format. + +**A modal dialog must close BEFORE the search it asked for runs.** The +connection is direct, so emitting first runs the query synchronously: the model +clears and the pane blanks while the dialog is still up, holding the `m_items` +it was built from. Caught by a test whose mutation check HUNG rather than +failed, which is what a missing `accept()` does to `exec()`. + +**Item 78 stays open**, carrying the rule shortcut alone. The road from a search +to a rule already exists: save the query, then create a rule from it. |
