From bcb57a344f40fc0f5e8d619417ce399f169fad25 Mon Sep 17 00:00:00 2001 From: anyongjitiger Date: Tue, 28 Nov 2023 14:25:54 +0800 Subject: [PATCH 1/6] fix: Avatar changes when from offline to online --- src/libs/UserUtils.ts | 57 +++++++++++++++++++++-------- src/libs/actions/PersonalDetails.ts | 2 +- 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/libs/UserUtils.ts b/src/libs/UserUtils.ts index d091cca57df4..1f3040d06332 100644 --- a/src/libs/UserUtils.ts +++ b/src/libs/UserUtils.ts @@ -1,6 +1,10 @@ import Str from 'expensify-common/lib/str'; import {SvgProps} from 'react-native-svg'; import {ValueOf} from 'type-fest'; +import Onyx, { OnyxEntry } from 'react-native-onyx'; +import _ from 'lodash'; +import ONYXKEYS from '@src/ONYXKEYS'; +import { PersonalDetails } from '@src/types/onyx'; import * as defaultAvatars from '@components/Icon/DefaultAvatars'; import {ConciergeAvatar, FallbackAvatar} from '@components/Icon/Expensicons'; import CONST from '@src/CONST'; @@ -13,6 +17,12 @@ type AvatarSource = React.FC | string; type LoginListIndicator = ValueOf | ''; +let allPersonalDetails: OnyxEntry>; +Onyx.connect({ + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + callback: (val) => (allPersonalDetails = _.isEmpty(val) ? {} : val), +}); + /** * Searches through given loginList for any contact method / login with an error. * @@ -68,36 +78,60 @@ function hashText(text: string, range: number): number { return Math.abs(hashCode(text.toLowerCase())) % range; } +/** + * Generate a random accountID base on searchValue. + */ +function generateAccountID(searchValue: string): number { + return hashText(searchValue, 2 ** 32); +} + /** * Helper method to return the default avatar associated with the given accountID * @param [accountID] * @returns */ -function getDefaultAvatar(accountID = -1): React.FC { +function getDefaultAvatar(accountID = -1, avatarURL?: string): React.FC { if (accountID <= 0) { return FallbackAvatar; } if (Number(accountID) === CONST.ACCOUNT_ID.CONCIERGE) { return ConciergeAvatar; } - // There are 24 possible default avatars, so we choose which one this user has based // on a simple modulo operation of their login number. Note that Avatar count starts at 1. - const accountIDHashBucket = ((accountID % CONST.DEFAULT_AVATAR_COUNT) + 1) as AvatarRange; - + let accountIDHashBucket: AvatarRange; + if (avatarURL && /images\/avatars\/default-avatar_\d+\./.test(avatarURL)) { + const match = avatarURL.match(/(?<=default-avatar_)\d+(?=\.)/); + const lastDigit = match && parseInt(match[0], 10); + accountIDHashBucket = lastDigit as AvatarRange; + } else { + accountIDHashBucket = ((accountID % CONST.DEFAULT_AVATAR_COUNT) + 1) as AvatarRange; + } return defaultAvatars[`Avatar${accountIDHashBucket}`]; } /** * Helper method to return default avatar URL associated with login */ -function getDefaultAvatarURL(accountID: string | number = '', isNewDot = false): string { +function getDefaultAvatarURL(accountID: string | number = '', isNewDot = true): string { if (Number(accountID) === CONST.ACCOUNT_ID.CONCIERGE) { return CONST.CONCIERGE_ICON_URL; } - + let email; let originAccountID; + if (allPersonalDetails?.[accountID]) { + if (allPersonalDetails[accountID].login) { + email = allPersonalDetails[accountID].login; + } else if (allPersonalDetails[accountID].displayName) { + email = allPersonalDetails[accountID].displayName; + } + } + if (email) { + originAccountID = generateAccountID(email); + } else { + originAccountID = accountID; + } // Note that Avatar count starts at 1 which is why 1 has to be added to the result (or else 0 would result in a broken avatar link) - const accountIDHashBucket = (Number(accountID) % (isNewDot ? CONST.DEFAULT_AVATAR_COUNT : CONST.OLD_DEFAULT_AVATAR_COUNT)) + 1; + const accountIDHashBucket = (Number(originAccountID) % (isNewDot ? CONST.DEFAULT_AVATAR_COUNT : CONST.OLD_DEFAULT_AVATAR_COUNT)) + 1; const avatarPrefix = isNewDot ? `default-avatar` : `avatar`; return `${CONST.CLOUDFRONT_URL}/images/avatars/${avatarPrefix}_${accountIDHashBucket}.png`; @@ -135,7 +169,7 @@ function isDefaultAvatar(avatarURL?: string | React.FC): boolean { * @param accountID - the accountID of the user */ function getAvatar(avatarURL: AvatarSource, accountID: number): AvatarSource { - return isDefaultAvatar(avatarURL) ? getDefaultAvatar(accountID) : avatarURL; + return isDefaultAvatar(avatarURL) ? getDefaultAvatar(accountID, avatarURL as string) : avatarURL; } /** @@ -184,13 +218,6 @@ function getSmallSizeAvatar(avatarURL: string, accountID: number): AvatarSource return `${source.substring(0, lastPeriodIndex)}_128${source.substring(lastPeriodIndex)}`; } -/** - * Generate a random accountID base on searchValue. - */ -function generateAccountID(searchValue: string): number { - return hashText(searchValue, 2 ** 32); -} - /** * Gets the secondary phone login number */ diff --git a/src/libs/actions/PersonalDetails.ts b/src/libs/actions/PersonalDetails.ts index 29d18d543a11..a157c0500231 100644 --- a/src/libs/actions/PersonalDetails.ts +++ b/src/libs/actions/PersonalDetails.ts @@ -518,7 +518,7 @@ function deleteAvatar() { } // We want to use the old dot avatar here as this affects both platforms. - const defaultAvatar = UserUtils.getDefaultAvatarURL(currentUserAccountID); + const defaultAvatar = UserUtils.getDefaultAvatarURL(currentUserAccountID, false); const optimisticData: OnyxUpdate[] = [ { From 7e9768e06ebfa06ec3dfcc729e40cb2a03c7c8b0 Mon Sep 17 00:00:00 2001 From: anyongjitiger Date: Tue, 28 Nov 2023 14:42:19 +0800 Subject: [PATCH 2/6] fix: Avatar changes when from offline to online --- src/libs/UserUtils.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/UserUtils.ts b/src/libs/UserUtils.ts index 1f3040d06332..26890697f2d6 100644 --- a/src/libs/UserUtils.ts +++ b/src/libs/UserUtils.ts @@ -97,6 +97,7 @@ function getDefaultAvatar(accountID = -1, avatarURL?: string): React.FC Date: Mon, 4 Dec 2023 13:46:29 +0800 Subject: [PATCH 3/6] fix: remove redundant validation --- src/libs/UserUtils.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libs/UserUtils.ts b/src/libs/UserUtils.ts index 509a1597f37f..2d6e10cdd3ff 100644 --- a/src/libs/UserUtils.ts +++ b/src/libs/UserUtils.ts @@ -100,8 +100,14 @@ function getDefaultAvatar(accountID = -1, avatarURL?: string): React.FC Date: Mon, 4 Dec 2023 13:47:15 +0800 Subject: [PATCH 4/6] fix: use newDot avatar --- src/libs/actions/PersonalDetails.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/PersonalDetails.ts b/src/libs/actions/PersonalDetails.ts index a157c0500231..226a05c09acf 100644 --- a/src/libs/actions/PersonalDetails.ts +++ b/src/libs/actions/PersonalDetails.ts @@ -518,7 +518,7 @@ function deleteAvatar() { } // We want to use the old dot avatar here as this affects both platforms. - const defaultAvatar = UserUtils.getDefaultAvatarURL(currentUserAccountID, false); + const defaultAvatar = UserUtils.getDefaultAvatarURL(currentUserAccountID, true); const optimisticData: OnyxUpdate[] = [ { From f66f6a1f49481b9466c7b69a26cc12353d384399 Mon Sep 17 00:00:00 2001 From: anyongjitiger Date: Tue, 5 Dec 2023 09:16:25 +0800 Subject: [PATCH 5/6] fix: remove param in getDefaultAvatarURL --- src/libs/UserUtils.ts | 31 +++++++++-------------------- src/libs/actions/PersonalDetails.ts | 2 +- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/src/libs/UserUtils.ts b/src/libs/UserUtils.ts index 2d6e10cdd3ff..a9b83a3bbff7 100644 --- a/src/libs/UserUtils.ts +++ b/src/libs/UserUtils.ts @@ -101,11 +101,8 @@ function getDefaultAvatar(accountID = -1, avatarURL?: string): React.FC Date: Thu, 7 Dec 2023 09:02:27 +0800 Subject: [PATCH 6/6] fix: prettier --- src/libs/UserUtils.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/UserUtils.ts b/src/libs/UserUtils.ts index a9b83a3bbff7..e95b62cc2437 100644 --- a/src/libs/UserUtils.ts +++ b/src/libs/UserUtils.ts @@ -1,13 +1,13 @@ import Str from 'expensify-common/lib/str'; +import _ from 'lodash'; +import Onyx, {OnyxEntry} from 'react-native-onyx'; import {SvgProps} from 'react-native-svg'; import {ValueOf} from 'type-fest'; -import Onyx, { OnyxEntry } from 'react-native-onyx'; -import _ from 'lodash'; -import ONYXKEYS from '@src/ONYXKEYS'; -import { PersonalDetails } from '@src/types/onyx'; import * as defaultAvatars from '@components/Icon/DefaultAvatars'; import {ConciergeAvatar, FallbackAvatar} from '@components/Icon/Expensicons'; import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import {PersonalDetails} from '@src/types/onyx'; import Login from '@src/types/onyx/Login'; import hashCode from './hashCode';