From b389a83bf0ddf0379780722a5360afb4e64c4b89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Henriques?= Date: Tue, 24 Oct 2023 08:43:03 -0300 Subject: [PATCH 1/7] Rename AvatarWithIndicator to TSX --- .../{AvatarWithIndicator.js => AvatarWithIndicator.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/components/{AvatarWithIndicator.js => AvatarWithIndicator.tsx} (100%) diff --git a/src/components/AvatarWithIndicator.js b/src/components/AvatarWithIndicator.tsx similarity index 100% rename from src/components/AvatarWithIndicator.js rename to src/components/AvatarWithIndicator.tsx From 18b8449e060243355c22510694531a57cc64d0dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Henriques?= Date: Tue, 24 Oct 2023 08:47:02 -0300 Subject: [PATCH 2/7] Migrate AvatarWithIndicator to TS --- src/components/AvatarWithIndicator.tsx | 36 ++++++++++++-------------- src/libs/UserUtils.ts | 6 ++--- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src/components/AvatarWithIndicator.tsx b/src/components/AvatarWithIndicator.tsx index 5e7b8d1ee632..c29507b9dcc5 100644 --- a/src/components/AvatarWithIndicator.tsx +++ b/src/components/AvatarWithIndicator.tsx @@ -1,36 +1,34 @@ import React from 'react'; import {View} from 'react-native'; -import PropTypes from 'prop-types'; -import Avatar from './Avatar'; -import styles from '../styles/styles'; -import Tooltip from './Tooltip'; +import {SvgProps} from 'react-native-svg'; import * as UserUtils from '../libs/UserUtils'; -import Indicator from './Indicator'; +import styles from '../styles/styles'; +import Avatar from './Avatar'; import * as Expensicons from './Icon/Expensicons'; +import Indicator from './Indicator'; +import Tooltip from './Tooltip'; -const propTypes = { +type AvatarWithIndicatorProps = { /** URL for the avatar */ - source: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired, + source: string | React.FC; /** To show a tooltip on hover */ - tooltipText: PropTypes.string, + tooltipText?: string; /** A fallback avatar icon to display when there is an error on loading avatar from remote URL. */ - fallbackIcon: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), -}; - -const defaultProps = { - tooltipText: '', - fallbackIcon: Expensicons.FallbackAvatar, + fallbackIcon?: string | React.FC; }; -function AvatarWithIndicator(props) { +function AvatarWithIndicator({source, tooltipText = '', fallbackIcon = Expensicons.FallbackAvatar}: AvatarWithIndicatorProps) { return ( - + @@ -38,8 +36,6 @@ function AvatarWithIndicator(props) { ); } -AvatarWithIndicator.defaultProps = defaultProps; -AvatarWithIndicator.propTypes = propTypes; AvatarWithIndicator.displayName = 'AvatarWithIndicator'; export default AvatarWithIndicator; diff --git a/src/libs/UserUtils.ts b/src/libs/UserUtils.ts index 15bf3c0f1029..572c4597b514 100644 --- a/src/libs/UserUtils.ts +++ b/src/libs/UserUtils.ts @@ -104,7 +104,7 @@ function getDefaultAvatarURL(accountID: string | number = '', isNewDot = false): * Given a user's avatar path, returns true if user doesn't have an avatar or if URL points to a default avatar * @param [avatarURL] - the avatar source from user's personalDetails */ -function isDefaultAvatar(avatarURL?: string): boolean { +function isDefaultAvatar(avatarURL?: React.FC | string): boolean { if (typeof avatarURL === 'string') { if (avatarURL.includes('images/avatars/avatar_') || avatarURL.includes('images/avatars/default-avatar_') || avatarURL.includes('images/avatars/user/default')) { return true; @@ -131,7 +131,7 @@ function isDefaultAvatar(avatarURL?: string): boolean { * @param avatarURL - the avatar source from user's personalDetails * @param accountID - the accountID of the user */ -function getAvatar(avatarURL: string, accountID: number): React.FC | string { +function getAvatar(avatarURL: React.FC | string, accountID?: number): React.FC | string { return isDefaultAvatar(avatarURL) ? getDefaultAvatar(accountID) : avatarURL; } @@ -162,7 +162,7 @@ function getFullSizeAvatar(avatarURL: string, accountID: number): React.FC. This adds the _128 at the end of the * source URL (before the file type) if it doesn't exist there already. */ -function getSmallSizeAvatar(avatarURL: string, accountID: number): React.FC | string { +function getSmallSizeAvatar(avatarURL: React.FC | string, accountID?: number): React.FC | string { const source = getAvatar(avatarURL, accountID); if (typeof source !== 'string') { return source; From cebcf98619b38ebeabcf3a75c23c171a8e75836f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Henriques?= Date: Wed, 25 Oct 2023 06:23:36 -0300 Subject: [PATCH 3/7] Rename params to better name --- src/libs/UserUtils.ts | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/libs/UserUtils.ts b/src/libs/UserUtils.ts index 572c4597b514..50fc95c8416a 100644 --- a/src/libs/UserUtils.ts +++ b/src/libs/UserUtils.ts @@ -102,21 +102,21 @@ function getDefaultAvatarURL(accountID: string | number = '', isNewDot = false): /** * Given a user's avatar path, returns true if user doesn't have an avatar or if URL points to a default avatar - * @param [avatarURL] - the avatar source from user's personalDetails + * @param [avatarSource] - the avatar source from user's personalDetails */ -function isDefaultAvatar(avatarURL?: React.FC | string): boolean { - if (typeof avatarURL === 'string') { - if (avatarURL.includes('images/avatars/avatar_') || avatarURL.includes('images/avatars/default-avatar_') || avatarURL.includes('images/avatars/user/default')) { +function isDefaultAvatar(avatarSource?: React.FC | string): boolean { + if (typeof avatarSource === 'string') { + if (avatarSource.includes('images/avatars/avatar_') || avatarSource.includes('images/avatars/default-avatar_') || avatarSource.includes('images/avatars/user/default')) { return true; } // We use a hardcoded "default" Concierge avatar - if (avatarURL === CONST.CONCIERGE_ICON_URL_2021 || avatarURL === CONST.CONCIERGE_ICON_URL) { + if (avatarSource === CONST.CONCIERGE_ICON_URL_2021 || avatarSource === CONST.CONCIERGE_ICON_URL) { return true; } } - if (!avatarURL) { + if (!avatarSource) { // If null URL, we should also use a default avatar return true; } @@ -128,11 +128,11 @@ function isDefaultAvatar(avatarURL?: React.FC | string): boolean { * Provided a source URL, if source is a default avatar, return the associated SVG. * Otherwise, return the URL pointing to a user-uploaded avatar. * - * @param avatarURL - the avatar source from user's personalDetails + * @param avatarSource - the avatar source from user's personalDetails * @param accountID - the accountID of the user */ -function getAvatar(avatarURL: React.FC | string, accountID?: number): React.FC | string { - return isDefaultAvatar(avatarURL) ? getDefaultAvatar(accountID) : avatarURL; +function getAvatar(avatarSource: React.FC | string, accountID?: number): React.FC | string { + return isDefaultAvatar(avatarSource) ? getDefaultAvatar(accountID) : avatarSource; } /** @@ -150,8 +150,8 @@ function getAvatarUrl(avatarURL: string, accountID: number): string { * Avatars uploaded by users will have a _128 appended so that the asset server returns a small version. * This removes that part of the URL so the full version of the image can load. */ -function getFullSizeAvatar(avatarURL: string, accountID: number): React.FC | string { - const source = getAvatar(avatarURL, accountID); +function getFullSizeAvatar(avatarSource: React.FC | string, accountID: number): React.FC | string { + const source = getAvatar(avatarSource, accountID); if (typeof source !== 'string') { return source; } @@ -162,8 +162,8 @@ function getFullSizeAvatar(avatarURL: string, accountID: number): React.FC. This adds the _128 at the end of the * source URL (before the file type) if it doesn't exist there already. */ -function getSmallSizeAvatar(avatarURL: React.FC | string, accountID?: number): React.FC | string { - const source = getAvatar(avatarURL, accountID); +function getSmallSizeAvatar(avatarSource: React.FC | string, accountID?: number): React.FC | string { + const source = getAvatar(avatarSource, accountID); if (typeof source !== 'string') { return source; } From 8e34982d458f2d6a7f115a1dc58c1960c6093ad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Henriques?= Date: Wed, 25 Oct 2023 10:38:52 -0300 Subject: [PATCH 4/7] Create AvatarSource type --- src/components/AvatarWithIndicator.tsx | 6 +++--- src/libs/UserUtils.ts | 11 +++++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/components/AvatarWithIndicator.tsx b/src/components/AvatarWithIndicator.tsx index c29507b9dcc5..e5100f084bd0 100644 --- a/src/components/AvatarWithIndicator.tsx +++ b/src/components/AvatarWithIndicator.tsx @@ -1,7 +1,7 @@ import React from 'react'; import {View} from 'react-native'; -import {SvgProps} from 'react-native-svg'; import * as UserUtils from '../libs/UserUtils'; +import {AvatarSource} from '../libs/UserUtils'; import styles from '../styles/styles'; import Avatar from './Avatar'; import * as Expensicons from './Icon/Expensicons'; @@ -10,13 +10,13 @@ import Tooltip from './Tooltip'; type AvatarWithIndicatorProps = { /** URL for the avatar */ - source: string | React.FC; + source: AvatarSource; /** To show a tooltip on hover */ tooltipText?: string; /** A fallback avatar icon to display when there is an error on loading avatar from remote URL. */ - fallbackIcon?: string | React.FC; + fallbackIcon?: AvatarSource; }; function AvatarWithIndicator({source, tooltipText = '', fallbackIcon = Expensicons.FallbackAvatar}: AvatarWithIndicatorProps) { diff --git a/src/libs/UserUtils.ts b/src/libs/UserUtils.ts index 50fc95c8416a..6d068b89305f 100644 --- a/src/libs/UserUtils.ts +++ b/src/libs/UserUtils.ts @@ -8,6 +8,8 @@ import Login from '../types/onyx/Login'; type AvatarRange = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24; +type AvatarSource = React.FC | string; + type LoginListIndicator = ValueOf | ''; /** @@ -104,7 +106,7 @@ function getDefaultAvatarURL(accountID: string | number = '', isNewDot = false): * Given a user's avatar path, returns true if user doesn't have an avatar or if URL points to a default avatar * @param [avatarSource] - the avatar source from user's personalDetails */ -function isDefaultAvatar(avatarSource?: React.FC | string): boolean { +function isDefaultAvatar(avatarSource?: AvatarSource): boolean { if (typeof avatarSource === 'string') { if (avatarSource.includes('images/avatars/avatar_') || avatarSource.includes('images/avatars/default-avatar_') || avatarSource.includes('images/avatars/user/default')) { return true; @@ -131,7 +133,7 @@ function isDefaultAvatar(avatarSource?: React.FC | string): boolean { * @param avatarSource - the avatar source from user's personalDetails * @param accountID - the accountID of the user */ -function getAvatar(avatarSource: React.FC | string, accountID?: number): React.FC | string { +function getAvatar(avatarSource: AvatarSource, accountID?: number): AvatarSource { return isDefaultAvatar(avatarSource) ? getDefaultAvatar(accountID) : avatarSource; } @@ -150,7 +152,7 @@ function getAvatarUrl(avatarURL: string, accountID: number): string { * Avatars uploaded by users will have a _128 appended so that the asset server returns a small version. * This removes that part of the URL so the full version of the image can load. */ -function getFullSizeAvatar(avatarSource: React.FC | string, accountID: number): React.FC | string { +function getFullSizeAvatar(avatarSource: AvatarSource, accountID: number): AvatarSource { const source = getAvatar(avatarSource, accountID); if (typeof source !== 'string') { return source; @@ -162,7 +164,7 @@ function getFullSizeAvatar(avatarSource: React.FC | string, accountID: * Small sized avatars end with _128.. This adds the _128 at the end of the * source URL (before the file type) if it doesn't exist there already. */ -function getSmallSizeAvatar(avatarSource: React.FC | string, accountID?: number): React.FC | string { +function getSmallSizeAvatar(avatarSource: AvatarSource, accountID?: number): AvatarSource { const source = getAvatar(avatarSource, accountID); if (typeof source !== 'string') { return source; @@ -202,3 +204,4 @@ export { getFullSizeAvatar, generateAccountID, }; +export type {AvatarSource}; From 55903d64c61a1b7cf1a7bd480374f4535babc4b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Henriques?= Date: Wed, 29 Nov 2023 18:20:58 -0300 Subject: [PATCH 5/7] Use AvatarSource in ReportAction --- src/types/onyx/ReportAction.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/types/onyx/ReportAction.ts b/src/types/onyx/ReportAction.ts index 891a0ffcb7b8..64e1eb0b7c88 100644 --- a/src/types/onyx/ReportAction.ts +++ b/src/types/onyx/ReportAction.ts @@ -1,5 +1,5 @@ -import {SvgProps} from 'react-native-svg'; import {ValueOf} from 'type-fest'; +import {AvatarSource} from '@libs/UserUtils'; import CONST from '@src/CONST'; import * as OnyxCommon from './OnyxCommon'; import OriginalMessage, {Decision, Reaction} from './OriginalMessage'; @@ -85,7 +85,7 @@ type ReportActionBase = { /** accountIDs of the people to which the whisper was sent to (if any). Returns empty array if it is not a whisper */ whisperedToAccountIDs?: number[]; - avatar?: string | React.FC; + avatar?: AvatarSource; automatic?: boolean; @@ -145,4 +145,4 @@ type ReportAction = ReportActionBase & OriginalMessage; type ReportActions = Record; export default ReportAction; -export type {ReportActions, Message}; +export type {Message, ReportActions}; From 4eea09e2f17aa0b82ea1bc34816dc45c2d86aa14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Henriques?= Date: Wed, 29 Nov 2023 18:27:32 -0300 Subject: [PATCH 6/7] Minor fixes in UserUtils docs --- 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 036eeff82b83..29a43bcf711d 100644 --- a/src/libs/UserUtils.ts +++ b/src/libs/UserUtils.ts @@ -105,7 +105,7 @@ function getDefaultAvatarURL(accountID: string | number = '', isNewDot = false): /** * Given a user's avatar path, returns true if user doesn't have an avatar or if URL points to a default avatar - * @param [avatarSource] - the avatar source from user's personalDetails + * @param avatarSource - the avatar source from user's personalDetails */ function isDefaultAvatar(avatarSource?: AvatarSource): boolean { if (typeof avatarSource === 'string') { @@ -120,7 +120,7 @@ function isDefaultAvatar(avatarSource?: AvatarSource): boolean { } if (!avatarSource) { - // If null URL, we should also use a default avatar + // If null source, we should also use a default avatar return true; } @@ -128,8 +128,8 @@ function isDefaultAvatar(avatarSource?: AvatarSource): boolean { } /** - * Provided a source URL, if source is a default avatar, return the associated SVG. - * Otherwise, return the URL pointing to a user-uploaded avatar. + * Provided an avatar source, if source is a default avatar, return the associated SVG. + * Otherwise, return the URL or SVG pointing to the user-uploaded avatar. * * @param avatarSource - the avatar source from user's personalDetails * @param accountID - the accountID of the user From fef6485b899c7ed07fb22fb293aebc5b6978e337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Henriques?= Date: Wed, 29 Nov 2023 18:32:17 -0300 Subject: [PATCH 7/7] Remove .ruby-version --- ios/.ruby-version | 1 - 1 file changed, 1 deletion(-) delete mode 100644 ios/.ruby-version diff --git a/ios/.ruby-version b/ios/.ruby-version deleted file mode 100644 index a603bb50a29e..000000000000 --- a/ios/.ruby-version +++ /dev/null @@ -1 +0,0 @@ -2.7.5