summaryrefslogtreecommitdiffstats
path: root/docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-08-07 11:39:31 +0200
committerDanilo M. <danix@danix.xyz>2026-08-07 11:39:31 +0200
commit0a9ef3c77c7c593f3568f25761aad5d1f55e0e33 (patch)
tree714f2a5f622a43477af50393007fd892434a7a65 /docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md
parent1a6007b4cdaacb22d013daeb58deb6ae72afda07 (diff)
downloadqtmaildir-0a9ef3c77c7c593f3568f25761aad5d1f55e0e33.tar.gz
qtmaildir-0a9ef3c77c7c593f3568f25761aad5d1f55e0e33.zip
feat(sync): the status bar says which account is syncing
"Syncing..." was set once and never updated, so a run that takes over a minute reported nothing about what it was doing. The original diagnosis in the backlog was half wrong, and two further wrong ones were made and discarded before the real cause: plain "mbsync -a" prints NOTHING until it exits, then a single summary line. Measured on a real run, one line at 11:11:08 then 73 within the second 11:11:33, at the end of a 46-second run. So there was no stream to read for the part of a sync that takes time. It is not buffering, so stdbuf changes nothing, and the account name is not unavailable either, which was the second wrong conclusion. mbsync -V is what changes both: it announces each channel as it reaches it, which is at once the progress and the account name originally asked for. The shipped script now passes it. SyncPhaseTracker derives a short status from the output as it streams: the channel being synced, the summary counts when mbsync ends, then the notmuch reindex. It lives beside MailSync rather than in the window so the matching rules are one testable thing, and it holds no widget. Matching is loose and case-insensitive, since the wording varies by version, and nothing in it decides success or failure: the exit status remains the only authority on that. Lines are reassembled in MainWindow before being fed, because QProcess::readAll() splits wherever it happens to and a half-line would match nothing. Every status is sanitised and truncated: the channel name comes from a config file this app does not own, and a long one must not stretch the status bar. Two defects in existing code, fixed with it. setSyncBusy(true) ran after start(), so a fast run's output arrived before the per-run reset and wiped its own phase. And a first draft deferred phases while a transient message showed, which let a "Background sync completed" message armed before the sync began suppress the whole run: a running sync's state outranks an expiring event message. Verified by replaying real captured mbsync -V output through the tracker, not only against fixtures. The MainWindow test paces its script with sleeps, since a script that prints everything at once arrives in one readyRead and makes every intermediate phase unobservable. Closes item 42. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.md52
1 files changed, 45 insertions, 7 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 d98c91e..9424ea4 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
@@ -89,7 +89,7 @@ taking that too literally.
| 39 | Thread list cannot be sorted by clicking a column header | workflow | S | open |
| 40 | No live filter over the current view | workflow | M | open |
| 41 | A message whose HTML body carries a `Content-Id` renders blank | correctness | S | **done** |
-| 42 | "Syncing..." says nothing about what is being synced | feedback | S | open |
+| 42 | "Syncing..." says nothing about what is being synced | feedback | S | **done** |
| 43 | No "Mark all read" for the current view | workflow | S | open |
| 44 | No way to manage the filters applied at sync time | workflow | ? | open, unspecified |
| 45 | Two Sync buttons, and only one of them works properly | correctness | S | **done** |
@@ -2093,18 +2093,34 @@ away.** `assets/mailsync.sh` streams every mbsync and `notmuch new` line,
timestamped, through `tee` (`assets/mailsync.sh:75-96`), and `MailSync` emits
each chunk as `outputReceived` (`src/mailsync.cpp:65-74`), which fills the sync
log pane. The status label is set once to `tr("Syncing...")`
-(`src/mainwindow.cpp:1569`) and never updated until the run finishes. So this
-needs no change to the script and no new channel; it needs the existing stream
-read for state.
+(`src/mainwindow.cpp:1569`) and never updated until the run finishes.
+
+**Correction (2026-08-07, measured): the paragraph above was half wrong, and
+the "no script change needed" claim with it.** `notmuch new` does stream, but
+plain `mbsync -a` prints **nothing at all** until it exits, then one summary
+line. Measured on a real run: one line at 11:11:08, then 73 lines within the
+single second 11:11:33, at the end of a 46-second run. So for the part of a
+sync that actually takes time there was no output to read, and no parsing of
+the existing stream could have fixed that.
+
+Two wrong diagnoses were made and discarded before the real one. It is **not**
+buffering, so `stdbuf` does nothing: the output streams fine, there simply is
+none. And the account name **is** available, contrary to the first reading of
+this item, which concluded it was not and proposed shipping phases only.
+
+`mbsync -V` is what changes both: it announces each channel as it reaches it
+(`Channel <name>`), which is at once the progress indication and the account
+name the user asked for. The shipped script now passes it.
**Approach.** Derive a short status from the output already being received.
- Recognise the phase from the stream: lines before `notmuch new` starts are
mbsync's, and `notmuch new` announces itself. Show "Syncing mail (mbsync)"
then "Reindexing (notmuch)".
-- mbsync prints the channel it is working on, which is the account name the user
- wants to see. Take it from the output rather than from config, so what is shown
- is what is actually happening.
+- mbsync prints the channel it is working on **only under `-V`**, which is the
+ account name the user wants to see. Take it from the output rather than from
+ config, so what is shown is what is actually happening, and in the order it
+ actually happens.
**Constraints.**
@@ -2120,6 +2136,28 @@ read for state.
- Match loosely. mbsync's exact wording varies by version, and a status line that
goes blank because a string moved is worse than the current fixed one.
+**Two defects in existing code, found while building this and fixed with it.**
+
+- `startSync()` called `setSyncBusy(true)` **after** `m_sync->start()`, so any
+ per-run state reset there happened after the process had already produced
+ output. A short run delivers everything before control returns, which wiped
+ the phase those lines had produced. The reset now happens before the launch.
+- The first draft deferred a phase while a transient message was still showing,
+ reading the constraint above as "never clobber a message the user is
+ reading". That let a `Background sync completed` message armed **before** the
+ sync started suppress the entire run's phases, which is how the first hand
+ test came back red. A running sync's state outranks an expiring event
+ message, so the deferral was removed. The constraint it was serving is
+ satisfied the other way round: a phase is written directly rather than
+ through `showTransientStatus()`, so the timer never reclaims it.
+
+**Verification note.** A test script that prints its lines at once is delivered
+in a single `readyRead`, so the tracker sees the whole run in one call and only
+the final phase is ever painted, which makes every intermediate one
+unobservable. `test_mainwindow`'s script therefore paces itself with `sleep`,
+standing in for a real sync's tens of seconds. The parser itself was checked by
+replaying real captured `mbsync -V` output through it.
+
## 43. No "Mark all read" for the current view
**Observed (user, 2026-08-05):** a "Mark All Read" button next to Sync, Archive,