914985b8b212f0a8c2bd9fea552f415168c1ad8e
A correction made from the layout is a frame late whatever phase it is made in: from placement it is never picked up by another measure and does nothing at all, and from measure it lands on the next frame with the uncorrected one drawn first. That is the flick when a card is opened, and it is why a close could finish somewhere other than where it was aimed -- the two are the same fault. Asked for at the tap instead, the request is consumed by the same measure pass that first lays the row out at its new size, so the resize is drawn once, in its right place. What makes that possible is that none of the three positions needs to know the new height. A top edge holds by placing the item *above* the row where it already is -- that item's bottom edge is the row's top edge whatever becomes of the row, and it does not have to be composed for the list to place it. A close places the row itself against the height it had at the moment it was opened, which is the height it is going back to. So the measure-phase hold, its modifier and the list's `afterMeasure` hook are all gone, and this is 75 lines shorter than the version that could not do it. Checked with ktfmtFormat, compileDebugKotlin, lintDebug and testDebugUnitTest, and on the emulator against a real imported conversation as well as the sandbox: a group closed by its heading lands centred on the tap (1467..1593 for a tap at 1530), a card closed at 1500 and at 1800 lands centred on each, opening by a heading holds the heading to the pixel, and opening or closing a real call inside a group of two leaves that group's heading exactly where it was.
Languages
Rust
53%
Kotlin
44.4%
Shell
2.6%