Open a call from its foot upward, as a row already does
A closed call inside a group opened downward wherever it was pressed: the anchor asked for the group's top in every case, which is right for a tap on the call's heading and wrong for one at its foot, where what the reader wants held is the edge under their finger. It is the rule every other row has had since the anchoring went in, applied one level down. An open in the call's lower half now asks for no scroll at all, which is the same answer a row gets and for the same reason: the list holds the group's bottom edge, a Column keeps the calls below the one growing at their distance from it, so the growth comes off the call's top. The closing behaviour is untouched -- the arithmetic is the same shift, written as the one term it cancels down to, since where the call sits in the group and where the group sits in the viewport drop out of it. Checked with ktfmtFormat, compileDebugKotlin, lintDebug and testDebugUnitTest, and on the emulator against a sandbox group of six calls, with enough conversation behind it for the list to actually scroll -- a transcript shorter than the viewport pins to the bottom and gives every anchor the same answer, which is how this was missed. A call closed at 1321..1447: opened from 1430 it leaves the call below it at 1485 to the pixel and takes the growth off its top; opened from 1360 it leaves the calls above it where they are and moves the one below down by the full 327; closed again from 1400 it lands at 1338..1464, centred on the tap within a pixel.
This commit is contained in:
1 parent
ee5bef3686
commit
84f978f16d
2 files changed
+32
-12
No files matched your search
@@ -1210,7 +1210,12 @@ dev-updater (Kotlin 2.4.x, CMP 1.11.x, JDK 21).
|
||||
call is drawn and how tall that card is (`onToolToggle`), which is the
|
||||
part only it knows, and the calls above the one toggled do not move, so
|
||||
shifting the group by the difference puts the call where the finger
|
||||
wants it.
|
||||
wants it. A call opened in its lower half asks for nothing at all, which
|
||||
is the same answer a row gets: the list holds the group's bottom edge, a
|
||||
Column holds the calls below the one growing at their distance from it,
|
||||
and so the growth comes off the call's top. Asking for the group's top
|
||||
in every case — which it did for a day — was an open pressed at the
|
||||
card's foot driving it downward instead.
|
||||
**The scroll is asked for in the gesture, not from the layout that
|
||||
discovers the new height**, and that is what makes it invisible: a
|
||||
request made at the tap is consumed by the same measure pass that first
|
||||
|
||||
@@ -610,7 +610,7 @@ fun SessionScreen(
|
||||
|
||||
/**
|
||||
* The same, for a call inside an open group: the call lands centred on the finger that shut it,
|
||||
* and holds its own top edge when it is opened.
|
||||
* and when it is opened it holds whichever of its own edges the finger is nearer.
|
||||
*
|
||||
* The group is what the list knows -- a call is drawn inside a row rather than being one -- so
|
||||
* the group is what the scroll is asked for, and [top] and [height], which only the group can
|
||||
@@ -618,10 +618,13 @@ fun SessionScreen(
|
||||
* one toggled do not move, so the call's own top stays [top] below the group's, and shifting
|
||||
* the group by the difference puts the call where the finger wants it.
|
||||
*
|
||||
* Holding the group's top edge is what an open wants and is what a close used to get as well.
|
||||
* It is right for the open -- the call's heading is the edge under the finger -- and wrong for
|
||||
* the close by however far down the open call the reader pressed, which for a card of output is
|
||||
* most of the screen: the card appeared to shrink to its own top, a long way from the hand.
|
||||
* The group's top edge is therefore the call's top edge, which is what an open pressed near the
|
||||
* call's heading wants. An open pressed in its lower half wants the call's *bottom* held
|
||||
* instead, and that is what asking for no scroll at all gives: the list holds the group's
|
||||
* bottom edge, a Column keeps the calls below the one growing at their distance from it, and so
|
||||
* the growth comes off the top exactly as it does for a row. Asking for the group's top in
|
||||
* every case -- which it did for a day -- drove a call opened from its foot downward off the
|
||||
* screen.
|
||||
*/
|
||||
fun toggleCallAnchored(
|
||||
row: TranscriptRow,
|
||||
@@ -635,12 +638,24 @@ fun SessionScreen(
|
||||
if (lastTouch.key == row.key && item != null && item.index + 1 < info.totalItemsCount) {
|
||||
val opening = id !in expandedTools
|
||||
val closed = if (opening) null else closedCallHeights[id]
|
||||
val touch = item.offset + lastTouch.height - lastTouch.y
|
||||
// Where the call's top edge is now, and where it has to be for the closed call to sit
|
||||
// centred on the finger; the group's top moves by the difference between them.
|
||||
val callTop = item.offset + lastTouch.height - top
|
||||
val shift = if (closed == null) 0 else touch + closed / 2 - callTop
|
||||
listState.requestScrollToItem(item.index + 1, -(item.offset + item.size + shift))
|
||||
// How far down its own top edge the finger landed is the whole of what the call's
|
||||
// place contributes: where it sits in the group and where the group sits in the
|
||||
// viewport cancel, since both edges move together.
|
||||
val into = lastTouch.y - top
|
||||
fun holdGroupTop(shift: Int) =
|
||||
listState.requestScrollToItem(item.index + 1, -(item.offset + item.size + shift))
|
||||
when {
|
||||
// The call the reader is shutting, centred on the finger that shut it: its top
|
||||
// goes down by how far the finger is into it, less half of what it is becoming.
|
||||
closed != null -> holdGroupTop(closed / 2 - into)
|
||||
// An open in the call's lower half wants its bottom edge held, and that is what
|
||||
// the list and the group do on their own.
|
||||
opening && into >= height / 2 -> {}
|
||||
// What is left holds the call's top, which is the group's top moved by nothing: an
|
||||
// open in the top half, and a close of a call opened before this screen was, which
|
||||
// has no remembered height to land on.
|
||||
else -> holdGroupTop(0)
|
||||
}
|
||||
// Its height as it stands is the height it goes back to when it is shut again.
|
||||
if (opening) closedCallHeights[id] = height
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user