summaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-06 20:10:13 +0200
committerDanilo M. <danix@danix.xyz>2026-08-06 20:10:13 +0200
commitdb4dbbf4bf4fd8aab1a9e20d87c266ce7836a946 (patch)
tree90af1ae39e94c610f2b7cbcc5e27c8621da473c5 /docs
parenta0a9306659ff34235db0a1ad537766fe4c161b91 (diff)
downloadqtmaildir-db4dbbf4bf4fd8aab1a9e20d87c266ce7836a946.tar.gz
qtmaildir-db4dbbf4bf4fd8aab1a9e20d87c266ce7836a946.zip
docs: record item 48, tag removal suggests every tag
The remove field's completer is built from knownTags, the whole database's tag list, because TagDialog builds both fields' completers in one loop. Only the tags a thread already carries can be removed from it. The dialog is already given currentTags and uses it to render the existing tags, so the candidate list is in hand and this needs no new plumbing.
Diffstat (limited to 'docs')
-rw-r--r--docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md43
1 files changed, 43 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 85e6ce8..f10a301 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
@@ -95,6 +95,7 @@ taking that too literally.
| 45 | Two Sync buttons, and only one of them works properly | correctness | S | **done** |
| 46 | `uiStateSurvivesARestart` fails under the offscreen platform | testing | XS | **done** |
| 47 | The query bar looks unfinished, and cannot be cleared by mouse | presentation | XS | **done** |
+| 48 | Removing a tag suggests every tag, not the thread's own | workflow | XS | open |
Sizes are rough: XS under an hour, S a sitting, M a session.
@@ -2361,6 +2362,48 @@ user as acceptable; suppressible if it becomes annoying in daily use.
**Verification:** by hand. The tests do not click the ✕, which is a mouse path.
The user confirmed the icon renders correctly, is themed, and clears the field.
+## 48. Removing a tag suggests every tag, not the thread's own
+
+**Observed (user, 2026-08-06):** "when removing a tag from a thread using the
+input box, I get suggested all tags, not only those relevant to the message
+being edited."
+
+**Cause (verified in code):** both fields share one completer setup.
+`TagDialog`'s constructor loops over `{ m_addEdit, m_removeEdit }` and builds
+`new QCompleter(knownTags, edit)` for each (`src/tagdialog.cpp:163-164`), and
+`knownTags` is every tag in the database. That is right for Add, where the point
+is to reach any tag and even create one, and wrong for Remove, where the only
+tags that can be removed are the ones the selected threads already carry.
+
+**The data is already in the dialog.** The constructor takes `currentTags`, a
+`QHash<QString, int>` of tag to how many selected threads carry it
+(`src/tagdialog.h:66-67`), and uses it at `:212` to render the existing-tag
+display. It is simply never given to the remove field's completer, so this needs
+no new plumbing and no worker query.
+
+**Approach.** Build the two completers from different vocabularies rather than
+in one loop: `knownTags` for Add, `currentTags.keys()` for Remove.
+
+**Constraints.**
+
+- **Keep the setWidget/prefix machinery exactly as it is.** Both fields hold a
+ comma-separated list, and `QLineEdit::setCompleter` is the documented trap
+ this dialog already works around, hit twice in this codebase. Only the
+ candidate list changes; the wiring does not.
+- **Completion stays a suggestion, not a whitelist.** The dialog's own comment
+ records that a tag absent from the list is exactly what it exists to create.
+ For Remove that matters less, but typing a tag not in the list must still be
+ possible rather than blocked, so nothing may start validating input against
+ the candidates.
+- On a multi-thread selection `currentTags` is the union across the selection,
+ with counts. That is the right set to offer, since removing a tag two of three
+ threads carry is meaningful. Do not filter to tags every thread has.
+
+**Verification:** a test can construct the dialog with a known `currentTags` and
+assert the remove field's completer offers only those. The keys must be typed,
+not `setText()`, since `setText` does not drive a completer at all, which
+`CLAUDE.md` records.
+
## Deferred, unsized, or split out
Items noted while triaging but not part of the original list. Same numbering