-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use fallback user avatar in cases where the user is unknown to us #39229
Use fallback user avatar in cases where the user is unknown to us #39229
Conversation
8d44e9d
to
f606775
Compare
f606775
to
fb6d6d6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
@@ -70,7 +70,7 @@ function DetailsPage({personalDetails, route, session}: DetailsPageProps) { | |||
accountID: optimisticAccountID, | |||
login, | |||
displayName: login, | |||
avatar: UserUtils.getDefaultAvatar(optimisticAccountID), | |||
avatar: UserUtils.getFallbackAvatar(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code looks much cleaner now, but you have conflicts and a lint failing 👍
db4484f
to
3cdf8f5
Compare
src/components/Avatar.tsx
Outdated
const fallbackAvatar = isWorkspace ? ReportUtils.getDefaultWorkspaceAvatar(name) : fallbackIcon || Expensicons.FallbackAvatar; | ||
const fallbackAvatarTestID = isWorkspace ? ReportUtils.getDefaultWorkspaceAvatarTestID(name) : fallbackIconTestID || 'SvgFallbackAvatar Icon'; | ||
const avatarSource = useFallBackAvatar ? fallbackAvatar : source; | ||
const avatarSource = useFallBackAvatar ? fallbackAvatar : UserUtils.getAvatar(source, accountID) ?? Expensicons.FallbackAvatar; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
This bug #39229 (comment) is on staging so let's not block on that |
@s77rt ready for re-review |
be930bc
to
53b3251
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
}; | ||
|
||
function Avatar({ | ||
source, | ||
source: originalSource, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's the originalSource?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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>
componentavatar
prop frompersonalDetails
. It is returned from backend, and any user "known" to us will have suchaccountId
FallbackAvatar
when:accountID
accountID
was optimistically set in TS codegetAvatar()
because what they mostly did was usesource
+accountID
to decide whether to show SVG version of default avatar or Concierge avatar. Nowsource
prop is simply passed through the components and the call togetAvatar()
is done only once inside<Avatar />
.special note for icons:
FallbackAvatar
but sometimes when creatingicons
object 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 oficons
object decides whether any kind of Avatar will be shown. That is why you will find?? FallbackAvatar
in some placesFixed Issues
$ #38743
PROPOSAL:
Tests
Offline tests
QA Steps
PR Author Checklist
### Fixed Issues
section aboveTests
sectionOffline steps
sectionQA steps
sectiontoggleReport
and notonIconClick
)myBool && <MyComponent />
.src/languages/*
files and using the translation methodSTYLE.md
) were followedAvatar
, I verified the components usingAvatar
are working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG)
)Avatar
is modified, I verified thatAvatar
is working as expected in all cases)Design
label and/or tagged@Expensify/design
so the design team can review the changes.ScrollView
component to make it scrollable when more elements are added to the page.main
branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTest
steps.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