Slide the main screen over a session with a right swipe

Switching conversation was a step back to the list and a step down into
another, which disposed the session being left and refetched its whole
transcript over the tunnel on the way back. A right swipe now pulls
MainScreen itself over the open session -- the screen Back would have
shown, moved over the session instead of replacing it -- and swiping it
back off returns to a live stream, an unsent draft and the scroll
position it had. Tapping the session already open is that same swipe
back; tapping another is a screen of its own; deleting the one
underneath closes the screen, since there is nothing left to return to.

One gesture drives both this and the subagent panel (SidePanels.kt, now
the home of the drag and animation SubagentPanel had): two draggables
over the same content cannot share a horizontal drag, so the position is
a single signed reveal, negative left and positive right, which also
makes it impossible to have both open. The panels exist only inside a
session, so nothing on the main screen swipes anywhere.

Full width and no tonal step for this one, because a screen standing in
for another must be the same colour as it; the subagent panel keeps its
88% and its sliver. The list keeps its rows while it asks again -- the
panel refetches on every open, and blanking it each time handed the
reader an empty screen about something never in doubt -- with a bar over
the top while an answer is outstanding.

Where the panel has got to is read from draw lambdas only: it changes
every frame of a drag, and a body that reads it recomposes the session
beneath once per frame. Composition sees booleans that change twice per
gesture, the same correction the keyboard inset needed.

Verified on the emulator against the sandbox with ui-trace: the panel
opens and closes on the two swipes, tapping another session replaces the
screen, deleting the open one leaves for the list, the subagent panel is
unchanged, and neither swipe does anything on the main screen. ktfmt,
compile, lint and the unit tests are clean.
This commit is contained in:
iris-ai committed 2026-09-19 22:15:14 -04:00
1 parent ef788b0405
commit c8bfc958ad
8 files changed
+418 -126

No files matched your search

+46
View File
@@ -1207,6 +1207,52 @@ the gesture back to the panel, while Android keeps its own edge Back gesture.
This is also the intended home for background work once that has a list of its
own; only subagents are shown there now.
### The main screen is the other panel over a session (2026-09-19)
**A right swipe pulls the main screen over the open session**, the mirror of
the subagent panel, and for the same reason: switching conversation was a step
back to the list and a step down into another, which disposed the session
being left and refetched its transcript over the tunnel on the way back. The
session under the panel stays composed, so swiping it back off returns to a
live stream, an unsent draft and the scroll position it had.
**It is `MainScreen` itself and the whole width of the screen** (`MainPanel.kt`),
not a list of its own: what the swipe gets is the screen Back would have got,
moved over the session instead of replacing it — tabs, title, refresh and
settings included. A panel narrower than the screen leaves a sliver saying
what it is over, which is right for the subagents and wrong here, and a
full-width panel takes no tonal step either, since a screen standing in for
another must be the same colour as it.
**One gesture drives both panels** (`SidePanels.kt`, which is now where the
subagent panel's drag and animation live). Two `draggable` modifiers over the
same content cannot share a horizontal drag — the inner one claims it
whichever way the finger went and the outer never sees a thing — so the
position is a single signed reveal, negative for the left panel and positive
for the right, which also makes it impossible to have both open. A side with
no panel cannot be dragged toward at all, and that is what makes the gesture
absent until a session has been opened: the main panel exists only inside the
session screen, and nothing on the main screen swipes anywhere.
Tapping the session already open is the same act as swiping the panel back off
— reopening it would hand `SessionScreen` a new summary for the conversation
it is already showing. Tapping any other session is a screen of its own, so
the panel and the session under it go with it. Deleting the session the panel
is drawn over is the one thing the list can do that leaves nothing to swipe
back into, so that closes the screen (`onDeleted`, reported by the list to
whoever is showing it elsewhere).
**The list keeps its rows while it asks again.** The panel refetches every
time it opens, and blanking the list for each of those handed the reader an
empty screen about something never in doubt; a bar over the top says an answer
is outstanding, and only a first load with nothing to keep shows the spinner.
Where the panel has got to is read from draw lambdas only, never from the
composable body: it changes every frame of a drag, and a body that reads it
recomposes the session beneath once per frame. Composition sees booleans that
change twice per gesture — the same correction the keyboard inset needed in
`SessionScreen`.
### HTTP surface
**`routes.rs`'s module doc comment is the table.** REST for actions, one SSE