feat: render expanded chart at native resolution and add pinch-zoom via MultiGestureCanvas - #97698
feat: render expanded chart at native resolution and add pinch-zoom via MultiGestureCanvas#97698abbasifaizan70 wants to merge 31 commits into
Conversation
…ia MultiGestureCanvas
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
…70/Expensify into 92969-followup-zoom
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 24d931aac7
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…width) in expanded charts
…high-res, let MultiGestureCanvas own all transforms
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppAndroid: mWeb ChromeiOS: HybridAppiOS: mWeb SafariMacOS: Chrome / Safari |
|
@situchan how's review going? |
|
@situchan any updates on the review? |
…s - blank close, zoom flicker, browser back
|
@situchan Fixed the above-mentioned issues; here videos. Screen.Recording.2026-09-03.at.3.49.28.AM.movScreen.Recording.2026-09-03.at.3.52.11.AM.mov |
|
Lint failing |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9a7a3104b5
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
…n zoom hook, typography disable in test
ReviewBoth issues from my last two comments are fixed — 1. ESLint — 8 errors (blocker)The failing run breaks down into three groups: Alias-for-sibling import (
2. Double-tap still upscales past the rendered resolution on touch
Because Simplest fix: set Nit and testing note
I also tried to verify the three bugs Everything else looks right: the inline path is untouched at Next Steps: Reply with |
…uble-tap zoom at rendered resolution
|
Lint and code feedbacks are fixed. @situchan |
|
Please pull main |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0e1bc2494f
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
🤖 Regression review — one regression found in the expand-modal refactor. The expanded chart's Skia canvas is never unmounted anymoreBefore this PR, both render branches of the expand modal were gated on
That guard is gone on every path:
Two consequences:
Fix: restore the gate. Pass Worth measuring before mergeThe 3× render is a deliberate sharpness tradeoff, but it is unmeasured here. At DPR 2–3 a 2048 px-wide chart canvas has a backing store in the tens of MB, allocated on open whether or not the user zooms, and (per the bug above) retained afterwards. Please check memory and open latency on a low-end Android device with a couple of charts expanded — What I checked that came back clean
Runtime verification was blocked (no web test run)I could not exercise either changed surface in the browser:
So the findings above are code-level only. The white-flash regression in particular should be confirmed by eye: open a chart in dark mode, expand it, and close it. Next Steps: Reply with |
|
@situchan Updated with latest main branch. |
|
@situchan bump for review |
situchan
left a comment
There was a problem hiding this comment.
Bug: modal background flashes
You can see white briefly when closing modal
Screen.Recording.2026-09-10.at.7.13.55.AM.mov
Let's target to get this shipped upon one-time review.
So please make sure to perform full test before requesting re-review. Every time request review, another bugs happen.
Do not purely rely on code generated by Claude.
|
🤖 Regression + code-quality review — one blocker, one touch-device defect. 1. Blocker: the expanded chart's Skia canvas is still never unmountedThis is the same regression I flagged on 2026-09-08 and it is unchanged at Before this PR both render branches were gated on
Fix: wrap 2. Double-tap still overshoots the rendered resolution on tabletsSetting
Fix: clamp the double tap to the render headroom — either honour 3. Code quality
What I checked that came back clean
Web testing — image viewer verified, chart still unreachableThe refactored
So findings #1 and #2 are code-level only. The white flash in particular is worth a quick manual look: open a chart in dark mode, expand it, close it. Next Steps: Reply with view run · no recording available |
…double-tap to zoom range, fix click-to-zoom point, address review feedback
|
|
There's Podfile.lock change which seems unrelated |
|
@situchan Sorry about that — the Podfile.lock change was accidental. I ran pod install locally to fix an iOS build issue, which rewrote a few pod checksums, and it got staged along with the lint fix. There are no native changes in this PR; I've reverted the file to match main. |
|
@situchan Quick note on the new victory-native patch, since it's a judgment call I'd like your view on. The two close bugs conflict: keeping the WebGL canvas mounted during the close animation causes the white flash, while unmounting it causes the blank card you reported. The clean fix is to render the expanded chart as a static bitmap via Skia's __destroyWebGLContextAfterRender, but victory-native doesn't expose its props — hence the small patch (a canvasProps passthrough, JS-only, no native changes). If you'd rather avoid a patch, the alternatives are: (a) restore the isVisible gate and accept the brief blank card on close, or (b) make the close animation near-instant so neither shows. Both are compromises; the patch is the only one that fixes both properly. Happy to switch if you prefer one of those. |
|
Do you think the patch in #100714 fixes that bug or nothing related? |
|
@situchan I don't think so — |
|
@situchan After adding the patch I rebuilt Android locally and re-tested everything end to end — double-tap now stops at the render cap, a small pinch after that no longer snaps back, swipe-down closes the modal, and closing shows no blank or flash. Demo videos attached below. If you still think any improvement, let me know i will take care for that. Screen_Recording_20260911_182050_New.Expensify.Dev.mp4Screen.Recording.2026-09-11.at.6.24.42_PM-compressed.mp4 |


Explanation of Change
Re-renders the expanded chart natively at its target size (via a scaled chart context) instead of raster-upscaling the design-size render, so charts stay sharp on large screens.
Adds pinch/double-tap zoom and pan to the expanded chart using MultiGestureCanvas — the same gestures as the image attachment viewer, as agreed in the follow-up discussion on #95249.
Includes unit tests for the new context-scaling logic.
Fixed Issues
$ #92969
PROPOSAL:#92969 (comment)
Tests
Offline tests
Same as tests.
QA Steps
Same as tests.
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectionAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Screen_Recording_20260825_014636_New.Expensify.Dev.mp4
Android: mWeb Chrome
Screen_Recording_20260825_015755_Chrome.mp4
iOS: Native
Screen.Recording.2026-08-25.at.12.38.37.AM.mov
iOS: mWeb Safari
Screen.Recording.2026-08-25.at.12.53.26.AM.mov
MacOS: Chrome / Safari
Screen.Recording.2026-08-22.at.5.33.50.AM.mp4