Skip to content

fix(chat): arm the reply swipe only where the bubble is - #800

Merged
bmc08gt merged 1 commit into
mainfrom
fix/reply-swipe-gutter
Sep 18, 2026
Merged

bmc08gt merged 1 commit into
mainfrom
fix/reply-swipe-gutter

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator

The leading strip of a chat row was inert for the reply swipe only where the row reserves the author gutter — an incoming row in a group. Everywhere else the swipe still armed from the row's leading edge, which on an outgoing row is empty transcript: the bubble hugs the far side, and there is nothing under the finger. That held in DMs and in groups.

ChatColumnCell.allowsReplySwipe(at:) derives the strip from where the bubble sits instead of from what the row reserves. A point inside the strip starts a swipe only when the bubble covers it; a point outside it is unchanged, so the empty transcript on the trailing side of an incoming row still swipes as before.

Row Before After
Group, incoming inert inert
Group, outgoing armed inert
DM, incoming armed armed
DM, outgoing armed inert

A drag that starts on a bubble always replies, which is what keeps the DM incoming row live: its bubble begins at the row margin, inside the strip.

reservesAuthorGutter is no longer a field. The column's leading inset already puts a group bubble past the gutter, so the bubble's own frame carries the distinction and the cell holds one less piece of state.

This mirrors code-android-app#1501 row for row, including outgoing group rows — that PR swept them in for the same reason, and they would otherwise be the one place the old behaviour survived. Two deltas that don't change what a finger can do: Android decides per row and returns a Dp strip, iOS decides per point from the measured bubble frame; and on a DM incoming row Android arms from x=0 while iOS arms from the bubble's own 12pt margin, which backGestureInset already owns.

ChatColumnCellAuthorGutterTests becomes ChatColumnCellLeadingStripTests, with a case per row kind.

The leading strip went inert only on a row that reserves the author gutter, which
is an incoming row of a group. Every other row armed from its leading edge, where
an outgoing bubble hugs the far side and there is nothing under the finger — in a
DM and in a group alike.

`allowsReplySwipe(at:)` asks where the bubble sits rather than what the row
reserves: a point in the strip starts a swipe only when the bubble covers it,
which is true for exactly one kind of row.

| Row | Before | After |
|---|---|---|
| Group, incoming | inert | inert |
| Group, outgoing | armed | inert |
| DM, incoming | armed | armed |
| DM, outgoing | armed | inert |

A drag that starts on a bubble always replies, and everything outside the strip is
unchanged — the empty transcript on the trailing side of an incoming row still
swipes. `reservesAuthorGutter` goes with the old rule: the column's leading inset
already puts a group bubble past the gutter, so the bubble's own frame carries the
distinction.

Mirrors code-payments/code-android-app#1501, row for row.
@bmc08gt bmc08gt self-assigned this Sep 18, 2026
@bmc08gt
bmc08gt merged commit 8f11872 into main Sep 18, 2026
1 check passed
@bmc08gt
bmc08gt deleted the fix/reply-swipe-gutter branch October 5, 2026 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant