Use fallback user avatar in cases where the user is unknown to us#39229
Conversation
8d44e9d to
f606775
Compare
f606775 to
fb6d6d6
Compare
s77rt
left a comment
There was a problem hiding this comment.
Avoid explicitly setting the fallback avatar i.e. replace all instance were we return the fallback avatar with returning null or undefined. Then in the Avatar component if no source is provided then use the fallback avatar
src/pages/DetailsPage.tsx
Outdated
There was a problem hiding this comment.
| avatar: UserUtils.getFallbackAvatar(), |
|
@s77rt that is a good comment in general and I'd prefer to not return the fallback avatar explicitly. I will try to clean this up so that we never pass |
|
@s77rt I have now spent a few hours trying to refactor to returning undefined instead of fallback avatar. That function is used in 10+ files multiple times, and it affects many places - multiple parts of the app that display avatars depend on it. Often its used when creating Some examples of usage that you can check:
(as a quick test you can try to modify the return type of In general this change would affect so many places in the code that I believe its not worth doing in this PR. |
s77rt
left a comment
There was a problem hiding this comment.
Found 2 missing cases where we should use the fallback avatar if user is not found in onyx
- In ReportUtils.getPersonalDetailsForAccountID
- In ProfilePage
|
@s77rt tl;dr Example places where this happens (there might be more):
As you can see in the described examples ☝️ I think there is no way to simply tell whether the user IS or IS NOT known to us, and base the fallback avatar logic on this. At this point Im not sure what is the best way forward, I'm reluctant to modify code related to optimistic accountID generation since it touches multiple places in the app. |
fb6d6d6 to
9293f31
Compare
|
We can definitely call it on this one if it's proving a rabbit hole to fix. It's not high enough priority if it's proven to be complex. One idea to fix this is by tracing/removing all of the We'd then use one single call to Let me know if that's something you already ruled out |
|
@grgia Thanks for the suggestion, I think this is something that is worth investigating.
In this scenario who would do the storing? Frontend code when making an api call and sending it to backend? or backend would do this on their end and always return an avatar url? Otherwise I think this is a sound idea to base the avatar on 1 field (url) instead of calling The only complication I can see is that in some places we don't use a property Tell me what you think |
6e978c8 to
42d2a5e
Compare
blazejkustra
left a comment
There was a problem hiding this comment.
Code looks much cleaner now, but you have conflicts and a lint failing 👍
db4484f to
3cdf8f5
Compare
src/components/Avatar.tsx
Outdated
There was a problem hiding this comment.
this line gives us 100% guarantee that there will be something in the source prop, so that we will at the worst always display FallbackAvatar (if source and accountID are missing).
Thanks to that we can just pass props directly into the Avatar component, and we don't have to call .getAvatar() in multiple places in code.
3cdf8f5 to
7af9cd0
Compare
|
@s77rt ready for re-review |
be930bc to
53b3251
Compare
|
|
||
| function Avatar({ | ||
| source, | ||
| source: originalSource, |
There was a problem hiding this comment.
It's just the source prop renamed to originalSource. We defined a new variable source variable inside.
const source = isWorkspace ? originalSource : UserUtils.getAvatar(originalSource, accountID);The new source variable will take the original source and use the svg version of the avatar if possible.
grgia
left a comment
There was a problem hiding this comment.
Code / changes LGTM, quick question before merging:
Are we still displaying the SVG files?
|
Yes #39229 (comment) |
|
Thanks @s77rt ! |
|
Nice work on this one @Kicu |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚀 Deployed to staging by https://github.com/grgia in version: 1.4.66-0 🚀
|
|
🚀 Deployed to staging by https://github.com/grgia in version: 1.4.66-0 🚀
|
|
🚀 Deployed to production by https://github.com/mountiny in version: 1.4.66-5 🚀
|

Details
<Avatar>componentavatarprop frompersonalDetails. It is returned from backend, and any user "known" to us will have suchaccountIdFallbackAvatarwhen:accountIDaccountIDwas optimistically set in TS codegetAvatar()because what they mostly did was usesource+accountIDto decide whether to show SVG version of default avatar or Concierge avatar. Nowsourceprop is simply passed through the components and the call togetAvatar()is done only once inside<Avatar />.special note for icons:
FallbackAvatarbut sometimes when creatingiconsobject I have to do it, because of patterns like this one: https://github.com/Expensify/App/blob/main/src/components/OptionRow.tsx#L207 - The existence oficonsobject decides whether any kind of Avatar will be shown. That is why you will find?? FallbackAvatarin some placesFixed Issues
$ #38743
PROPOSAL:
Tests
Offline tests
QA Steps
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)myBool && <MyComponent />.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
rec-fallback-andr-SM.mp4
Android: mWeb Chrome
iOS: Native
rec-fallback-ios-SM.mp4
iOS: mWeb Safari
MacOS: Chrome / Safari
rec-fallback-web-1.mp4
rec-fallback-web-2.mp4
MacOS: Desktop