aboutsummaryrefslogtreecommitdiffstats
path: root/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md')
-rw-r--r--docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md53
1 files changed, 5 insertions, 48 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 755caa5..ab11c4f 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
@@ -232,8 +232,8 @@ taking that too literally.
| 159 | The Drafts view lists threads, so a draft is unreachable by double-click | defect | S | **done** 2026-08-25, unreleased. Reverses item 138's own decision, confirmed with the user. `generatorIsFlat()` in `config.cpp` is now the single closed set of flat generators, replacing three hardcoded comparisons against `"sent"`: the built-in filter, the reader that reapplies the mode, and the writer that skips storing what the generator implies. Those three had to agree and nothing made them; a `drafts` entry saved and reloaded would otherwise have come back THREADED while the button was flat. `builtinFilter()` sets `flat` once from the helper rather than in a branch, so the set cannot drift from the labels |
-| 160 | The composer never says a draft was autosaved | feedback | S | open, 2026-08-25, from the notes. Autosave works (`m_autosaveTimer`, `saveDraftNow()`) and is SILENT on success: the only feedback is `m_banner`, which appears on FAILURE. The user asks for a status bar reporting "last autosave 20s ago" progressing to "Draft autosaved", plus an eye-catching "unsaved content" cue whenever `m_dirty` is true. Both states already exist as data; nothing displays them |
-| 161 | The composer has no menu bar | discoverability | S | open, 2026-08-25, from the notes. Save draft on `Ctrl+S` is asked for and does not exist at all: `saveDraftNow()` is reachable only from the timer, Send and `closeEvent`. The composer's actions are ad-hoc `QAction`s parented to the window (Send, Close, and the formatting toolbar's), none registered in `KeyMap`, so item 132's menu-reachability rule does not currently reach them. Depends on 160 for what "saved" then reports |
+| 160 | The composer never says a draft was autosaved | feedback | S | **done** 2026-08-25, unreleased. A status bar on the composer: the age line left, the `○ unsaved content` cue beside it. **The fix is a funnel, not a label.** `m_dirty` had SEVEN writers and four of them clear it, only two of which are a save, so a cue hung off the save path silently missed the constructor and the send; `setDirty()` is the one writer now and refreshes both cues plus `setWindowModified()`. Presentation was **reworked after the user looked at it**: it first reused item 151's yellow ribbon treatment, which reads as a misplaced widget on a bare status label, and the cue sat in the permanent (right-hand) tray. Two defects found by probing rather than by reading, see the section |
+| 161 | The composer has no menu bar | discoverability | S | open, 2026-08-25, from the notes. Save draft on `Ctrl+S` is asked for and does not exist at all: `saveDraftNow()` is reachable only from the timer, Send and `closeEvent`. The composer's actions are ad-hoc `QAction`s parented to the window (Send, Close, and the formatting toolbar's), none registered in `KeyMap`, so item 132's menu-reachability rule does not currently reach them. **Unblocked** 2026-08-25: 160 shipped the status bar, so a manual save now has somewhere to report. Still needs the user to say WHICH main-window actions belong on a composer menu, since most message actions are meaningless over a message being written |
Sizes are rough: XS under an hour, S a sitting, M a session.
@@ -1337,50 +1337,6 @@ The 70-second duration recorded above fits a `QTRY_*` waiting for a file that
is never going to appear, which is consistent with a wrong destination rather
than a slow one.
-## 160. The composer never says a draft was autosaved
-
-**Observed (user, 2026-08-25):** "we should add a status bar to the compose
-window, to report every time a draft is autosaved. With a timer like 'last
-autosave 20s ago' progressing into 'Draft autosaved' and next to it a visually
-highlighted notification 'unsaved content' (blinking, color yellow, something
-eye catching) whenever there's new content since the last autosave."
-
-**Cause (verified in code):** autosave is built and works. `m_autosaveTimer`
-is a single-shot timer restarted on every edit (`composewindow.cpp:960-963`),
-so it fires once the user pauses rather than once per character, and
-`saveDraftNow()` writes the Maildir file. It reports **nothing on success**.
-
-The only feedback that exists is `m_banner`, and it is deliberately a FAILURE
-channel: the comment at `composewindow.cpp:1026` records the reasoning, "a
-PERSISTENT banner, not a modal and not a status-bar line that fades", because
-a failed save must survive until it is dealt with. Success is the opposite
-case and wants the fading line that comment rejected for failure.
-
-**Both states already exist as data**, which is what makes this small:
-
-- `m_dirty` is true exactly when there is content newer than the last save.
-- `m_savedFingerprint` and the `draftSaved` signal mark a successful write.
-
-Nothing displays either. There is no `QStatusBar` on the composer at all.
-
-**Approach.** A `QStatusBar` on the composer, with the age line as a permanent
-widget and the unsaved cue beside it. The age needs a second timer of its own,
-since "20s ago" changes with no edit to drive it; a one-second tick is wasteful
-for a label that reads in tens of seconds, so tick slower and accept the
-granularity.
-
-**Constraints.**
-
-- **Do not reuse `m_banner`.** Its persistence is load-bearing for the quit
- path's honesty, and a success message that shares it would either fade the
- failure away or make success sticky.
-- The "blinking" the note asks for should be treated as "eye-catching", not
- literally: a blinking widget is an accessibility problem and Qt has no
- blink facility to reach for. A yellow ground matching item 151's warning
- severity is the established vocabulary here.
-- `saveDraftNow()` returns false on failure and the banner takes over, so the
- status line must not claim a save the write did not make.
-
## 161. The composer has no menu bar
**Observed (user, 2026-08-25):** "the compose window should have a menu bar on
@@ -1417,6 +1373,7 @@ new action and the existing ones gathered under it rather than duplicated.
- Save draft must go through `saveDraftNow()`, which already handles the
failure banner and emits `draftSaved` for the indexing item 158 added. A
second write path would reintroduce the ghost-file problem that fixed.
-- **Depends on item 160** for what a manual save then reports: with no status
- line, a successful `Ctrl+S` would be as silent as an autosave is now.
+- **Item 160 unblocked this** on 2026-08-25: the status bar exists, so a
+ manual save reports through `refreshDraftStatus()` like an autosave. Route
+ `Ctrl+S` through `saveDraftNow()` and the reporting is already done.