diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-29 13:50:38 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-29 13:50:38 +0200 |
| commit | b1fdf59e22f153e27b6526129fea51f5f679f3b9 (patch) | |
| tree | 469518adb59b20e70d87104186905a280c327710 | |
| parent | acce57fa95219484b69a8978e85f506bacd33d86 (diff) | |
| download | qtmaildir-b1fdf59e22f153e27b6526129fea51f5f679f3b9.tar.gz qtmaildir-b1fdf59e22f153e27b6526129fea51f5f679f3b9.zip | |
docs: correct item 187 against the real folder layout
The entry was written from the assumption that no account names a spam folder,
and concluded a tag generator was therefore the answer. The user corrected it:
some accounts do have one, and the split is not the provider but the mbsync
configuration. A channel with Patterns * receives everything the server has;
the channels that list their folders one by one never name the spam folder,
which the provider does expose.
That rules out both existing shapes. A tag generator finds only what this
application's own Mark spam tagged, missing everything the server filed, which
is most of what those folders hold. A mandatory folder key like trash cannot be
filled for the accounts that have none, and item 103's hazard is live: a
configured folder that does not exist is created and propagates to the server.
Records the layout generically, proposes an optional per-account key composing
a union like sent does, and names the two questions only the user can answer:
whether the view means the folder, the tag or either, and which folder to use
for the account that has two.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NY6poqw199LfFaXe5BHKNe
| -rw-r--r-- | docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md | 76 |
1 files changed, 60 insertions, 16 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 442e0cf..c0db234 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 @@ -260,7 +260,7 @@ taking that too literally. | 184 | New mail waits up to ten minutes, because sync is a fixed cron tick | workflow | ? | open, 2026-08-29, from the user: the 10 minute tick "has always bothered me", and it is already a compromise down from 30. Outgoing edits are immediate (`auto_sync_delay_ms`), so this is the INCOMING half only. Polling faster is not the answer; IMAP IDLE is, and it lives in a watcher that triggers `mailsync.sh`, NOT in qtmaildir, which does no network protocol work. Needs decisions first: which watcher, whether it packages on Slackware, and what the server supports. **Blocked on 174**, whose status file is the reporting channel this needs anyway | | 185 | The message-pane bar offers Reply and Forward on a trashed message | presentation | S | **done 2026-08-29**, unreleased, with 186. The bar has a third branch keyed on the SELECTION being in a trash folder, the same predicate the menus use: Restore, Delete permanently and Empty trash replace the reply pair, and Restore alone is tinted. Added `purge`, the selection-scoped sibling of `empty_trash`, which inherits both its safeguards. Refilled from the digest as well as from the selection, since a conversation's trash-ness is not known until every path is reported. Section in the closed file. Original entry: `MainWindow::refreshMessageBarActions()` (`mainwindow.cpp:2311`) swaps the bar's message half for a DRAFT and for nothing else, so the trash view shows the two actions that make least sense there. The notes ask for Restore and Delete permanently in their place, and for Delete to move here from the main toolbar (item 186). The visibility rules already exist in `refreshTrashActions()`; what is missing is the bar consulting them | | 186 | Delete sits on the main toolbar rather than beside Reply and Forward | presentation | XS | **done 2026-08-29**, unreleased, with 185. Moved to the message bar's ordinary branch; still in the Message and context menus. Section in the closed file. Original entry: `toolBar->addAction(... "delete")` at `mainwindow.cpp:2251`. The user places it with the message actions, so this rides with item 185 rather than being done alone: moving it before the bar is trash-aware leaves Delete in a bar that still offers Reply on trashed mail | -| 187 | There is no Spam view beside Trash | workflow | S | open, 2026-08-29, from the notes. `kQueryGenerators` (`config.cpp:62`) holds six generators and no `spam`, while the `spam` ACTION has existed since 0.2.x and writes the tag. So mail can be marked spam and never listed. A tag generator like `unread`, not a folder one like `trash`: nothing in the config names a spam folder, and adding one would make it a per-account mandatory key like `trash` | +| 187 | There is no Spam view beside Trash | workflow | S | open, 2026-08-29, from the notes; the shape was **corrected 2026-08-29** after looking at the real Maildir, having first been written from a wrong assumption. Spam folders DO exist on some accounts: the two whose mbsync channels use `Patterns *` have a `Spam` folder, one of them a `Junk` beside it, while the accounts whose channels list folders explicitly have none, because that list never names the provider's spam folder. So neither a pure tag generator nor a mandatory folder key like `trash` fits. See the entry | | 188 | Does Empty trash respect the account selector? | question | XS | **answered 2026-08-29** by reading the code, no work needed. It does: `MainWindow::emptyTrash()` (`mainwindow.cpp:6567`) reads `m_accountBox->currentData()` and uses `allTrashQuery()` only for All accounts, and the confirmation names which. Recorded so the notes' question has an answer rather than sitting open | | 189 | The message bar carries only Reply, Forward and Delete | presentation | S | **done 2026-08-29**, unreleased. Star and Archive joined the bar's ordinary branch, Archive leaving the main toolbar as Delete did. `mark_all_read` deliberately did NOT move, at the user's decision: it is the one action that ignores the selection. Item 140's toolbar test listed `archive` as a list-wide action and had to be corrected, which is the classification this item changed. Section in the closed file. Original entry: Asks for Star (`flag`) and Archive on the bar, and raises Mark all read as a question. Two of the three are selection-scoped and fit the bar's rule as it stands; **`mark_all_read` does not**, since it deliberately ignores the selection and acts on every row in the view, which is the one action in the window that does. Needs a decision from the user on that one and on whether Archive LEAVES the main toolbar the way Delete did | @@ -1428,29 +1428,73 @@ spam today and there is no filter that lists it. **Cause.** `kQueryGenerators` (`config.cpp:62`) is a closed set of six: `unread`, `inbox`, `flagged`, `sent`, `drafts`, `trash`. There is no `spam`. The `spam` action has existed since the first toolbar and writes the tag -(`mainwindow.cpp:1760`, adds `spam`, removes `inbox`), so the write half is +(`mainwindow.cpp:1770`, adds `spam`, removes `inbox`), so the write half is built and the read half is missing. -**Approach.** A TAG generator, like `unread` and `flagged`, not a folder one -like `trash`: add `spam` to `kQueryGenerators`, return `spam` from -`generatorTag()`, and give it a label in `builtinFilter()`. Threaded rather -than flat, matching Trash. That is the whole change; `Config::resolvedQuery()` -already composes a tag generator with the account selector. +**The folder layout, measured rather than assumed.** This entry first said no +account names a spam folder and that a tag generator was therefore the answer. +That was wrong, and the user corrected it. What is actually on disk, described +generically since account names are personal data: + +| account shape | spam folders present | +|---|---| +| two accounts, mbsync `Patterns *` | `Spam`; one of them also `Junk`, the other a confirmed-spam/confirmed-ham pair | +| two accounts, explicit `Patterns` list | none | + +The difference is the mbsync configuration, not the provider. A channel with +`Patterns *` receives everything the server has. The other channels name their +folders one by one (inbox, sent, drafts, starred, trash) and simply do not name +the spam one, which the provider does expose over IMAP. Whether to add it there +is a decision for the user in `.mbsyncrc`, and it is NOT this item's to change. + +**So neither existing shape fits, and that is the whole difficulty.** + +- **A pure tag generator** (like `unread` or `flagged`) matches `tag:spam`, + which finds only what this application's own Mark spam action tagged. It + would not show a message the SERVER filed as spam, which is the majority of + what is in those folders and the reason to want the view at all. +- **A folder generator** (like `trash`) needs a per-account key. `trash` is + mandatory and that is safe because every account has one; a mandatory `spam` + key cannot be filled for the two Gmail accounts. Item 103's hazard is live + here: a folder named in config that does not exist is CREATED by the move, + mbsync adopts it, and under `Create Both` it propagates to the server where + every other client sees it. A wrong or speculative default would do exactly + that. + +**Approach, and it needs one decision from the user.** An OPTIONAL per-account +`spam` key, defaulting to unset, with the generator composing the union of +whatever is set, in the way `sent` already composes across accounts. An account +with no spam folder contributes nothing rather than a guess. Two sub-questions +the user has to answer, since the repository cannot: + +- **Does the view mean the folder, the tag, or either?** The honest answer is + probably `path:"<account>/<spam folder>/**" or tag:spam` per account, so it shows both what + the server filed and what the user marked. That also makes it useful on the + Gmail accounts, where only the tag half can ever match. +- **Which folder for the account that has both a `Spam` and a `Junk`?** The + key holds one name. Either it takes a list, or the user picks one and the + other stays invisible. **Constraints.** -- **Do NOT make it a folder generator.** No account config names a spam - folder, and adding one would be a new mandatory per-account key with the - item 103 hazard attached: a folder name that does not exist is CREATED and - propagates to the server. +- **Never write a default.** The key is unset unless the user sets it. A + default of `Spam` would be right for the accounts that have one and would + create a folder on the servers that do not. +- **`Config::matchNothingQuery()` for an account that configures nothing**, not + an empty string: notmuch reads an empty query as "match everything", so a + Spam button would otherwise show the whole Maildir for an unconfigured + account. This is the trap `resolvedQuery()` already documents for `sent`. - **The label is translated, the generator is not.** `spam` is stored in `queries.json` and matched against a closed set, so it is wire format; see the `flagged`/"Important" note in `builtinFilter()`. -- **Adding a generator changes queries.json's readable set**, so an older - build reading a file that names `spam` reports an unknown generator and - KEEPS the row. That is the existing behaviour and needs no version bump. -- **The button row is fixed and left to right.** Decide where Spam sits with - the user; the obvious place is beside Trash, which puts it last. +- **Adding a generator changes queries.json's readable set**, so an older build + reading a file that names `spam` reports an unknown generator and KEEPS the + row. That is the existing behaviour and needs no version bump. +- **Mark spam already removes `inbox`** and adds `spam`; it does not move the + file. Whether it SHOULD move it into the account's spam folder, the way + Delete moves into trash, is a separate question this item should not decide + quietly. Moving would make the view path-based and consistent with Trash; not + moving keeps the current behaviour and leans on the tag half. ## 188. Does Empty trash respect the account selector? |
