Skip to content

fix(chat): keep the focused message where it was long-pressed - #1400

Merged
bmc08gt merged 1 commit into
code/cashfrom
fix/chat-edit-scroll-pin
Sep 3, 2026
Merged

fix(chat): keep the focused message where it was long-pressed#1400
bmc08gt merged 1 commit into
code/cashfrom
fix/chat-edit-scroll-pin

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Editing a message part-way up the thread scrolled it off the top. The list is reverseLayout inside an imePadding'd scaffold, so the keyboard shortens the viewport from the bottom and every row rides up by the keyboard's height.

FocusPin hands that height back to the list in the layout pass, letting its bottom-anchored content overflow behind the keyboard so the focused row lands back where it started. Reading the compensation in the layout phase is what keeps it in step with imePadding across the IME animation; a counter-scroll from an effect trails it by a frame the whole way down.

The keyboard's height is not the whole of the movement. The input bar's navigationBarsPadding subtracts the insets the scaffold's imePadding has already consumed, so the bar loses its navigation-bar inset as the keyboard arrives and the list's bottom padding shrinks with it, dropping the content back down. Correcting for the keyboard alone left the row 63px low on a Pixel 10 emulator, exactly that inset, so the pin corrects for both terms. The total is capped at the room the row had above the composer, so a message already sitting near the bar rides up with the bar instead of being buried. On release it animates back to zero rather than being handed to the scroll position, which would have cost the transcript a keyboard's worth of history once the keyboard closed.

The pin holds for the whole focus, not just the edit it can lead to. Tapping the composer with the selection bar up raises the keyboard as well, and a selected message pushed off the top is the same message lost from under the buttons acting on it.

Around that:

  • The transcript stops taking drags for as long as the backdrop is up, selection and edit alike. It is behind the same scrim that already swallows taps.
  • A message arriving mid-edit still scrolls the list, but only as far as the point where the edited row would pass under the top bar.
  • A row long-pressed while it runs under the top bar is brought level with the bar's lower edge, so it isn't left sitting behind the buttons acting on it.
  • Back unwinds the edit, then the selection, before it leaves the conversation.

MessageList had grown to the point where the per-row rendering obscured this, so the row, the pin, the read reporting and the receipt rules move to their own files.

Editing a message part-way up the thread scrolled it off the top. The list is
reverseLayout inside an imePadding'd scaffold, so the keyboard shortens the
viewport from the bottom and every row rides up by the keyboard's height.

FocusPin hands that height back to the list in the layout pass, letting its
bottom-anchored content overflow behind the keyboard so the focused row lands
back where it started. Reading the compensation in the layout phase is what
keeps it in step with imePadding across the IME animation; a counter-scroll from
an effect trails it by a frame the whole way down.

The keyboard's height is not the whole of the movement. The input bar's
navigationBarsPadding subtracts the insets the scaffold's imePadding has already
consumed, so the bar loses its navigation-bar inset as the keyboard arrives and
the list's bottom padding shrinks with it, dropping the content back down.
Correcting for the keyboard alone left the row 63px low on a Pixel 10 emulator,
exactly that inset, so the pin corrects for both terms. The total is capped at
the room the row had above the composer, so a message already sitting near the
bar rides up with the bar instead of being buried. On release it animates back
to zero rather than being handed to the scroll position, which would have cost
the transcript a keyboard's worth of history once the keyboard closed.

The pin holds for the whole focus, not just the edit it can lead to. Tapping the
composer with the selection bar up raises the keyboard as well, and a selected
message pushed off the top is the same message lost from under the buttons
acting on it.

Around that:

- The transcript stops taking drags for as long as the backdrop is up, selection
  and edit alike. It is behind the same scrim that already swallows taps.
- A message arriving mid-edit still scrolls the list, but only as far as the
  point where the edited row would pass under the top bar.
- A row long-pressed while it runs under the top bar is brought level with the
  bar's lower edge, so it isn't left sitting behind the buttons acting on it.
- Back unwinds the edit, then the selection, before it leaves the conversation.

MessageList had grown to the point where the per-row rendering obscured this, so
the row, the pin, the read reporting and the receipt rules move to their own
files.
@bmc08gt bmc08gt self-assigned this Sep 3, 2026
@github-actions github-actions Bot added the type: fix Bug fix label Sep 3, 2026
@bmc08gt
bmc08gt merged commit ab66598 into code/cash Sep 3, 2026
3 checks passed
bmc08gt added a commit that referenced this pull request Sep 3, 2026
Picks up #1397 (UserFlags), #1401 (restores KikCode+Badge/KikCode+Figure/
SVGPath/KikCodeFigureTests), and #1400 (FocusPin/MessageRow/
MessageReadReporter/ReceiptRules) via the true fork point as the merge
base, correcting an earlier rewrite that had reparented this branch onto
code/cash's graph without actually merging its content.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: fix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant