Open IuliiaHerets opened 1 week ago
Triggered auto assignment to @puneetlath (Bug
), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.
@puneetlath FYI I haven't added the External label as I wasn't 100% sure about this issue. Please take a look and add the label if you agree it's a bug and can be handled by external contributors
Job added to Upwork: https://www.upwork.com/jobs/~021837227522028493087
Triggered auto assignment to Contributor-plus team member for initial proposal review - @dukenv0307 (External
)
Edited by proposal-police: This proposal was edited at 2024-09-21 10:37:45 UTC.```
Android - Avatar - Profile avatar can be seen only if tap on blank screen
The layout is not changing, so onLayout
is not being called, which prevents updateCanvasSize
from being triggered.
https://github.com/Expensify/App/blob/9160fa585c26d3312fd6d6fbd69d334e66cb373d/src/components/Lightbox/index.tsx#L204-L207
So, the canvasSize
will be undefined
, and isCanvasLoading
will be set to true
.
https://github.com/Expensify/App/blob/9160fa585c26d3312fd6d6fbd69d334e66cb373d/src/components/Lightbox/index.tsx#L94-L95
isCanvasLoading
is true
, the image component will not render, resulting in a blank screen, and this issue occurs
https://github.com/Expensify/App/blob/9160fa585c26d3312fd6d6fbd69d334e66cb373d/src/components/Lightbox/index.tsx#L208
The reason onLayout is not being triggered is that shouldLoadAttachment
is enabled after the parent component has rendered.
The reason onLayout
is not being triggered is that the Send Button is rendered before the AttachmentView component. Its presence at the bottom might be affecting how the onLayout
event is triggered. Since React Native handles layouts asynchronously, the positioning of components in the view hierarchy can influence when their dimensions are calculated and when onLayout
is fired.
To solve this problem, we just need to render the Send Button
at the same time as the AttachmentView
. The code will change to something like this:
// .src/components/AttachmentModal.tsx#L580
- {!!onConfirm && !isConfirmButtonDisabled && (
+ {!!onConfirm && !isConfirmButtonDisabled && shouldLoadAttachment && (
<Button
ref={viewRef(submitRef)}
success
large
style={[styles.buttonConfirm, shouldUseNarrowLayout ? {} : styles.attachmentButtonBigScreen]}
textStyles={[styles.buttonConfirmText]}
text={translate('common.send')}
onPress={submitAndClose}
isDisabled={isConfirmButtonDisabled}
pressOnEnter
/>
)}
[!Note] Note: As I tested, this issue only occurs on Android. We can either update it for Android only or for all platforms, and it will still work under this condition
What alternative solutions did you explore? (Optional)
We should set
We should set shouldLoadAttachment
to true
when isModalOpen
is set. This way, the AttachmentView
will render with the modal, allowing the onLayout
for the attachment view to be triggered.shouldLoadAttachment
to true
when isModalOpen
is set. This way, the AttachmentView
will render same time with Send Button
// .src/components/AttachmentModal.tsx#L368
} else if (fileObject.uri) {
const inputModalType = getModalType(fileObject.uri, fileObject);
+ setShouldLoadAttachment(true);
setIsModalOpen(true);
setSourceState(fileObject.uri);
setFile(fileObject);
setModalType(inputModalType);
}
We should use a ref so that the measurement occurs after the component has mounted, something like this:
// .src/components/Lightbox/index.tsx#L167
+ const viewRef = useRef<View>(null);
// .src/components/Lightbox/index.tsx#L172
+ useEffect(() => {
+ const measureView = () => {
+ viewRef.current?.measure((_, __, width, height) => {
+ setCanvasSize({
+ width: PixelRatio.roundToNearestPixel(width),
+ height: PixelRatio.roundToNearestPixel(height),
+ });
+ });
+ };
+ measureView();
+ }, []);
// .src/components/Lightbox/index.tsx#L204
<View
style={[StyleSheet.absoluteFill, style]}
onLayout={updateCanvasSize}
+ ref={viewRef}
>
Avatar image does not show up or load.
On mobile, we use Lightbox to render the avatar image, however onLayout
is never called because the view does not have a defined size yet.
Which also means the image view is never mounted and ImageView.onload
is also never called.
https://github.com/Expensify/App/blob/9160fa585c26d3312fd6d6fbd69d334e66cb373d/src/components/Lightbox/index.tsx#L204-L207
Initialize canvasSize with any value (i.e 0x0) will force a layout and mount the image view and thus load the image.
so we replace
with
const [canvasSize, setCanvasSize] = useState<CanvasSize>({width: 0, height: 0});
N/A
https://github.com/user-attachments/assets/7928de0e-f53d-498c-99a1-84303a16ed58
@huult @struc Thanks for your proposals. onLayout
should be called on mount (works well in iOS). Can you dig deeper to find the RCA?
FYI, I just tested onLayout
on snack.expo.dev, it worked well on Android
import React from 'react';
import {View, Text} from 'react-native';
const ViewBoxesWithColorAndText = () => {
const [a,setA] = React.useState(0)
return (
<View>
<Text>{a}</Text>
<View
onLayout={(e)=>{
setA(111111)
}}>
</View>
</View>
);
};
export default ViewBoxesWithColorAndText;
The reason onLayout is not being triggered is that shouldLoadAttachment is enabled after the parent component has rendered.
@huult Can you elaborate that?
Apologies, @dukenv0307 for the many changes in the proposal. Could you please review it again? I've updated the problem with more accuracy, and I appreciate your help. Thank you!
@huult It doesn't really convince me, why does this happen on Android only?
📣 It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? 💸
@dukenv0307 ,
I believe this issue is related to the rendering process in Android React Native. According to my RCA, the AttachmentView
is rendered last, after all other components. I'm unsure why the onLayout
is being prevented in AttachmentView
.
With the solution I provided, rendering the Send Button
at the same time as the AttachmentView
seems reasonable and fixes the issue. I also tested it on the web and iOS, and it is still working well.
// .src/components/AttachmentModal.tsx#L580
- {!!onConfirm && !isConfirmButtonDisabled && (
+ {!!onConfirm && !isConfirmButtonDisabled && shouldLoadAttachment && (
@puneetlath, @dukenv0307 Eep! 4 days overdue now. Issues have feelings too...
@puneetlath, @dukenv0307 Still overdue 6 days?! Let's take care of this!
I believe this issue is related to the rendering process in Android React Native
I tested this issue on React Native expo, I didn't face this issue. Can you dig deeper to find the exact RCA?
We also open to receive more proposals
If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!
Version Number: 9.0.39-0 Reproducible in staging?: Y Reproducible in production?: Y Issue reported by: Applause Internal Team
Action Performed:
Expected Result:
Profile avatar should be displayed when open it
Actual Result:
Profile avatar can be seen only if tap on blank screen Same issue occurs when Take photo
Workaround:
Unknown
Platforms:
Screenshots/Videos
https://github.com/user-attachments/assets/05367f4d-e64f-48cd-bf85-9ab211629dcb
View all open jobs on GitHub
Upwork Automation - Do Not Edit
Issue Owner
Current Issue Owner: @dukenv0307