-
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 #41846
Use fallback user avatar in cases where the user is unknown to us #41846
Conversation
src/components/Avatar.tsx
Outdated
// We pass the color styles down to the SVG for the workspace and fallback avatar. | ||
const source = isWorkspace ? originalSource : UserUtils.getAvatar(originalSource, Number(accountID)); | ||
// if it's user avatar then accountID will be a number | ||
const source = isWorkspace ? originalSource : UserUtils.getAvatar(originalSource, accountID as number); |
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.
@s77rt any better ideas for "accountID as number"
?
the logic here is
- if
isWorkspace
is true -> theaccountID
will be apolicyID
which is astring
- if
isWorkspace
false -> accountID is standard user account id which is anumber
I dislike casting via as
, but not sure how to improve this line
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.
We can split the types into two and use union
type AvatarProps = {
...
} & (
| {
type: typeof CONST.ICON_TYPE_AVATAR;
accountID?: number;
}
| {
type: typeof CONST.ICON_TYPE_WORKSPACE;
accountID?: string;
}
);
However for this to work we need to make the type
prop required and remove its default value.
src/pages/ProfilePage.tsx
Outdated
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.
The changes here seem unrelated. Can you please double check
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.
You're asking about ProfilePage
? So the changes are deliberate, and related to fixing #40989.
Basically right now (on main) the decision to show most of the content is based on this line:
const hasMinimumDetails = !isEmptyObject(details.avatar);
(https://github.com/Expensify/App/blob/main/src/pages/ProfilePage.tsx#L154)
But we know that there will be no avatar in case we're offline and rely on optimistic data - as I removed the default avatar from optimistic data almost everywhere.
All the other basic data is there, so I just allow everything to display and the Fallback avatar will be correctly shown.
I also disable clicking on the avatar when it's the fallback displayed
All the other changes are just indentation moved 1 level up. I tested this both in offline and online and it behaves correct I believe.
src/pages/home/report/ReportActionCompose/SuggestionMention.tsx
Outdated
Show resolved
Hide resolved
source?: UserUtils.AvatarSource; | ||
|
||
/** account id if it's user avatar */ | ||
accountID?: number; |
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.
accountID?: number; | |
accountID: number | undefined; |
This should help catch cases where we are missing to pass accountID.
(do same with Avatar component)
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.
Will do it for every Avatar.
What do you think about doing the same for source
?
Now it looks kinda suspicious that I will have:source?: string
but accountID as explicit: number | undefined
almost as if accountID is more important than source.
I used this pattern to find all cases for TS fails, but after this I reverted back to optional with ?
. In 2 cases I had to explicitly pass undefined
and it looked weird IMO. We don't do this pattern anywhere else in code.
There are 2 cases where accountID will be undefined on purpose:
- https://github.com/Expensify/App/blob/main/src/pages/workspace/WorkspaceProfilePage.tsx#L141 - this is workspace avatar, no accountID
- https://github.com/Expensify/App/blob/main/src/pages/NewChatConfirmPage.tsx#L115 - this is for a group chat, it will never be 1 user's avatar
@s77rt thanks for all the comments, some notes from me:
|
src/libs/OptionsListUtils.ts
Outdated
userToInvite.icons = [ | ||
{ | ||
source: UserUtils.getAvatar('', optimisticAccountID), | ||
source: FallbackAvatar, | ||
name: searchValue, | ||
type: CONST.ICON_TYPE_AVATAR, | ||
}, |
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.
Add id: optimisticAccountID
src/libs/SidebarUtils.ts
Outdated
@@ -418,7 +417,7 @@ function getOptionData({ | |||
result.subtitle = subtitle; | |||
result.participantsList = participantPersonalDetailList; | |||
|
|||
result.icons = ReportUtils.getIcons(report, personalDetails, UserUtils.getAvatar(personalDetail?.avatar ?? '', personalDetail?.accountID), '', -1, policy); | |||
result.icons = ReportUtils.getIcons(report, personalDetails, personalDetail?.avatar, '', -1, policy); |
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.
result.icons = ReportUtils.getIcons(report, personalDetails, personalDetail?.avatar, '', -1, policy); | |
result.icons = ReportUtils.getIcons(report, personalDetails, personalDetail?.avatar, personalDetail?.login, personalDetail?.accountID, policy); |
The avatar relays on the account id, if we pass -1 we will end up using the fallback avatar instead of the real avatar (if the used avatar is the default colorful one)
@@ -117,7 +120,7 @@ function ReportActionItemSingle({ | |||
} | |||
|
|||
secondaryAvatar = { | |||
source: UserUtils.getAvatar(secondaryUserAvatar, secondaryAccountId), | |||
source: secondaryUserAvatar, |
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.
NAB. secondaryUserAvatar
is using an empty string as the fallback, let's use the fallback avatar instead
src/components/Avatar.tsx
Outdated
// We pass the color styles down to the SVG for the workspace and fallback avatar. | ||
const source = isWorkspace ? originalSource : UserUtils.getAvatar(originalSource, Number(accountID)); | ||
// if it's user avatar then accountID will be a number | ||
const source = isWorkspace ? originalSource : UserUtils.getAvatar(originalSource, accountID as number); |
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.
We can split the types into two and use union
type AvatarProps = {
...
} & (
| {
type: typeof CONST.ICON_TYPE_AVATAR;
accountID?: number;
}
| {
type: typeof CONST.ICON_TYPE_WORKSPACE;
accountID?: string;
}
);
However for this to work we need to make the type
prop required and remove its default value.
All changes pushes @s77rt For the bug that you found there is something wrong in the whole chain of calls : |
So without workaround it reproduces for me every time on web. I have a feeling that whether you get this bug is related to state of However I tried running it on ios and there I had the correct avatar :/ |
In main / staging can you reproduce the bug? If not then it's a regression and we should fix it without workarounds |
I'm sorry I misunderstood. We are talking about Task > "Assign to me" bug correct?
I strongly believe the bug is related to current state of one's local DB and what That being said I would still keep the workaround as it uses |
Can you please resolve the conflicts and remove the workaround? I cannot reproduce this constantly but feels like we should handle it separately |
@shawnborton or @dubielzyk-expensify I have one more avatar related PR- I just spun up a test build if you'd like to take a look. This one handles the changes to fallback avatars after the first take was reverted |
🧪🧪 Use the links below to test this adhoc build on Android, iOS, Desktop, and Web. Happy testing! 🧪🧪 |
Found a missing spot when viewing the workspace avatar from the workspace overview page: CleanShot.2024-05-17.at.08.42.40.mp4 |
@shawnborton great find. I checked that the same bug is currently appearing on web so its not introduced by my code, but rather another bug after this: #39637 However if thats okey with you guys I could try to fix this within this PR as hopefully that will be faster. |
@shawnborton @grgia rec-bug.mov |
Amazing, thanks! |
@@ -138,7 +138,7 @@ function ReportActionItemSingle({ | |||
source: avatarSource ?? FallbackAvatar, | |||
type: isWorkspaceActor ? CONST.ICON_TYPE_WORKSPACE : CONST.ICON_TYPE_AVATAR, | |||
name: primaryDisplayName ?? '', | |||
id: avatarAccountId, | |||
id: isWorkspaceActor ? report.policyID : avatarAccountId, |
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.
NAB. avatarAccountId
already takes into account the isWorkspaceActor
condition. Change the variable name to avatarId
to avoid confusion
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.
@Kicu Couple minor comments, can you please sync up with main too? Thanks!
@mountiny Done and done |
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 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/mountiny in version: 1.4.77-0 🚀
|
🚀 Deployed to production by https://github.com/puneetlath in version: 1.4.77-11 🚀
|
🚀 Deployed to production by https://github.com/puneetlath in version: 1.4.77-11 🚀
|
Details
<Avatar>
component, almost all calls togetAvatar
andgetDefaultAvatar
were removed as they were mostly concerned with showing a correct SVG avatar version - now<Avatar>
does all thisavatar
prop frompersonalDetails
. It is returned from backend, and any user "known" to us will have it setFallbackAvatar
when:accountID
accountID
was optimistically set in TS codeFallbackAvatar
as source. Otherwise nothing would be shown because of patterns like this one: https://github.com/Expensify/App/blob/main/src/components/OptionRow.tsx#L209Extra notes for reviewer:
accountID
for both user account and policy id.Because of this we were already passing accountID to Avatar component in some places
CC @s77rt
Fixed Issues
$ #38743
$ #40989
$ #40996
PROPOSAL:
Tests
verify that small avatars in mentions from chat are correct including Concierge avatar
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-android-fallback.mp4
Android: mWeb Chrome
iOS: Native
recsm-ios-fallback-demo.mp4
iOS: mWeb Safari
MacOS: Chrome / Safari
rec-web-fallback-demo.mp4
rec-web-fallback-page-err.mp4
rec-web-fallback-quickaction.mp4
MacOS: Desktop