aboutsummaryrefslogtreecommitdiffstats
path: root/docs/superpowers
diff options
context:
space:
mode:
Diffstat (limited to 'docs/superpowers')
-rw-r--r--docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md79
1 files changed, 43 insertions, 36 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 f559bf1..159643f 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
@@ -112,10 +112,10 @@ taking that too literally.
| 52 | `test_querycompleter` fails under Wayland, passes offscreen | testing | XS | **done** |
| 53 | Message rows still read as a table, not as a conversation | presentation | ? | open, unspecified |
| 54 | A cron sync carries the edits but the count still says pending | correctness | S | **done** |
-| 55 | In a narrow window the message pane is invisible | presentation | XS | open |
+| 55 | In a narrow window the message pane is invisible | presentation | XS | **done** |
| 56 | No action carries an icon, so the toolbar reserves space for nothing | presentation | S | **done** |
| 57 | "Flag" would read better as "Important" or "Starred" | presentation | XS | **done** |
-| 58 | `message_zoom` documents a 0.5 to 3.0 range and enforces none of it | correctness | XS | open |
+| 58 | `message_zoom` documents a 0.5 to 3.0 range and enforces none of it | correctness | XS | **done** |
| 59 | Archive and Mark all read shipped with the same icon | presentation | XS | **done** |
Sizes are rough: XS under an hour, S a sitting, M a session.
@@ -3360,26 +3360,29 @@ Two notes on the verification, both worth more than the passing count:
**Observed (user, 2026-08-08):** "when opening in a squared window, the left
pane takes the whole width (right pane almost invisible)".
-**Cause, verified in code.** The splitter is built at
-`src/mainwindow.cpp:584` with `setStretchFactor(1, 2)` and **no**
-`setSizes()`, and neither pane carries a minimum width. A stretch factor only
-distributes space left over **after** every child's size hint is satisfied. The
-thread view's hint follows its columns, which are set to fixed widths at
-`src/mainwindow.cpp:557-561` and total roughly 886px (28 + 28 + 130 + 180 +
-520), every one of them `Interactive` with `setStretchLastSection(false)` at
-`src/mainwindow.cpp:513`. In a window narrower than that sum plus a usable
-message pane there is no leftover space at all, so the stretch factor never
-applies and the thread view takes essentially everything.
-
-This only bites on first run. Once a splitter position is saved it is restored
-from `window/splitter` (`src/mainwindow.cpp:120-123`), which is why the window
-behaves after the user has dragged it once. Item 1 built that persistence; it
-does not supply a sane starting point.
-
-**Approach.** Give the message view a minimum width so the splitter cannot
-collapse it, and set an initial `setSizes()` proportional to the window rather
-than letting the hints decide. Sizes only apply when nothing is restored, so it
-must go behind the same "no saved state" check as the geometry.
+**Cause, verified in code, and NOT what this item first recorded.** The
+original entry blamed the thread view's size hint, computed as the sum of its
+fixed column widths (~886px) against a `setStretchFactor(1, 2)` with no leftover
+space to distribute. Measured, the hint is **256px**: a `QTableView` does not
+put its column sum in its size hint, so that mechanism never applied and a
+freshly built window splits correctly.
+
+The real trigger is the **restore**, not the first run. A splitter position is
+saved in pixels (`window/splitter`, `src/mainwindow.cpp:120-124`), and the
+user's own state file held `1285/1252`, saved from a wide session. Reopened at
+1136px, `QSplitter::restoreState()` honours the first pane's 1285 verbatim and
+gives the second whatever is left, which is **29px**. That is the sliver in the
+screenshot. It gets worse the wider the window ever was, which is why item 1's
+persistence is where this comes from and why widening the default window would
+have changed nothing.
+
+**Approach, as built.** A `setMinimumWidth()` on the message view plus
+`setCollapsible(1, false)`, and nothing else. A restore-time repair was written
+first, running from `showEvent()` because the splitter has no laid-out width
+until the window is shown, and was then **deleted**: with the floor in place it
+was mutation-tested to be redundant, since the minimum width constrains
+`restoreState()` as much as it constrains a drag. Two mechanisms for one fault
+is one too many.
**Constraints.**
@@ -3550,20 +3553,24 @@ independent confirmation that `flagged` is load-bearing across the suite.
`toolbar_icon_size`, by reading `message_zoom` as the model for a bounded
numeric key and noticing it is not bounded.
-**Cause, verified in code.** `src/config.cpp:79-90` parses the value with
-`toDouble()` and assigns it on success. The parse failure is reported, but
-nothing checks the range. The README documents "0.5 to 3.0" (`README.md`, the
-`[general]` block), and `m_messageZoom` is never clamped anywhere else:
-`src/mainwindow.cpp:145` passes it straight to the saved-state default.
-
-So `message_zoom = 500` is accepted and applied. Unlike the toolbar icon size,
-this one is recoverable, since the zoom is adjustable from the UI and the
-adjusted value is what gets saved, but the first render is unusable.
-
-**Approach.** Clamp with a report, exactly as `toolbar_icon_size` does
-(`src/config.cpp`, the `kMinToolbarIconSize`/`kMaxToolbarIconSize` block). Both
-ends already have documented bounds, so this is applying the README's own
-numbers.
+**Cause, verified in code, and narrower than this item first recorded.** The
+entry claimed the value is applied unclamped and "the first render is
+unusable". It is not. `MessageView::clampZoom()` (`src/messageview.cpp:716`)
+bounds every value to `kMinZoom`/`kMaxZoom`, which are 0.5 and 3.0
+(`src/messageview.h:96-97`), exactly the README's numbers, and
+`MainWindow::restoreUiState()` routes the config value through
+`setZoomFactor()`, so `message_zoom = 500` renders at 3.0.
+
+What is genuinely missing is the **report**. `src/config.cpp` parses with
+`toDouble()` and, on success, assigns without comment, so nothing ever tells
+the user the 500 in their file is not what they are looking at. That silence is
+what the item's own Constraints section asks for.
+
+**Approach, as built.** Report only, no second clamp. `MessageView` owns the
+bounds and already enforces them; a copy in `Config` would be free to drift
+from the one that does the work, so `config.cpp` includes `messageview.h` and
+reports against `MessageView::kMinZoom`/`kMaxZoom`. This is where it differs
+from `toolbar_icon_size`, which has no widget-side enforcement to defer to.
**Constraints.**