Heic conversion infinitie loader on mWeb#70273
Conversation
|
@QichenZhu Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
Reviewer Checklist
Screenshots/VideosAndroid: HybridApp (N/A)android-native-bug.webmAndroid: mWeb Chromeandroid-web.moviOS: HybridAppios-native.moviOS: mWeb Safariios-web.movMacOS: Chrome / Safarimac-web.movMacOS: Desktopmac-desktop.mov |
|
|
||
| return verifyPngFormat(fileFromBlob).then((isPng) => { | ||
| if (isPng) { | ||
| const correctedFile = Object.assign(new File([blob], fileName.replace(/\.(heic|heif)$/i, '.png'), {type: CONST.IMAGE_FILE_FORMAT.PNG}), { |
There was a problem hiding this comment.
I noticed the JPEG and PNG format detection is only used to rename files. Does the filename actually matter for the server? If not, we could probably simplify this by skipping the JPEG/PNG detection and only detecting HEIC format.
There was a problem hiding this comment.
This conversion (renaming the extension in the file name) is needed only in cases where the user provides a mismatched image (e.g., a JPG file labeled with a .HEIC extension). We need this detection to correctly change the extension.
Without it, we end up with an empty placeholder instead of the image:

There was a problem hiding this comment.
I found the frontend doesn't display it because expensify-common's isImage() function doesn't recognize the file extension. The backend can still scan it.
If I simply give the fake HEIC image a .png extension (even if it's actually a JPEG image), both the frontend and backend accept it just fine.
So it looks like neither the frontend nor backend cares about whether PNG or JPEG files have the right extension, so we don't really need to distinguish between them.
There was a problem hiding this comment.
Ok, I will double check it and remove that part, it might be that with the fallback it is not necessary anymore
There was a problem hiding this comment.
I revisited it and cleaned up the logic.
You are right, after adding the fallback we don't need the additional checks for png and jpg. In that scenario the canvas fallback will do the proper conversion
|
It shouldn’t be related to our changes, since for the native parts we use a different file and a different approach (ImageManipulator). That said, it would still be good to fix it - I’ll look into it. |
|
@QichenZhu Could you verify now? I created the variable for image context. It fixes the android upload for me: Screen.Recording.2025-09-19.at.13.50.51.mp4 |
|
@rinej, I'm still seeing that error on the PR branch (and on main). Also noticed the chat was in an infinite loading state, so it may be related to https://expensify.slack.com/archives/C05LX9D6E07/p1757575934291339. android-native-bug.webmHowever, the upload succeeded if I sent a message first. |
|
After applying the fix on that branch, I’m no longer able to reproduce the issue on Android Native, it is how it looks: Android.mp4When you encountered the infinite loader, it was likely a sign that something else in the app was off, so that might have been the root cause. What do you think about moving forward with the HEIC for web fix? Since using HEIC on Android is not very common, It is a lower priority. cc @mountiny |
|
I’ve just resolved the conflicts with the main after the Windows fix. |
|
Yeah i think if that is already on main we can treat it as a separate issue, can you please complete the review and checklist? @QichenZhu |
mountiny
left a comment
There was a problem hiding this comment.
Asked for unit tests but I dont want to block on this, we can follow up with these
| /** | ||
| * Canvas fallback for converting HEIC to JPEG in web browsers | ||
| */ | ||
| const canvasFallback = (blob: Blob, fileName: string): Promise<File> => { |
There was a problem hiding this comment.
@rinej can you think of ways to add unit test for this logic please?
There was a problem hiding this comment.
sure, I will make some units for it
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
I created the follow up PR with the unit tests -> #71052 |
|
🚀 Deployed to staging by https://github.com/mountiny in version: 9.2.17-0 🚀
|
|
🚀 Deployed to production by https://github.com/roryabraham in version: 9.2.17-6 🚀
|


Explanation of Change
It fixes an issue where some HEIC files cannot be converted properly, causing users to see an infinite loader. To address this, we introduced the following improvements:
Fixed Issues
$ #68778
PROPOSAL: #68778 (comment)
Tests
withCanvasFallback.mp4
Offline tests
QA Steps
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectioncanBeMissingparam foruseOnyxtoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.ScrollViewcomponent to make it scrollable when more elements are added to the page.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
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
MacOS: Desktop