Repository navigation
fix(mobile): match browser GIF timing in the iOS reaction sheet - #9437
Conversation
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 Approved (code-only review).
No defects found.
NativeReactionDetails.swift: ImageIO reportsUnclampedDelayTime0 / 0.01 / 0.02 / 0.05 for a 0/1/2/5 cs GIF (checked with a standalone ImageIO script), sodelay <= 0.01 ? 0.1 : delaygives 0.27 s, matching the DartwithBrowserFrameTimingrule and the new XCTest. Dropping the 0.02 floor changes only frames of 10 ms or less, which now use 100 ms.- Provider test:
withBrowserFrameTimingtests pass locally (3/3). With the provider call reverted toreturn await decode(buffer);, the new provider test fails, so it guards the wiring as described.
Merge blocker (not code): the PR is CONFLICTING because the branch still carries the pre-squash commit from #9432. Rebase onto main and drop that commit, so the diff is just the Swift change plus the tests. The description still says the PR targets the #9432 branch; the base is now main.
Not run here: the RunnerTests XCTests (Mobile Swift CI was still pending).
The reaction details sheet decodes custom emoji natively and showed frames of 10 ms or less for 20 ms, while the Flutter timeline (with the short-delay clamp in MediaImageProvider) shows them for 100 ms, so the same emoji played five times faster in the sheet than in the chip that opened it. Map such frames to 100 ms there too, and drop the 20 ms floor, which browsers do not have. Also cover the provider's use of the clamp: a GIF resolved through MediaImageProvider keeps its 10 ms first frame on screen for 100 ms. Signed-off-by: Tom Brow <[email protected]> Co-authored-by: judge <7615ec4b7ddf99f0bb48e913297f99f8f772d289a1c9ef54e1d906dd55a93ba8@sprout-oss.stage.blox.sqprod.co>
4bf446c to
9c15fba
Compare
🔐 Codex Security Review
Review SummaryOverall Risk: NONE
FindingsNo concrete security, correctness, or reliability findings were identified. Notes
Generated by Codex Security Review | |
Co-authored-by: mboston.Engineer <932d3b6ebea6cc83e091551ae46d1c7e7f8f7d0fa8e9cef5e6facc8544af413b@buzz.block.builderlab.xyz> * origin/main: fix(mobile): require Builderlab consent for existing identities (#8823) feat(mobile): use HTTP/2 on iOS through app-wide URLSessions (#8897) fix(relay): publish a git push only when refs changed; check the protocol by refinement (#9425) fix(mobile): show shared chats under Solo (#9348) chore(release): release Buzz Desktop version 0.5.29 (#9456) feat(mobile): render messages with gpt_markdown 1.3.4 plusparse (#8945) fix(acp): bound observer retention by bytes (#7987) (#9436) Tune release codegen for faster/smaller binaries (#9434) feat(desktop): add dismissible banner pointing to the new buzz app (#9379) fix(mobile): keep publishing presence while the app is open (#9441) feat(mobile): share into Buzz from the iOS share sheet (#9433) fix(mobile): qualify every namesake mention and keep authored mention casing (#9325) fix(mobile): match browser GIF timing in the iOS reaction sheet (#9437) fix(mobile): play short-delay animation frames at browser speed (#9432) buzz-search: read profile names without the profile_name_fields function (#9397) buzz-db: build the community deletion lock key in Rust (#9396) fix(cli): pair for the active community, skip stopped desktops, accept a bare relay host (#9417) test(mobile): run push tests without a gateway dart-define (#9423) fix(mobile): never pop Home when archiving from channel settings (#9387) perf(acp): reduce observer CPU and lock overhead (#9381) Signed-off-by: Matthew Boston <[email protected]>
…count-backfill Co-authored-by: mboston.Engineer <932d3b6ebea6cc83e091551ae46d1c7e7f8f7d0fa8e9cef5e6facc8544af413b@buzz.block.builderlab.xyz> * bostonaholic--agent-reply-count: fix(mobile): require Builderlab consent for existing identities (#8823) feat(mobile): use HTTP/2 on iOS through app-wide URLSessions (#8897) fix(relay): publish a git push only when refs changed; check the protocol by refinement (#9425) fix(mobile): show shared chats under Solo (#9348) chore(release): release Buzz Desktop version 0.5.29 (#9456) feat(mobile): render messages with gpt_markdown 1.3.4 plusparse (#8945) fix(acp): bound observer retention by bytes (#7987) (#9436) Tune release codegen for faster/smaller binaries (#9434) feat(desktop): add dismissible banner pointing to the new buzz app (#9379) fix(mobile): keep publishing presence while the app is open (#9441) feat(mobile): share into Buzz from the iOS share sheet (#9433) fix(mobile): qualify every namesake mention and keep authored mention casing (#9325) fix(mobile): match browser GIF timing in the iOS reaction sheet (#9437) fix(mobile): play short-delay animation frames at browser speed (#9432) buzz-search: read profile names without the profile_name_fields function (#9397) buzz-db: build the community deletion lock key in Rust (#9396) fix(cli): pair for the active community, skip stopped desktops, accept a bare relay host (#9417) test(mobile): run push tests without a gateway dart-define (#9423) fix(mobile): never pop Home when archiving from channel settings (#9387) perf(acp): reduce observer CPU and lock overhead (#9381) Signed-off-by: Matthew Boston <[email protected]>
The two follow-ups from the pre-review of #9432 GIF frame timing, rebased onto main now that it has landed.
iOS reaction details sheet. The sheet decodes custom emoji natively (
NativeMessageImageLoader.decode) and timed each frame asmax(0.02, delay), so with #9432 GIF frame timing a GIF with 0 or 1 cs delays plays at 100 ms per frame in the timeline chip but 20 ms per frame in the sheet opened from it. The decoder now shows frames of 10 ms or less for 100 ms, as browsers andMediaImageProviderdo, and keeps longer frames as written. The 20 ms floor goes with it: browsers keep 11 to 19 ms frames as written too.Provider-level test. The existing tests call
withBrowserFrameTimingdirectly, so removing the provider's call to it left the suite green. A new test resolves a GIF throughMediaImageProviderwith a mock HTTP client and pumps the scheduler's app frames at explicit timestamps: the 10 ms first frame is still showing at 50 ms and is replaced at 100 ms.Regressions
None expected. The sheet already summed the frame delays into one
UIImage.animatedImageduration, so only the per-frame value changes, and only for frames of 10 ms or less, which ran at 20 ms before. Still images and longer frames decode as before. The Dart test drives frame callbacks with explicit timestamps rather than waiting on wall-clock time.Validation
Added tests:
NativeMessageImageLoaderDecodeTestsin RunnerTests (a 0, 1, 2, 5 cs GIF decodes to a 0.27 s animation; a one-frame GIF stays still) andwithBrowserFrameTiming is applied to the frames MediaImageProvider playsinmedia_image_test.dart, which fails when the provider's call is removed (the second frame shows at 50 ms).Full mobile suite: 4,780 tests passed.
flutter analyze: no issues. RunnerTestsNativeMessageImageLoaderDecodeTestsandNativeReactionDetailsTests: all five pass on an iPhone 17 simulator (Xcode build-for-testing of the Debug simulator app). No full-app run: the change is one delay value in a decoder and is covered by the unit tests above.