feat(chat): flash the message a reply-quote jump lands on - #738
Merged
Conversation
Tapping a reply quote scrolled to the quoted message and stopped there, with nothing to separate it from the rows around it. The flash is a keyframe on `BubbleBackgroundView`, the chrome every bubble and cash card already shares, on its own layer above the wash and below the border. The resting opacity stays 0 so a cell recycled mid-flash can't strand a lit bubble, and `apply(fill:radii:identity:)` drops a running flash when the row changes. A jump lands right as the transcript re-dequeues rows around the arriving page, and a recycled cell loses its `CAAnimation`s, so `willDisplay` re-attaches from the original start time: a row displayed twice joins the flash in progress rather than replaying it. Two ordering bugs stopped a deferred jump, one waiting on the page that carries the row, from landing at all. The reload branch of `update(items:)` ran the opening scroll-to-bottom before the pending jump, and that scroll queues a re-anchor for the next runloop turn which pulled the transcript back off the message; the jump now runs instead of the opening scroll. Separately, `scrollToBottom`'s deferred re-anchors were fire-and-forget, so one queued by an earlier update still undid a jump that landed first. Both now give way when a `positionClaim` counter has moved.
bmc08gt
added a commit
that referenced
this pull request
Sep 11, 2026
…discrete-curve * origin/main: (27 commits) fix(database): share one SQLite writer per owner and take write locks up front (#759) feat(chat): declare the payment action on tip DM payments (#752) refactor(chat): drop the deprecated new_messages overlay (#757) feat(notifications): write prefetched messages into the shared store (#756) refactor(store): move the persistence layer into a shared FlipcashStore package (#755) feat(database): move the SQLite store into the App Group container (#754) feat(database): open the store on demand, close it on background (#753) feat(nse): extension crash reporting, a WAL checkpoint, and on-device push hooks (#751) feat(home): long-press the You tab to open the account switcher (#749) fix(tests): reset Photos access before the previous app instance lingers (#746) chore: bump version to 2026.9.2 (#745) revert: back out the Coinbase Stable Swapper authority migration (#747) (#750) fix(swap): follow the Coinbase Stable Swapper authority migration (#747) fix(tests): cancel a cash link through the details screen (#744) fix(chat): make the whole Send Cash pill tappable while it stands alone (#743) fix(username): drop a leading @ in the validator (#742) fix(chat): scope the send-button spring to the button (#741) fix(transactions): tighten the details card stack and drop the header badge (#740) fix(transactions): draw View in Chat as a card, not the primary action (#739) feat(chat): flash the message a reply-quote jump lands on (#738) ... # Conflicts: # Code.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved # FlipcashCore/Package.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Tapping a reply quote scrolled the transcript to the quoted message and stopped there, with nothing to separate it from the rows around it.
The flash
It lives on
BubbleBackgroundView— the chrome every bubble and cash card already shares — as a keyframe on its own layer, above the wash and below the border, so it brightens the ground without washing over the text or softening the hairline edge. 0.15s rise, 0.45s hold, 0.40s fade, defined inChatMotionnext to the rest of the transcript's motion.The resting opacity stays 0 throughout; the animation carries the raised value. A cell reconfigured or recycled mid-flash therefore can't strand a lit bubble, and
apply(fill:radii:identity:)drops a running flash when the row identity changes.A jump lands exactly when the transcript is re-dequeueing rows around the page that brought the target in, and a recycled cell loses its
CAAnimations. SowillDisplayre-attaches the flash from its original start time: a row displayed twice joins the flash in progress and still ends when it would have, rather than replaying it.Two ordering bugs underneath
A deferred jump — one that has to wait for the page carrying the row — wasn't landing at all:
update(items:)ran the opening scroll-to-bottom before the pending jump. That scroll queues a re-anchor for the next runloop turn, which pulled the transcript off the message a beat after arriving on it. The jump now runs instead of the opening scroll rather than after it.scrollToBottom's deferred re-anchors were fire-and-forget, so one queued by an earlier update still undid a jump that landed before it ran. Both now capture apositionClaimcounter and give way if a jump has bumped it since.The second is the narrower of the two: it needs a jump inside the same runloop turn as the opening scroll. The first fires on any quote tap that has to page.