aboutsummaryrefslogtreecommitdiffstats
path: root/docs/superpowers/plans
diff options
context:
space:
mode:
Diffstat (limited to 'docs/superpowers/plans')
-rw-r--r--docs/superpowers/plans/2026-08-03-post-0.1.0-usability.md51
1 files changed, 51 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 c799e23..17cf434 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
@@ -117,6 +117,7 @@ taking that too literally.
| 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 | **done** |
| 59 | Archive and Mark all read shipped with the same icon | presentation | XS | **done** |
+| 60 | Next thread dead-ends on the last reply of an expanded thread | defect | XS | open; branch only, fix as part of 53 |
Sizes are rough: XS under an hour, S a sitting, M a session.
@@ -1201,6 +1202,13 @@ screenshots alone did not settle:**
within a thread without returning to the list. An addition on top, not part of
this item.
+**No longer deferred, 2026-08-09.** Folded into the card-list spec, because it
+turned out to be a defect repair rather than an addition: `next_thread` is
+`selectRow(current.row() + 1)`, and in a tree that names a sibling, so from the
+last reply of an expanded thread the action does nothing at all. Up/Down get the
+behaviour for free from `QTreeView`'s own navigation, and Alt+Up/Down keep the
+thread-to-thread jump.
+
**What exists today**, as the starting point: a thread is
one HTML document in one web view, messages stacked in chronological order,
each with a small grey `.msg-header` carrying From and Date
@@ -3643,6 +3651,49 @@ distinguishable are separate properties, and only the first was tested. The
candidate replacement was therefore checked by rendering both icons at 24px and
comparing the images, not by asking whether the name existed.
+## 60. Next thread dead-ends on the last reply of an expanded thread
+
+**Observed (found while specifying 53, 2026-08-09), not user-reported.** On the
+`item-20-message-rows` branch, with a thread expanded and the last reply
+selected, `next_thread` (Ctrl+J) does nothing. It should move to the next
+thread.
+
+**Cause (verified in code).** `mainwindow.cpp:644-655` implements both actions
+as arithmetic on a row NUMBER:
+
+```
+const int row = current.isValid() ? current.row() + 1 : 0;
+if (row < m_model->rowCount())
+ m_threadView->selectRow(row);
+```
+
+A `QTableView` numbers rows once for the whole view, so this was correct before
+item 20. A tree numbers them **per parent**: the last reply of a thread is row
+N of that thread, `row + 1` names a sibling that does not exist, and
+`m_model->rowCount()` with no argument counts top-level threads rather than the
+current parent's children. `prev_thread` fails the mirror case, moving from the
+first reply to nowhere instead of to the thread root.
+
+This is a fresh instance of the rule the branch's own commit message states:
+**nothing may be keyed on a row NUMBER**, because a tree numbers rows per
+parent. That commit lists it for the tag strip's paint walk. Nobody checked the
+navigation actions against the same rule.
+
+**Approach.** Walk with `QTreeView::indexBelow()` / `indexAbove()` from the
+current index, which follow visible rows across parent boundaries. For
+thread-to-thread jumping, skip any index whose `IsMessageRole` is true.
+
+**Specified as part of the card-list spec**
+(`docs/superpowers/specs/2026-08-09-card-list-design.md`), which also adds
+Alt+Up/Down for these actions and relies on `QTreeView`'s built-in Up/Down for
+stepping through replies. Fix it there rather than separately, unless the card
+list is dropped.
+
+**Constraint.** The test that would catch this must start from the **last reply
+of an expanded thread**. A test that arrows down a collapsed list passes against
+the bug, since with nothing expanded every row is top-level and the arithmetic
+is accidentally correct.
+
## Deferred, unsized, or split out
Items noted while triaging but not part of the original list. Same numbering