Open a row downwards, and hold the edge that was pressed

Reinstates the reverted downward-opening rows with the two defects that
made the first attempt worse than what it replaced.

The correction waited on the row's top edge and could wait up to half a
second for it to move. A top edge also moves when the reader scrolls, so a
correction still pending would wake on their drag, read the scroll distance
as the row's growth, and undo it -- the transcript jumping on every expand
and refusing to scroll back at all. It now waits on the row's *size*, which
nothing but a resize changes.

The second is why collapsing a group taller than the screen did nothing at
all. Such a group is the list's own anchor item, so as it shrinks it slides
down behind its anchored bottom edge and out of the viewport, and its size
reads as null -- which `withTimeoutOrNull` cannot tell from the null that
means the wait expired. The case most needing the correction was the one
silently skipped. The wait now answers a value that a timeout cannot, and
the distance is read off any row from the pressed one upwards, all of which
move by exactly the row's growth.

Verified on the emulator with ui-trace (~/.local/bin), which samples the
accessibility tree at 60Hz and reports node bounds in device pixels:
expanding and collapsing from a heading hold it to the pixel, collapsing
from the foot bar holds all four rows below it, a drag 120ms after a tap is
left alone, and scrolling back stays put for six seconds. ktfmt, lint and
85 tests clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
irisandClaude Opus 5 committed 2026-08-30 11:56:53 -04:00
1 parent ec40499ba4
commit cab21442d6
3 files changed
+150 -19

No files matched your search

+12
View File
@@ -624,6 +624,18 @@ dev-updater (Kotlin 2.4.x, CMP 1.11.x, JDK 21). Screens:
output; a spinner while `ToolStart` has no matching `ToolEnd`).
- Question cards inline: option buttons for AskUserQuestion, allow/deny for
permissions, free-text where allowed.
- Expanding a row **opens downwards**: whichever end the reader pressed —
a group's heading or the bar at its foot — is the end that stays put,
and the row grows away from it. The transcript is laid out from the
bottom, so a row's bottom edge is anchored for free and the top one
has to be arranged. `toggleAnchored` waits on the row's *size*, which
a scroll cannot change — a version that waited on the top edge instead
mistook the reader's own drag for the row resizing and undid it — and
then reads how far things moved off any row from the pressed one
upwards, since a group taller than the screen disappears under the
bottom edge as it shrinks and cannot report its own move (2026-08-30,
asked for after groups opened upwards and sent their own heading off
the top of the screen).
- Input bar: text, attach (camera/gallery/file), send — **always enabled**;
mid-run sends become steering messages.
- Top bar: model chip (tap to change), stop button while running, token