From 08ffa3df5921341781ab4dfe450d78752a0ed839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Mon, 21 Feb 2022 15:20:30 -0600 Subject: [PATCH 01/89] check if the given report is a Workspace Chat --- src/libs/OptionsListUtils.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index f7a9e3441fbd..05dd3e117b42 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -775,9 +775,13 @@ function getCurrencyListForSections(currencyOptions, searchValue) { * * @param {Object} report * @param {Object} personalDetails - * @returns {String} + * @returns {String[]} */ function getReportIcons(report, personalDetails) { + if (ReportUtils.isPolicyExpenseChat(report)) { + return ['']; + } + // Default rooms have a specific avatar so we can return any non-empty array if (ReportUtils.isChatRoom(report)) { return ['']; From 86a1bbc5a9fd984b1d1794bbd9e03f14e28e8528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Mon, 21 Feb 2022 15:27:56 -0600 Subject: [PATCH 02/89] get the linked policy of the workspace chat --- src/libs/OptionsListUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 05dd3e117b42..416d8720251b 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -779,7 +779,7 @@ function getCurrencyListForSections(currencyOptions, searchValue) { */ function getReportIcons(report, personalDetails) { if (ReportUtils.isPolicyExpenseChat(report)) { - return ['']; + const linkedPolicy = policies[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`]; } // Default rooms have a specific avatar so we can return any non-empty array From ef23069b526f3f75ecff8a07ea310d591b396902 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Mon, 21 Feb 2022 16:35:53 -0600 Subject: [PATCH 03/89] return avatar of the workspace for non-admin users --- src/libs/OptionsListUtils.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 416d8720251b..a7546713aa10 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -779,7 +779,11 @@ function getCurrencyListForSections(currencyOptions, searchValue) { */ function getReportIcons(report, personalDetails) { if (ReportUtils.isPolicyExpenseChat(report)) { - const linkedPolicy = policies[`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`]; + if (report.isOwnPolicyExpenseChat) { + return [lodashGet(policies, [ + `${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`, 'avatarURL', + ])]; + } } // Default rooms have a specific avatar so we can return any non-empty array From a2dc66dc02f67d32b4ca96526bd95ee8b99ccdce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Mon, 21 Feb 2022 16:46:57 -0600 Subject: [PATCH 04/89] return participan and workspace avatar url for admins --- src/libs/OptionsListUtils.js | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index a7546713aa10..b587af608c6b 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -778,24 +778,32 @@ function getCurrencyListForSections(currencyOptions, searchValue) { * @returns {String[]} */ function getReportIcons(report, personalDetails) { - if (ReportUtils.isPolicyExpenseChat(report)) { - if (report.isOwnPolicyExpenseChat) { - return [lodashGet(policies, [ - `${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`, 'avatarURL', - ])]; - } - } - // Default rooms have a specific avatar so we can return any non-empty array if (ReportUtils.isChatRoom(report)) { return ['']; } + const sortedParticipants = _.map(report.participants, dmParticipant => ({ firstName: lodashGet(personalDetails, [dmParticipant, 'firstName'], ''), avatar: lodashGet(personalDetails, [dmParticipant, 'avatarThumbnail'], '') || getDefaultAvatar(dmParticipant), })) .sort((first, second) => first.firstName - second.firstName); + + if (ReportUtils.isPolicyExpenseChat(report)) { + const policyExpenseChatAvatarURL = lodashGet(policies, [ + `${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`, 'avatarURL', + ]); + + // If the user is not an admin for this workspace chat, return avatar of the workspace + if (report.isOwnPolicyExpenseChat) { + return [policyExpenseChatAvatarURL]; + } + + // If the user is an admin, return avatar url of the other participant of the report (this is their workspace chat) and the avatar url of the workspace + return [_.first(sortedParticipants).avatar, policyExpenseChatAvatarURL]; + } + return _.map(sortedParticipants, item => item.avatar); } From 57f4e6c15e742e87a9a91d0e6b4dbbe43d8621f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Mon, 21 Feb 2022 17:40:07 -0600 Subject: [PATCH 05/89] use report.reportName for workspace chats --- src/libs/actions/PersonalDetails.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/PersonalDetails.js b/src/libs/actions/PersonalDetails.js index f7a82ce8699d..8c9b89853a31 100644 --- a/src/libs/actions/PersonalDetails.js +++ b/src/libs/actions/PersonalDetails.js @@ -190,7 +190,7 @@ function getFromReportParticipants(reports) { } const avatars = OptionsListUtils.getReportIcons(report, details); - const reportName = ReportUtils.isChatRoom(report) + const reportName = (ReportUtils.isChatRoom(report) || ReportUtils.isPolicyExpenseChat(report)) ? report.reportName : _.chain(report.participants) .filter(participant => participant !== currentUserEmail) From a61cafb9081f1b9f5db10bea1670c515bfa4438e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Tue, 22 Feb 2022 14:03:24 -0600 Subject: [PATCH 06/89] display workspace chat in search page --- src/libs/OptionsListUtils.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index b587af608c6b..6849d08155ac 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -217,7 +217,8 @@ function createOption(personalDetailList, report, { showChatPreviewLine = false, forcePolicyNamePreview = false, }) { const isChatRoom = ReportUtils.isChatRoom(report); - const hasMultipleParticipants = personalDetailList.length > 1 || isChatRoom; + const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report); + const hasMultipleParticipants = personalDetailList.length > 1 || isChatRoom || isPolicyExpenseChat; const personalDetail = personalDetailList[0]; const hasDraftComment = hasReportDraftComment(report); const hasOutstandingIOU = lodashGet(report, 'hasOutstandingIOU', false); From 425e3b76630d948f528419d865baf011cb6187d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Tue, 22 Feb 2022 14:26:53 -0600 Subject: [PATCH 07/89] get reportName as option.text --- src/libs/OptionsListUtils.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 6849d08155ac..66c6a7aa4703 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -167,7 +167,7 @@ function getParticipantNames(personalDetailList) { * @param {Boolean} isChatRoom * @return {String} */ -function getSearchText(report, personalDetailList, isChatRoom) { +function getSearchText(report, personalDetailList, isChatRoom) { // TODO: change isChatRoom name const searchTerms = []; if (!isChatRoom) { @@ -240,7 +240,7 @@ function createOption(personalDetailList, report, { let text; let alternateText; let icons; - if (isChatRoom) { + if (isChatRoom || isPolicyExpenseChat) { text = lodashGet(report, ['reportName'], ''); alternateText = (showChatPreviewLine && !forcePolicyNamePreview && lastMessageText) ? lastMessageText @@ -275,7 +275,7 @@ function createOption(personalDetailList, report, { isUnread: report ? report.unreadActionCount > 0 : null, hasDraftComment, keyForList: report ? String(report.reportID) : personalDetail.login, - searchText: getSearchText(report, personalDetailList, isChatRoom), + searchText: getSearchText(report, personalDetailList, isChatRoom || isPolicyExpenseChat), isPinned: lodashGet(report, 'isPinned', false), hasOutstandingIOU, iouReportID: lodashGet(report, 'iouReportID'), From d5a963bd399a4b1fb49bf529a2d975957cad3b9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Tue, 22 Feb 2022 14:29:55 -0600 Subject: [PATCH 08/89] expose option.isPolicyExpenseChat to use fullTitle --- src/libs/OptionsListUtils.js | 1 + src/pages/home/sidebar/OptionRow.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 66c6a7aa4703..17a27dfe6707 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -282,6 +282,7 @@ function createOption(personalDetailList, report, { isIOUReportOwner: lodashGet(iouReport, 'ownerEmail', '') === currentUserLogin, iouReportAmount: lodashGet(iouReport, 'total', 0), isChatRoom, + isPolicyExpenseChat, isArchivedRoom: ReportUtils.isArchivedRoom(report), }; } diff --git a/src/pages/home/sidebar/OptionRow.js b/src/pages/home/sidebar/OptionRow.js index 6141fc8d7e29..c78ac290223f 100644 --- a/src/pages/home/sidebar/OptionRow.js +++ b/src/pages/home/sidebar/OptionRow.js @@ -188,7 +188,7 @@ const OptionRow = (props) => { tooltipEnabled={props.showTitleTooltip} numberOfLines={1} textStyles={displayNameStyle} - shouldUseFullTitle={props.option.isChatRoom} + shouldUseFullTitle={props.option.isChatRoom || props.option.isPolicyExpenseChat} /> {props.option.alternateText ? ( Date: Tue, 22 Feb 2022 14:31:15 -0600 Subject: [PATCH 09/89] dislay alternateText for non-admins for workspace chats --- src/libs/OptionsListUtils.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 17a27dfe6707..85526f451877 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -208,9 +208,10 @@ function hasReportDraftComment(report) { * Creates a report list option * * @param {Array} personalDetailList - * @param {Object} [report] - * @param {Boolean} showChatPreviewLine - * @param {Boolean} forcePolicyNamePreview + * @param {Object} report + * @param {Object} options + * @param {Boolean} options.showChatPreviewLine + * @param {Boolean} options.forcePolicyNamePreview * @returns {Object} */ function createOption(personalDetailList, report, { @@ -435,9 +436,10 @@ function getOptions(reports, personalDetails, activeReportID, { if (logins.length <= 1) { reportMapForLogins[logins[0]] = report; } + const isSearchingSomeonesPolicyExpenseChat = !report.isOwnPolicyExpenseChat && searchValue !== ''; allReportOptions.push(createOption(reportPersonalDetails, report, { showChatPreviewLine, - forcePolicyNamePreview, + forcePolicyNamePreview: ReportUtils.isPolicyExpenseChat(report) ? isSearchingSomeonesPolicyExpenseChat : forcePolicyNamePreview, })); }); From efe6be54cef2d0b5956a05cf4ab95287eb7afb60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Tue, 22 Feb 2022 14:33:55 -0600 Subject: [PATCH 10/89] change name param name in getSearchText --- src/libs/OptionsListUtils.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 85526f451877..23e1e09d51b2 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -164,13 +164,13 @@ function getParticipantNames(personalDetailList) { * * @param {Object} report * @param {Array} personalDetailList - * @param {Boolean} isChatRoom + * @param {Boolean} isChatRoomOrPolicyExpenseChat * @return {String} */ -function getSearchText(report, personalDetailList, isChatRoom) { // TODO: change isChatRoom name +function getSearchText(report, personalDetailList, isChatRoomOrPolicyExpenseChat) { const searchTerms = []; - if (!isChatRoom) { + if (!isChatRoomOrPolicyExpenseChat) { _.each(personalDetailList, (personalDetail) => { searchTerms.push(personalDetail.displayName); searchTerms.push(personalDetail.login); @@ -180,7 +180,7 @@ function getSearchText(report, personalDetailList, isChatRoom) { // TODO: change searchTerms.push(...report.reportName); searchTerms.push(..._.map(report.reportName.split(','), name => name.trim())); - if (isChatRoom) { + if (isChatRoomOrPolicyExpenseChat) { const chatRoomSubtitle = ReportUtils.getChatRoomSubtitle(report, policies); searchTerms.push(...chatRoomSubtitle); searchTerms.push(..._.map(chatRoomSubtitle.split(','), name => name.trim())); From 0dab98c7f365418be7b1f799d6ee0e094fdff17b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Tue, 22 Feb 2022 15:27:26 -0600 Subject: [PATCH 11/89] show workspace chat in search page for admins --- src/libs/OptionsListUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 23e1e09d51b2..16f72c6acb29 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -399,7 +399,7 @@ function getOptions(reports, personalDetails, activeReportID, { const logins = lodashGet(report, ['participants'], []); // Report data can sometimes be incomplete. If we have no logins or reportID then we will skip this entry. - const shouldFilterNoParticipants = _.isEmpty(logins) && !ReportUtils.isChatRoom(report) && !ReportUtils.isDefaultRoom(report); + const shouldFilterNoParticipants = _.isEmpty(logins) && !ReportUtils.isChatRoom(report) && !ReportUtils.isDefaultRoom(report) && !ReportUtils.isPolicyExpenseChat(report); if (!report || !report.reportID || shouldFilterNoParticipants) { return; } From 7195cd2fb8a7ee0f353304ac82f1c8399f84c778 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Tue, 22 Feb 2022 18:01:24 -0600 Subject: [PATCH 12/89] get the correct report icons when user is admin --- src/libs/OptionsListUtils.js | 18 +++++++++--------- src/libs/actions/PersonalDetails.js | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 16f72c6acb29..b58290e6e85e 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -787,13 +787,6 @@ function getReportIcons(report, personalDetails) { return ['']; } - const sortedParticipants = _.map(report.participants, dmParticipant => ({ - firstName: lodashGet(personalDetails, [dmParticipant, 'firstName'], ''), - avatar: lodashGet(personalDetails, [dmParticipant, 'avatarThumbnail'], '') - || getDefaultAvatar(dmParticipant), - })) - .sort((first, second) => first.firstName - second.firstName); - if (ReportUtils.isPolicyExpenseChat(report)) { const policyExpenseChatAvatarURL = lodashGet(policies, [ `${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`, 'avatarURL', @@ -804,10 +797,17 @@ function getReportIcons(report, personalDetails) { return [policyExpenseChatAvatarURL]; } - // If the user is an admin, return avatar url of the other participant of the report (this is their workspace chat) and the avatar url of the workspace - return [_.first(sortedParticipants).avatar, policyExpenseChatAvatarURL]; + // If the user is an admin, return avatar url of the other participant of the report + // (their workspace chat) and the avatar url of the workspace + return [lodashGet(personalDetails, [report.ownerEmail, 'avatarThumbnail']), policyExpenseChatAvatarURL]; } + const sortedParticipants = _.map(report.participants, dmParticipant => ({ + firstName: lodashGet(personalDetails, [dmParticipant, 'firstName'], ''), + avatar: lodashGet(personalDetails, [dmParticipant, 'avatarThumbnail'], '') + || getDefaultAvatar(dmParticipant), + })) + .sort((first, second) => first.firstName - second.firstName); return _.map(sortedParticipants, item => item.avatar); } diff --git a/src/libs/actions/PersonalDetails.js b/src/libs/actions/PersonalDetails.js index 8c9b89853a31..3edb48d15adb 100644 --- a/src/libs/actions/PersonalDetails.js +++ b/src/libs/actions/PersonalDetails.js @@ -185,7 +185,7 @@ function getFromReportParticipants(reports) { // skip over default rooms which aren't named by participants. const reportsToUpdate = {}; _.each(reports, (report) => { - if (report.participants.length <= 0 && !ReportUtils.isChatRoom(report)) { + if (report.participants.length <= 0 && !ReportUtils.isChatRoom(report) && !ReportUtils.isPolicyExpenseChat(report)) { return; } From 38174988b27216ab6ea8a9f45575c35ed5541fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Tue, 22 Feb 2022 18:47:32 -0600 Subject: [PATCH 13/89] create styles for SubscriptAvatar --- src/styles/styles.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/styles/styles.js b/src/styles/styles.js index efa5ab09f0f6..772c2eda65bb 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -1486,6 +1486,13 @@ const styles = { borderRadius: 24, }, + singleSubscript: { + height: 20, + width: 20, + backgroundColor: themeColors.icon, + borderRadius: 20, + }, + singleAvatarSmall: { height: 18, width: 18, @@ -1524,6 +1531,15 @@ const styles = { borderColor: 'transparent', }, + secondAvatarSubscript: { + position: 'absolute', + right: -3, + bottom: -3, + borderWidth: 3, + borderRadius: 18, + borderColor: 'transparent', + }, + secondAvatarInline: { bottom: -3, right: -25, From 39cc2868f171528644c616fe65233b06b97b851b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Tue, 22 Feb 2022 18:48:13 -0600 Subject: [PATCH 14/89] create SubscriptAvatar component --- src/components/SubscriptAvatar.js | 40 +++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/components/SubscriptAvatar.js diff --git a/src/components/SubscriptAvatar.js b/src/components/SubscriptAvatar.js new file mode 100644 index 000000000000..993290e91eaf --- /dev/null +++ b/src/components/SubscriptAvatar.js @@ -0,0 +1,40 @@ +import React, {memo} from 'react'; +import PropTypes from 'prop-types'; +import {Image, View} from 'react-native'; +import styles from '../styles/styles'; +import Tooltip from './Tooltip'; + +const propTypes = { + /** Array of avatar URL */ + avatarImageURLs: PropTypes.arrayOf(PropTypes.string).isRequired, + + /** Tooltip for the Avatar */ + avatarTooltips: PropTypes.arrayOf(PropTypes.string).isRequired, +}; + +const SubscriptAvatar = props => ( + + + + + + + + + + +); + +SubscriptAvatar.propTypes = propTypes; +export default memo(SubscriptAvatar); From 3763739892b2ced6e1f75a88b5c57a875adb0b34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Tue, 22 Feb 2022 18:48:46 -0600 Subject: [PATCH 15/89] add showSubscript MultipleAvatars to render SubscriptAvatar --- src/components/MultipleAvatars.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/components/MultipleAvatars.js b/src/components/MultipleAvatars.js index 1d65a5469481..6b8fdf817787 100644 --- a/src/components/MultipleAvatars.js +++ b/src/components/MultipleAvatars.js @@ -5,6 +5,7 @@ import styles from '../styles/styles'; import Avatar from './Avatar'; import Tooltip from './Tooltip'; import Text from './Text'; +import SubscriptAvatar from './SubscriptAvatar'; const propTypes = { /** Array of avatar URL */ @@ -25,6 +26,9 @@ const propTypes = { /** Tooltip for the Avatar */ avatarTooltips: PropTypes.arrayOf(PropTypes.string), + + /** Flag to show SubscriptAvatar component */ + showSubscript: PropTypes.bool, }; const defaultProps = { @@ -34,6 +38,7 @@ const defaultProps = { isChatRoom: false, isArchivedRoom: false, avatarTooltips: [], + showSubscript: false, }; const MultipleAvatars = (props) => { @@ -63,6 +68,15 @@ const MultipleAvatars = (props) => { ); } + if (props.showSubscript) { + return ( + + ); + } + return ( Date: Tue, 22 Feb 2022 18:49:55 -0600 Subject: [PATCH 16/89] add showSubscript to option --- src/libs/OptionsListUtils.js | 1 + src/pages/home/sidebar/OptionRow.js | 1 + 2 files changed, 2 insertions(+) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index b58290e6e85e..c2b823c5655f 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -284,6 +284,7 @@ function createOption(personalDetailList, report, { iouReportAmount: lodashGet(iouReport, 'total', 0), isChatRoom, isPolicyExpenseChat, + showSubscript: isPolicyExpenseChat && !report.isOwnPolicyExpenseChat, isArchivedRoom: ReportUtils.isArchivedRoom(report), }; } diff --git a/src/pages/home/sidebar/OptionRow.js b/src/pages/home/sidebar/OptionRow.js index c78ac290223f..28bab0bd3ede 100644 --- a/src/pages/home/sidebar/OptionRow.js +++ b/src/pages/home/sidebar/OptionRow.js @@ -178,6 +178,7 @@ const OptionRow = (props) => { isChatRoom={props.option.isChatRoom} isArchivedRoom={props.option.isArchivedRoom} avatarTooltips={avatarTooltips} + showSubscript={props.option.showSubscript} /> ) } From 6543229213f244cd62ee13d69f218233f75b8990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Wed, 23 Feb 2022 13:16:23 -0600 Subject: [PATCH 17/89] update subscript avatar styles --- src/styles/styles.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/styles/styles.js b/src/styles/styles.js index 772c2eda65bb..73e8ead71aab 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -1533,9 +1533,9 @@ const styles = { secondAvatarSubscript: { position: 'absolute', - right: -3, - bottom: -3, - borderWidth: 3, + right: -4, + bottom: -2, + borderWidth: 2, borderRadius: 18, borderColor: 'transparent', }, From 0690dee1b5fb03bc3acee3d00e4273f68c8fc7ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Wed, 23 Feb 2022 14:39:43 -0600 Subject: [PATCH 18/89] show SubscriptAvatar in HeaderView --- src/pages/home/HeaderView.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js index 7e4e0d84aef5..73d4cf3cde10 100644 --- a/src/pages/home/HeaderView.js +++ b/src/pages/home/HeaderView.js @@ -86,6 +86,7 @@ const HeaderView = (props) => { }, ); const isChatRoom = ReportUtils.isChatRoom(props.report); + const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(props.report); const title = isChatRoom ? props.report.reportName : _.map(displayNamesWithTooltips, ({displayName}) => displayName).join(', '); @@ -140,6 +141,7 @@ const HeaderView = (props) => { isChatRoom={isChatRoom} isArchivedRoom={ReportUtils.isArchivedRoom(props.report)} avatarTooltips={avatarTooltip} + showSubscript={isPolicyExpenseChat && !props.report.isOwnPolicyExpenseChat} /> Date: Wed, 23 Feb 2022 14:54:55 -0600 Subject: [PATCH 19/89] fix blank name in HeaderView for workspace chat --- src/pages/home/HeaderView.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js index 73d4cf3cde10..6ab32d087350 100644 --- a/src/pages/home/HeaderView.js +++ b/src/pages/home/HeaderView.js @@ -87,7 +87,7 @@ const HeaderView = (props) => { ); const isChatRoom = ReportUtils.isChatRoom(props.report); const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(props.report); - const title = isChatRoom + const title = (isChatRoom || isPolicyExpenseChat) ? props.report.reportName : _.map(displayNamesWithTooltips, ({displayName}) => displayName).join(', '); @@ -150,7 +150,7 @@ const HeaderView = (props) => { tooltipEnabled numberOfLines={1} textStyles={[styles.headerText, styles.textNoWrap]} - shouldUseFullTitle={isChatRoom} + shouldUseFullTitle={isChatRoom || isPolicyExpenseChat} /> {isChatRoom && ( Date: Wed, 23 Feb 2022 15:09:36 -0600 Subject: [PATCH 20/89] save ReportUtils function results in variables --- src/libs/OptionsListUtils.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index c2b823c5655f..ed4b60cee7ac 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -398,9 +398,12 @@ function getOptions(reports, personalDetails, activeReportID, { const allReportOptions = []; _.each(orderedReports, (report) => { const logins = lodashGet(report, ['participants'], []); + const isChatRoom = ReportUtils.isChatRoom(report); + const isDefaultRoom = ReportUtils.isDefaultRoom(report); + const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report); // Report data can sometimes be incomplete. If we have no logins or reportID then we will skip this entry. - const shouldFilterNoParticipants = _.isEmpty(logins) && !ReportUtils.isChatRoom(report) && !ReportUtils.isDefaultRoom(report) && !ReportUtils.isPolicyExpenseChat(report); + const shouldFilterNoParticipants = _.isEmpty(logins) && !isChatRoom && !isDefaultRoom && !isPolicyExpenseChat; if (!report || !report.reportID || shouldFilterNoParticipants) { return; } @@ -411,7 +414,7 @@ function getOptions(reports, personalDetails, activeReportID, { : ''; const reportContainsIOUDebt = iouReportOwner && iouReportOwner !== currentUserLogin; - const shouldFilterReportIfEmpty = !showReportsWithNoComments && report.lastMessageTimestamp === 0 && !ReportUtils.isDefaultRoom(report); + const shouldFilterReportIfEmpty = !showReportsWithNoComments && report.lastMessageTimestamp === 0 && !isDefaultRoom; const shouldFilterReportIfRead = hideReadReports && report.unreadActionCount === 0; const shouldFilterReport = shouldFilterReportIfEmpty || shouldFilterReportIfRead; if (report.reportID !== activeReportID @@ -422,7 +425,7 @@ function getOptions(reports, personalDetails, activeReportID, { return; } - if (ReportUtils.isChatRoom(report) && (!Permissions.canUseDefaultRooms(betas) || excludeDefaultRooms)) { + if (isChatRoom && (!Permissions.canUseDefaultRooms(betas) || excludeDefaultRooms)) { return; } @@ -440,7 +443,7 @@ function getOptions(reports, personalDetails, activeReportID, { const isSearchingSomeonesPolicyExpenseChat = !report.isOwnPolicyExpenseChat && searchValue !== ''; allReportOptions.push(createOption(reportPersonalDetails, report, { showChatPreviewLine, - forcePolicyNamePreview: ReportUtils.isPolicyExpenseChat(report) ? isSearchingSomeonesPolicyExpenseChat : forcePolicyNamePreview, + forcePolicyNamePreview: isPolicyExpenseChat ? isSearchingSomeonesPolicyExpenseChat : forcePolicyNamePreview, })); }); From 463e9289a499ad409c56d06887dd82e452139ed9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Wed, 23 Feb 2022 15:11:04 -0600 Subject: [PATCH 21/89] fix duplicate workspace chates for workspace members --- src/libs/OptionsListUtils.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index ed4b60cee7ac..ba144c429b54 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -435,9 +435,9 @@ function getOptions(reports, personalDetails, activeReportID, { const reportPersonalDetails = getPersonalDetailsForLogins(logins, personalDetails); - // Save the report in the map if this is a single participant so we can associate the reportID with the - // personal detail option later. - if (logins.length <= 1) { + // Save the report in the map if this is a single participant (with the exception of PolicyExpenseChat) so we + // can associate the reportID with the personal detail option later. + if (logins.length <= 1 && !isPolicyExpenseChat) { reportMapForLogins[logins[0]] = report; } const isSearchingSomeonesPolicyExpenseChat = !report.isOwnPolicyExpenseChat && searchValue !== ''; From 59816800290d392ea76f444d7ecb9a5330740874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Wed, 23 Feb 2022 15:12:43 -0600 Subject: [PATCH 22/89] fix a few jsdoc errors --- src/libs/OptionsListUtils.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index ba144c429b54..8efd228d9f32 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -210,8 +210,8 @@ function hasReportDraftComment(report) { * @param {Array} personalDetailList * @param {Object} report * @param {Object} options - * @param {Boolean} options.showChatPreviewLine - * @param {Boolean} options.forcePolicyNamePreview + * @param {Boolean} [options.showChatPreviewLine] + * @param {Boolean} [options.forcePolicyNamePreview] * @returns {Object} */ function createOption(personalDetailList, report, { @@ -315,7 +315,7 @@ function isSearchStringMatch(searchValue, searchText, participantNames = new Set /** * Returns the given userDetails is currentUser or not. * @param {Object} userDetails - * @returns {Bool} + * @returns {Boolean} */ function isCurrentUser(userDetails) { From 0a0509aaf0d99cc44188ea8134e7bc4b1813207a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Wed, 23 Feb 2022 15:33:04 -0600 Subject: [PATCH 23/89] fix array of strings jsdoc --- src/libs/OptionsListUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 8efd228d9f32..0d59b3f976e8 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -783,7 +783,7 @@ function getCurrencyListForSections(currencyOptions, searchValue) { * * @param {Object} report * @param {Object} personalDetails - * @returns {String[]} + * @returns {Array} */ function getReportIcons(report, personalDetails) { // Default rooms have a specific avatar so we can return any non-empty array From 533f8513359f7752b2b20426f2c0fc65494269d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Wed, 23 Feb 2022 17:24:38 -0600 Subject: [PATCH 24/89] fix duplicate admin rooms in Search Page --- src/libs/OptionsListUtils.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 0d59b3f976e8..398bb11e0588 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -435,9 +435,9 @@ function getOptions(reports, personalDetails, activeReportID, { const reportPersonalDetails = getPersonalDetailsForLogins(logins, personalDetails); - // Save the report in the map if this is a single participant (with the exception of PolicyExpenseChat) so we - // can associate the reportID with the personal detail option later. - if (logins.length <= 1 && !isPolicyExpenseChat) { + // Save the report in the map if this is a single participant (with the exception of PolicyExpenseChat and + // default rooms) so we can associate the reportID with the personal detail option later. + if (logins.length <= 1 && !isPolicyExpenseChat && !isDefaultRoom) { reportMapForLogins[logins[0]] = report; } const isSearchingSomeonesPolicyExpenseChat = !report.isOwnPolicyExpenseChat && searchValue !== ''; From 25fd44ddccd9b9a4035281d9f2814d5fd8af0f87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Wed, 23 Feb 2022 17:36:28 -0600 Subject: [PATCH 25/89] display policy name as alternateText for admins --- src/libs/reportUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/reportUtils.js b/src/libs/reportUtils.js index 509275bb420b..6c18c43c14df 100644 --- a/src/libs/reportUtils.js +++ b/src/libs/reportUtils.js @@ -161,7 +161,7 @@ function isArchivedRoom(report) { * @returns {String} */ function getChatRoomSubtitle(report, policiesMap) { - if (!isDefaultRoom(report) && !isUserCreatedPolicyRoom(report)) { + if (!isDefaultRoom(report) && !isUserCreatedPolicyRoom(report) && !isPolicyExpenseChat(report)) { return ''; } if (report.chatType === CONST.REPORT.CHAT_TYPE.DOMAIN_ALL) { From 3218eb34beb3fadc45546da16ac849bfc77e4f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Wed, 23 Feb 2022 18:18:21 -0600 Subject: [PATCH 26/89] fix displayed name in alternateText for workspace chats --- src/libs/OptionsListUtils.js | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 398bb11e0588..132ed494eb24 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -204,6 +204,25 @@ function hasReportDraftComment(report) { && lodashGet(reportsWithDraft, `${ONYXKEYS.COLLECTION.REPORTS_WITH_DRAFT}${report.reportID}`, false); } +/** + * @param {Object} report + * @returns {Array} + */ +function getParticipants(report) { + const participants = [...lodashGet(report, ['participants'], [])]; + if (ReportUtils.isPolicyExpenseChat(report)) { + if (!participants.includes(report.ownerEmail)) { + participants.push(report.ownerEmail); + } + + // Include admin as participant + if (!report.isOwnPolicyExpenseChat) { + participants.push(currentUserLogin); + } + } + return participants; +} + /** * Creates a report list option * @@ -236,7 +255,7 @@ function createOption(personalDetailList, report, { : ''; lastMessageText += report ? lastMessageTextFromReport : ''; - const tooltipText = ReportUtils.getReportParticipantsTitle(lodashGet(report, ['participants'], [])); + const tooltipText = ReportUtils.getReportParticipantsTitle(getParticipants(report)); let text; let alternateText; @@ -397,10 +416,10 @@ function getOptions(reports, personalDetails, activeReportID, { const allReportOptions = []; _.each(orderedReports, (report) => { - const logins = lodashGet(report, ['participants'], []); const isChatRoom = ReportUtils.isChatRoom(report); const isDefaultRoom = ReportUtils.isDefaultRoom(report); const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report); + const logins = getParticipants(report); // Report data can sometimes be incomplete. If we have no logins or reportID then we will skip this entry. const shouldFilterNoParticipants = _.isEmpty(logins) && !isChatRoom && !isDefaultRoom && !isPolicyExpenseChat; From 6ad97fb3d52ef67c3d11b4506f9d802d83e2161e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Wed, 23 Feb 2022 18:25:24 -0600 Subject: [PATCH 27/89] filter out workspace chat if user doesn't have permission --- src/libs/OptionsListUtils.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 132ed494eb24..3f88380dcc36 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -448,6 +448,10 @@ function getOptions(reports, personalDetails, activeReportID, { return; } + if (isPolicyExpenseChat && !Permissions.canUsePolicyExpenseChat(betas)) { + return; + } + if (ReportUtils.isUserCreatedPolicyRoom(report) && !Permissions.canUsePolicyRooms(betas)) { return; } From 95aa9cc4a4c1a24e1d52b96a179e46a9d7b73bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Thu, 24 Feb 2022 15:24:22 -0600 Subject: [PATCH 28/89] add showSubscript to RoomHeaderAvatars --- src/components/RoomHeaderAvatars.js | 5 +++++ src/pages/home/report/ReportActionItemCreated.js | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/components/RoomHeaderAvatars.js b/src/components/RoomHeaderAvatars.js index eb50814854b4..d2dfd00a79c0 100644 --- a/src/components/RoomHeaderAvatars.js +++ b/src/components/RoomHeaderAvatars.js @@ -13,11 +13,15 @@ const propTypes = { /** Whether this avatar is for a custom/default room */ isChatRoom: PropTypes.bool, + + /** Flag to show SubscriptAvatar component */ + showSubscript: PropTypes.bool, }; const defaultProps = { avatarImageURLs: [], isChatRoom: false, + showSubscript: false, }; const RoomHeaderAvatars = (props) => { @@ -31,6 +35,7 @@ const RoomHeaderAvatars = (props) => { source={props.avatarImageURLs[0]} imageStyles={[styles.avatarLarge]} isChatRoom={props.isChatRoom} + showSubscript={props.showSubscript} /> ); } diff --git a/src/pages/home/report/ReportActionItemCreated.js b/src/pages/home/report/ReportActionItemCreated.js index 68ef9035ca08..6a54fc3b3f7c 100644 --- a/src/pages/home/report/ReportActionItemCreated.js +++ b/src/pages/home/report/ReportActionItemCreated.js @@ -13,6 +13,9 @@ const propTypes = { report: PropTypes.shape({ /** Avatars corresponding to a chat */ icons: PropTypes.arrayOf(PropTypes.string), + + /** Whether the user is not an admin of policyExpenseChat chat */ + isOwnPolicyExpenseChat: PropTypes.bool, }), }; const defaultProps = { @@ -21,7 +24,7 @@ const defaultProps = { const ReportActionItemCreated = (props) => { const isChatRoom = ReportUtils.isChatRoom(props.report); - + const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(props.report); return ( { avatarImageURLs={props.report.icons} secondAvatarStyle={[styles.secondAvatarHovered]} isChatRoom={isChatRoom} + showSubscript={isPolicyExpenseChat && !props.report.isOwnPolicyExpenseChat} /> From 9fe06b7a4a0e2e19054328b04e886c74076f457d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Thu, 24 Feb 2022 15:34:11 -0600 Subject: [PATCH 29/89] show workspace icon for subscript avatar --- src/components/SubscriptAvatar.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/components/SubscriptAvatar.js b/src/components/SubscriptAvatar.js index 993290e91eaf..fa81acfe594f 100644 --- a/src/components/SubscriptAvatar.js +++ b/src/components/SubscriptAvatar.js @@ -3,6 +3,9 @@ import PropTypes from 'prop-types'; import {Image, View} from 'react-native'; import styles from '../styles/styles'; import Tooltip from './Tooltip'; +import Icon from './Icon'; +import * as Expensicons from './Icon/Expensicons'; +import themedefault from '../styles/themes/default'; const propTypes = { /** Array of avatar URL */ @@ -27,10 +30,19 @@ const SubscriptAvatar = props => ( ]} > - + { props.avatarImageURLs[1] === '' + ? ( + + ) : ( + + )} From f8f69753599cd6a8fce16f72811abb82a4dca0ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Thu, 24 Feb 2022 16:00:26 -0600 Subject: [PATCH 30/89] add defaultSubscriptIcon to SubscriptAvatar --- src/components/SubscriptAvatar.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/SubscriptAvatar.js b/src/components/SubscriptAvatar.js index fa81acfe594f..318797f66926 100644 --- a/src/components/SubscriptAvatar.js +++ b/src/components/SubscriptAvatar.js @@ -4,7 +4,6 @@ import {Image, View} from 'react-native'; import styles from '../styles/styles'; import Tooltip from './Tooltip'; import Icon from './Icon'; -import * as Expensicons from './Icon/Expensicons'; import themedefault from '../styles/themes/default'; const propTypes = { @@ -13,6 +12,9 @@ const propTypes = { /** Tooltip for the Avatar */ avatarTooltips: PropTypes.arrayOf(PropTypes.string).isRequired, + + /** Default icon if the subscript image is not set */ + defaultSubscriptIcon: PropTypes.func.isRequired, }; const SubscriptAvatar = props => ( @@ -33,7 +35,7 @@ const SubscriptAvatar = props => ( { props.avatarImageURLs[1] === '' ? ( From bedfc70224de21bdf449a753a279844901355a05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Thu, 24 Feb 2022 16:00:44 -0600 Subject: [PATCH 31/89] set Expensicons.Workspace in defaultSubscriptIcon --- src/components/MultipleAvatars.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/MultipleAvatars.js b/src/components/MultipleAvatars.js index 6b8fdf817787..722239080840 100644 --- a/src/components/MultipleAvatars.js +++ b/src/components/MultipleAvatars.js @@ -6,6 +6,7 @@ import Avatar from './Avatar'; import Tooltip from './Tooltip'; import Text from './Text'; import SubscriptAvatar from './SubscriptAvatar'; +import * as Expensicons from './Icon/Expensicons'; const propTypes = { /** Array of avatar URL */ @@ -73,6 +74,7 @@ const MultipleAvatars = (props) => { Expensicons.Workspace} /> ); } From 7652cf3d761f34f45a4760577cc9e4c38fa2cdff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Thu, 24 Feb 2022 16:20:48 -0600 Subject: [PATCH 32/89] show SubscriptAvatar component in RoomHeaderAvatars --- src/components/RoomHeaderAvatars.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/components/RoomHeaderAvatars.js b/src/components/RoomHeaderAvatars.js index d2dfd00a79c0..7a1ae90ef3e2 100644 --- a/src/components/RoomHeaderAvatars.js +++ b/src/components/RoomHeaderAvatars.js @@ -6,6 +6,8 @@ import styles from '../styles/styles'; import Text from './Text'; import CONST from '../CONST'; import Avatar from './Avatar'; +import SubscriptAvatar from './SubscriptAvatar'; +import * as Expensicons from './Icon/Expensicons'; const propTypes = { /** Array of avatar URL */ @@ -29,13 +31,22 @@ const RoomHeaderAvatars = (props) => { return null; } + if (props.showSubscript) { + return ( + Expensicons.Workspace} + /> + ); + } + if (props.avatarImageURLs.length === 1 || props.isChatRoom) { return ( ); } From adc6ccc30b917b26f29c9cbd95682c3a2117ad7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Thu, 24 Feb 2022 17:09:46 -0600 Subject: [PATCH 33/89] create emptyAvatarLarge and add var avatarSizeLarge --- src/styles/styles.js | 10 ++++++++-- src/styles/variables.js | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/styles/styles.js b/src/styles/styles.js index 73e8ead71aab..f3539eb5189c 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -1597,6 +1597,12 @@ const styles = { width: variables.avatarSizeNormal, }, + emptyAvatarLarge: { + marginRight: variables.componentSizeNormal - 24, + height: variables.avatarSizeLarge, + width: variables.avatarSizeLarge, + }, + emptyAvatarSmall: { marginRight: variables.componentSizeNormal - 28, height: variables.avatarSizeSmall, @@ -1815,8 +1821,8 @@ const styles = { }, avatarLarge: { - width: 80, - height: 80, + width: variables.avatarSizeLarge, + height: variables.avatarSizeLarge, }, roomHeaderAvatar: { diff --git a/src/styles/variables.js b/src/styles/variables.js index b99177951635..a541d499676e 100644 --- a/src/styles/variables.js +++ b/src/styles/variables.js @@ -8,6 +8,7 @@ export default { componentBorderRadiusSmall: 4, componentBorderRadiusNormal: 8, componentBorderRadiusCard: 12, + avatarSizeLarge: 80, avatarSizeNormal: 40, avatarSizeSmall: 28, fontSizeSingleEmoji: 30, From 1e548192bb48b0a7bce142b8334a90ef49a98b24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Thu, 24 Feb 2022 17:12:34 -0600 Subject: [PATCH 34/89] add size to SubscriptAvatar and use Avatar instead of Image --- src/components/RoomHeaderAvatars.js | 1 + src/components/SubscriptAvatar.js | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/components/RoomHeaderAvatars.js b/src/components/RoomHeaderAvatars.js index 7a1ae90ef3e2..42fe6abfb0c4 100644 --- a/src/components/RoomHeaderAvatars.js +++ b/src/components/RoomHeaderAvatars.js @@ -37,6 +37,7 @@ const RoomHeaderAvatars = (props) => { avatarImageURLs={props.avatarImageURLs} avatarTooltips={[]} defaultSubscriptIcon={() => Expensicons.Workspace} + size={props.showSubscript ? 'large' : 'default'} /> ); } diff --git a/src/components/SubscriptAvatar.js b/src/components/SubscriptAvatar.js index 318797f66926..1845c828fddd 100644 --- a/src/components/SubscriptAvatar.js +++ b/src/components/SubscriptAvatar.js @@ -1,10 +1,11 @@ import React, {memo} from 'react'; import PropTypes from 'prop-types'; -import {Image, View} from 'react-native'; +import {View} from 'react-native'; import styles from '../styles/styles'; import Tooltip from './Tooltip'; import Icon from './Icon'; import themedefault from '../styles/themes/default'; +import Avatar from './Avatar'; const propTypes = { /** Array of avatar URL */ @@ -15,14 +16,21 @@ const propTypes = { /** Default icon if the subscript image is not set */ defaultSubscriptIcon: PropTypes.func.isRequired, + + /** Set the sie of avatars */ + size: PropTypes.oneOf(['default', 'large']), +}; + +const defaultProps = { + size: 'default', }; const SubscriptAvatar = props => ( - + - ( ); +SubscriptAvatar.defaultProps = defaultProps; SubscriptAvatar.propTypes = propTypes; export default memo(SubscriptAvatar); From ec1dcec40c2fef2d2e496b5e7de78c69c638ac7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Thu, 24 Feb 2022 18:42:41 -0600 Subject: [PATCH 35/89] add secondAvatarLarge and firstAvatar styles --- src/styles/styles.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/styles/styles.js b/src/styles/styles.js index f3539eb5189c..02d3046ed777 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -1487,10 +1487,11 @@ const styles = { }, singleSubscript: { - height: 20, - width: 20, + height: variables.iconSizeNormal, + width: variables.iconSizeNormal, backgroundColor: themeColors.icon, borderRadius: 20, + zIndex: 1, }, singleAvatarSmall: { @@ -1540,6 +1541,14 @@ const styles = { borderColor: 'transparent', }, + secondAvatarLarge: { + position: 'absolute', + left: -40, + borderWidth: 2, + borderRadius: 18, + borderColor: 'transparent', + }, + secondAvatarInline: { bottom: -3, right: -25, @@ -1820,6 +1829,13 @@ const styles = { width: '100%', }, + firstAvatar: { + zIndex: 2, + borderRadius: 100, + borderColor: themeColors.componentBG, + borderWidth: 4, + }, + avatarLarge: { width: variables.avatarSizeLarge, height: variables.avatarSizeLarge, From b223cf27d1e0f014aa66a843b32da2af064bade1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Thu, 24 Feb 2022 18:44:58 -0600 Subject: [PATCH 36/89] apply different styles if size is large --- src/components/SubscriptAvatar.js | 30 +++++++++++++++++------------- src/styles/styles.js | 2 +- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/components/SubscriptAvatar.js b/src/components/SubscriptAvatar.js index 1845c828fddd..54306a0675ed 100644 --- a/src/components/SubscriptAvatar.js +++ b/src/components/SubscriptAvatar.js @@ -6,6 +6,7 @@ import Tooltip from './Tooltip'; import Icon from './Icon'; import themedefault from '../styles/themes/default'; import Avatar from './Avatar'; +import variables from '../styles/variables'; const propTypes = { /** Array of avatar URL */ @@ -27,30 +28,33 @@ const defaultProps = { const SubscriptAvatar = props => ( - - - + + + + + { props.avatarImageURLs[1] === '' ? ( ) : ( - )} diff --git a/src/styles/styles.js b/src/styles/styles.js index 02d3046ed777..23e72df5401f 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -1829,7 +1829,7 @@ const styles = { width: '100%', }, - firstAvatar: { + rightSideLargeAvatar: { zIndex: 2, borderRadius: 100, borderColor: themeColors.componentBG, From 4aff4d6fa1f3871e947843f0f878101edfebe782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Thu, 24 Feb 2022 18:45:18 -0600 Subject: [PATCH 37/89] set large size in RoomHeaderAvatars --- src/components/RoomHeaderAvatars.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/RoomHeaderAvatars.js b/src/components/RoomHeaderAvatars.js index 42fe6abfb0c4..ef764ffc3810 100644 --- a/src/components/RoomHeaderAvatars.js +++ b/src/components/RoomHeaderAvatars.js @@ -37,7 +37,7 @@ const RoomHeaderAvatars = (props) => { avatarImageURLs={props.avatarImageURLs} avatarTooltips={[]} defaultSubscriptIcon={() => Expensicons.Workspace} - size={props.showSubscript ? 'large' : 'default'} + size="large" /> ); } From 79a40ba31654fb2a9686226c1fe63080196cbf27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Fri, 25 Feb 2022 13:29:55 -0600 Subject: [PATCH 38/89] move chat room icons to Expensicons --- src/components/Icon/Expensicons.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/Icon/Expensicons.js b/src/components/Icon/Expensicons.js index 340e8e5ad25e..40e0342153b6 100644 --- a/src/components/Icon/Expensicons.js +++ b/src/components/Icon/Expensicons.js @@ -70,8 +70,11 @@ import Users from '../../../assets/images/users.svg'; import Venmo from '../../../assets/images/venmo.svg'; import Wallet from '../../../assets/images/wallet.svg'; import Workspace from '../../../assets/images/workspace-default-avatar.svg'; +import ActiveRoomAvatar from '../../../assets/images/avatars/room.svg'; +import DeletedRoomAvatar from '../../../assets/images/avatars/deleted-room.svg'; export { + ActiveRoomAvatar, Android, Apple, ArrowRight, @@ -92,6 +95,7 @@ export { ClosedSign, Concierge, CreditCard, + DeletedRoomAvatar, DownArrow, Download, Emoji, From 2f73f0d8aa7fc26e3b2d91d5e1b122a6150592a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Fri, 25 Feb 2022 13:30:38 -0600 Subject: [PATCH 39/89] use Icon instead of RoomAvatar in Avatar --- src/components/Avatar.js | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/components/Avatar.js b/src/components/Avatar.js index 0e6aa6a381e6..e9085f6d83d6 100644 --- a/src/components/Avatar.js +++ b/src/components/Avatar.js @@ -1,10 +1,13 @@ import React, {PureComponent} from 'react'; import {Image, View} from 'react-native'; import PropTypes from 'prop-types'; +import _ from 'underscore'; import styles from '../styles/styles'; -import themeColors from '../styles/themes/default'; -import RoomAvatar from './RoomAvatar'; import stylePropTypes from '../styles/stylePropTypes'; +import Icon from './Icon'; +import variables from '../styles/variables'; +import * as Expensicons from './Icon/Expensicons'; +import themeColors from '../styles/themes/default'; const propTypes = { /** Url source for the avatar */ @@ -37,7 +40,15 @@ const defaultProps = { class Avatar extends PureComponent { render() { - if (!this.props.source && !this.props.isChatRoom) { + let source = this.props.source; + if (this.props.isChatRoom) { + source = Expensicons.ActiveRoomAvatar; + } + if (this.props.isArchivedRoom) { + source = Expensicons.DeletedRoomAvatar; + } + + if (!source) { return null; } @@ -49,11 +60,15 @@ class Avatar extends PureComponent { ...this.props.imageStyles, ]; + const iconSize = this.props.size === 'small' ? variables.avatarSizeSmall : variables.avatarSizeNormal; + return ( - {this.props.isChatRoom - ? - : } + { + _.isFunction(source) + ? + : + } ); } From 5b8b05055f9772672d6c775565ed6ee1e5517bee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Fri, 25 Feb 2022 13:31:41 -0600 Subject: [PATCH 40/89] delete RoomAvatar (logic moved to Avatar) --- src/components/RoomAvatar.js | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 src/components/RoomAvatar.js diff --git a/src/components/RoomAvatar.js b/src/components/RoomAvatar.js deleted file mode 100644 index f9675418e542..000000000000 --- a/src/components/RoomAvatar.js +++ /dev/null @@ -1,31 +0,0 @@ -import React, {PureComponent} from 'react'; -import {StyleSheet} from 'react-native'; -import PropTypes from 'prop-types'; -import ActiveRoomAvatar from '../../assets/images/avatars/room.svg'; -import DeletedRoomAvatar from '../../assets/images/avatars/deleted-room.svg'; - -const propTypes = { - /** Extra styles to pass to Image */ - avatarStyle: PropTypes.arrayOf(PropTypes.object), - - /** Whether the room this avatar is for is deleted or not */ - isArchived: PropTypes.bool, -}; - -const defaultProps = { - avatarStyle: [], - isArchived: false, -}; - -class RoomAvatar extends PureComponent { - render() { - return (this.props.isArchived - ? - : - ); - } -} - -RoomAvatar.defaultProps = defaultProps; -RoomAvatar.propTypes = propTypes; -export default RoomAvatar; From 704be62a5c957ce278fd3559a61f037d653141c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Fri, 25 Feb 2022 13:37:48 -0600 Subject: [PATCH 41/89] display archived room in RoomHeaderAvatar --- src/components/RoomHeaderAvatars.js | 5 +++++ src/pages/home/report/ReportActionItemCreated.js | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/RoomHeaderAvatars.js b/src/components/RoomHeaderAvatars.js index ef764ffc3810..78c524d9255a 100644 --- a/src/components/RoomHeaderAvatars.js +++ b/src/components/RoomHeaderAvatars.js @@ -16,6 +16,9 @@ const propTypes = { /** Whether this avatar is for a custom/default room */ isChatRoom: PropTypes.bool, + /** Whether this avatar is for an archived room */ + isArchivedRoom: PropTypes.bool, + /** Flag to show SubscriptAvatar component */ showSubscript: PropTypes.bool, }; @@ -23,6 +26,7 @@ const propTypes = { const defaultProps = { avatarImageURLs: [], isChatRoom: false, + isArchivedRoom: false, showSubscript: false, }; @@ -48,6 +52,7 @@ const RoomHeaderAvatars = (props) => { source={props.avatarImageURLs[0]} imageStyles={[styles.avatarLarge]} isChatRoom={props.isChatRoom} + isArchivedRoom={props.isArchivedRoom} /> ); } diff --git a/src/pages/home/report/ReportActionItemCreated.js b/src/pages/home/report/ReportActionItemCreated.js index 6a54fc3b3f7c..68ddd16ac318 100644 --- a/src/pages/home/report/ReportActionItemCreated.js +++ b/src/pages/home/report/ReportActionItemCreated.js @@ -35,8 +35,8 @@ const ReportActionItemCreated = (props) => { From 0e981d888a42cf234567f13df6a3d69a99e2a30a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Fri, 25 Feb 2022 14:00:05 -0600 Subject: [PATCH 42/89] fix border for large avatar in RoomHeaderAvatar --- src/components/SubscriptAvatar.js | 2 +- src/styles/styles.js | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/components/SubscriptAvatar.js b/src/components/SubscriptAvatar.js index 54306a0675ed..eaa98ca868d7 100644 --- a/src/components/SubscriptAvatar.js +++ b/src/components/SubscriptAvatar.js @@ -27,7 +27,7 @@ const defaultProps = { }; const SubscriptAvatar = props => ( - + Date: Fri, 25 Feb 2022 14:19:26 -0600 Subject: [PATCH 43/89] create LargeDualAvatars to remove complexity in SubscripAvatar --- src/components/LargeDualAvatars.js | 55 +++++++++++++++++++++++++++++ src/components/RoomHeaderAvatars.js | 5 ++- 2 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 src/components/LargeDualAvatars.js diff --git a/src/components/LargeDualAvatars.js b/src/components/LargeDualAvatars.js new file mode 100644 index 000000000000..df30764ad8bb --- /dev/null +++ b/src/components/LargeDualAvatars.js @@ -0,0 +1,55 @@ +import React, {memo} from 'react'; +import PropTypes from 'prop-types'; +import {View} from 'react-native'; +import styles from '../styles/styles'; +import Tooltip from './Tooltip'; +import Icon from './Icon'; +import themedefault from '../styles/themes/default'; +import Avatar from './Avatar'; +import variables from '../styles/variables'; + +const propTypes = { + /** Array of avatar URL */ + avatarImageURLs: PropTypes.arrayOf(PropTypes.string).isRequired, + + /** Tooltip for the Avatar */ + avatarTooltips: PropTypes.arrayOf(PropTypes.string).isRequired, + + /** Default icon if the subscript image is not set */ + defaultSubscriptIcon: PropTypes.func.isRequired, +}; + +const LargeDualAvatars = props => ( + + + + + + + + + { props.avatarImageURLs[1] === '' + ? ( + + ) : ( + + )} + + + +); + +LargeDualAvatars.propTypes = propTypes; +export default memo(LargeDualAvatars); diff --git a/src/components/RoomHeaderAvatars.js b/src/components/RoomHeaderAvatars.js index 78c524d9255a..6e40f25f6f4f 100644 --- a/src/components/RoomHeaderAvatars.js +++ b/src/components/RoomHeaderAvatars.js @@ -6,8 +6,8 @@ import styles from '../styles/styles'; import Text from './Text'; import CONST from '../CONST'; import Avatar from './Avatar'; -import SubscriptAvatar from './SubscriptAvatar'; import * as Expensicons from './Icon/Expensicons'; +import LargeDualAvatars from './LargeDualAvatars'; const propTypes = { /** Array of avatar URL */ @@ -37,11 +37,10 @@ const RoomHeaderAvatars = (props) => { if (props.showSubscript) { return ( - Expensicons.Workspace} - size="large" /> ); } From 4290b91a1e2832bb9db89921ad1e3266faf9ae1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Fri, 25 Feb 2022 14:25:25 -0600 Subject: [PATCH 44/89] remove LargeDualAvatars from RoomHeaderAvatars and call it directly --- src/components/RoomHeaderAvatars.js | 16 ------------- .../home/report/ReportActionItemCreated.js | 23 ++++++++++++++----- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/src/components/RoomHeaderAvatars.js b/src/components/RoomHeaderAvatars.js index 6e40f25f6f4f..6e074107729f 100644 --- a/src/components/RoomHeaderAvatars.js +++ b/src/components/RoomHeaderAvatars.js @@ -6,8 +6,6 @@ import styles from '../styles/styles'; import Text from './Text'; import CONST from '../CONST'; import Avatar from './Avatar'; -import * as Expensicons from './Icon/Expensicons'; -import LargeDualAvatars from './LargeDualAvatars'; const propTypes = { /** Array of avatar URL */ @@ -18,16 +16,12 @@ const propTypes = { /** Whether this avatar is for an archived room */ isArchivedRoom: PropTypes.bool, - - /** Flag to show SubscriptAvatar component */ - showSubscript: PropTypes.bool, }; const defaultProps = { avatarImageURLs: [], isChatRoom: false, isArchivedRoom: false, - showSubscript: false, }; const RoomHeaderAvatars = (props) => { @@ -35,16 +29,6 @@ const RoomHeaderAvatars = (props) => { return null; } - if (props.showSubscript) { - return ( - Expensicons.Workspace} - /> - ); - } - if (props.avatarImageURLs.length === 1 || props.isChatRoom) { return ( { ]} > - + { + isPolicyExpenseChat && !props.report.isOwnPolicyExpenseChat ? ( + Expensicons.Workspace} + /> + ) : ( + + ) + } From 0a84faec5222aa49b1eaf03cd5db49351186f939 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Fri, 25 Feb 2022 14:31:10 -0600 Subject: [PATCH 45/89] remove size from SubscriptAvatar --- src/components/SubscriptAvatar.js | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/src/components/SubscriptAvatar.js b/src/components/SubscriptAvatar.js index eaa98ca868d7..41bdc979cc1a 100644 --- a/src/components/SubscriptAvatar.js +++ b/src/components/SubscriptAvatar.js @@ -17,44 +17,34 @@ const propTypes = { /** Default icon if the subscript image is not set */ defaultSubscriptIcon: PropTypes.func.isRequired, - - /** Set the sie of avatars */ - size: PropTypes.oneOf(['default', 'large']), -}; - -const defaultProps = { - size: 'default', }; const SubscriptAvatar = props => ( - - + + { props.avatarImageURLs[1] === '' ? ( ) : ( )} @@ -62,6 +52,5 @@ const SubscriptAvatar = props => ( ); -SubscriptAvatar.defaultProps = defaultProps; SubscriptAvatar.propTypes = propTypes; export default memo(SubscriptAvatar); From 7818250303a108bee38509949a0976e637122e65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Fri, 25 Feb 2022 15:16:36 -0600 Subject: [PATCH 46/89] add new avatar sizes --- src/CONST/index.js | 2 ++ src/styles/variables.js | 1 + 2 files changed, 3 insertions(+) diff --git a/src/CONST/index.js b/src/CONST/index.js index 9da5ca6ac638..11f5a029f147 100755 --- a/src/CONST/index.js +++ b/src/CONST/index.js @@ -545,6 +545,8 @@ const CONST = { AVATAR_SIZE: { LARGE: 'large', DEFAULT: 'default', + SMALL: 'small', + SUBSCRIPT: 'subscript', }, PHONE_MAX_LENGTH: 15, diff --git a/src/styles/variables.js b/src/styles/variables.js index a541d499676e..c92ba7a9b557 100644 --- a/src/styles/variables.js +++ b/src/styles/variables.js @@ -11,6 +11,7 @@ export default { avatarSizeLarge: 80, avatarSizeNormal: 40, avatarSizeSmall: 28, + avatarSizeSubscript: 20, fontSizeSingleEmoji: 30, fontSizeSingleEmojiHeight: 35, fontSizeSmall: 11, From 9d39368dc62cc20f4ad83c15817703b0196b301f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Fri, 25 Feb 2022 15:17:54 -0600 Subject: [PATCH 47/89] add size prop to Avatar to re-use it as Icon --- src/components/Avatar.js | 38 ++++++++++++++++++++--------- src/components/RoomHeaderAvatars.js | 1 + src/components/SubscriptAvatar.js | 26 ++++++-------------- 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/components/Avatar.js b/src/components/Avatar.js index e9085f6d83d6..9ea7a19797c6 100644 --- a/src/components/Avatar.js +++ b/src/components/Avatar.js @@ -8,10 +8,12 @@ import Icon from './Icon'; import variables from '../styles/variables'; import * as Expensicons from './Icon/Expensicons'; import themeColors from '../styles/themes/default'; +import CONST from '../CONST'; + const propTypes = { - /** Url source for the avatar */ - source: PropTypes.string, + /** Source for the avatar. Can be the URL of an image or an icon. */ + source: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired, /** Extra styles to pass to Image */ imageStyles: PropTypes.arrayOf(PropTypes.object), @@ -20,22 +22,29 @@ const propTypes = { containerStyles: stylePropTypes, /** Set the size of Avatar */ - size: PropTypes.oneOf(['default', 'small']), + size: PropTypes.oneOf(_.values(CONST.AVATAR_SIZE)), /** Whether this avatar is for a chat room */ isChatRoom: PropTypes.bool, /** Whether this avatar is for an archived default room */ isArchivedRoom: PropTypes.bool, + + /** Whether this avatar is for a policyExpenseChat */ + isPolicyExpenseChat: PropTypes.bool, + + /** The fill color for the icon. Can be hex, rgb, rgba, or valid react-native named color such as 'red' or 'blue' */ + fill: PropTypes.string, }; const defaultProps = { - source: '', imageStyles: [], containerStyles: [], - size: 'default', + size: CONST.AVATAR_SIZE.DEFAULT, isChatRoom: false, isArchivedRoom: false, + isPolicyExpenseChat: false, + fill: themeColors.icon, }; class Avatar extends PureComponent { @@ -47,26 +56,31 @@ class Avatar extends PureComponent { if (this.props.isArchivedRoom) { source = Expensicons.DeletedRoomAvatar; } + if (this.props.isPolicyExpenseChat) { + source = Expensicons.Workspace; + } if (!source) { return null; } const imageStyle = [ - this.props.size === 'small' ? styles.avatarSmall : styles.avatarNormal, - - // Background color isn't added for room avatar because it changes it's shape to a square - this.props.isChatRoom ? {} : {backgroundColor: themeColors.icon}, + this.props.size === CONST.AVATAR_SIZE.SMALL ? styles.avatarSmall : styles.avatarNormal, ...this.props.imageStyles, ]; - const iconSize = this.props.size === 'small' ? variables.avatarSizeSmall : variables.avatarSizeNormal; - + const AVATAR_SIZES = { + [CONST.AVATAR_SIZE.DEFAULT]: variables.avatarSizeNormal, + [CONST.AVATAR_SIZE.SUBSCRIPT]: variables.avatarSizeSubscript, + [CONST.AVATAR_SIZE.SMALL]: variables.avatarSizeSmall, + [CONST.AVATAR_SIZE.LARGE]: variables.avatarSizeLarge, + }; + const iconSize = AVATAR_SIZES[this.props.size]; return ( { _.isFunction(source) - ? + ? : } diff --git a/src/components/RoomHeaderAvatars.js b/src/components/RoomHeaderAvatars.js index 6e074107729f..c3305c6ee85b 100644 --- a/src/components/RoomHeaderAvatars.js +++ b/src/components/RoomHeaderAvatars.js @@ -36,6 +36,7 @@ const RoomHeaderAvatars = (props) => { imageStyles={[styles.avatarLarge]} isChatRoom={props.isChatRoom} isArchivedRoom={props.isArchivedRoom} + size={CONST.AVATAR_SIZE.LARGE} /> ); } diff --git a/src/components/SubscriptAvatar.js b/src/components/SubscriptAvatar.js index 41bdc979cc1a..bd40f80ca044 100644 --- a/src/components/SubscriptAvatar.js +++ b/src/components/SubscriptAvatar.js @@ -3,10 +3,9 @@ import PropTypes from 'prop-types'; import {View} from 'react-native'; import styles from '../styles/styles'; import Tooltip from './Tooltip'; -import Icon from './Icon'; -import themedefault from '../styles/themes/default'; +import themeColors from '../styles/themes/default'; import Avatar from './Avatar'; -import variables from '../styles/variables'; +import CONST from '../CONST'; const propTypes = { /** Array of avatar URL */ @@ -32,21 +31,12 @@ const SubscriptAvatar = props => ( style={[styles.secondAvatarSubscript, styles.secondAvatarHovered]} > - { props.avatarImageURLs[1] === '' - ? ( - - ) : ( - - )} + From 752edb58a2a1bcb00de66184493ab0afeea72bf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Fri, 25 Feb 2022 15:21:11 -0600 Subject: [PATCH 48/89] use size property to remove Icon from LargeDualAvatars --- src/components/LargeDualAvatars.js | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/src/components/LargeDualAvatars.js b/src/components/LargeDualAvatars.js index df30764ad8bb..a2443ab7a352 100644 --- a/src/components/LargeDualAvatars.js +++ b/src/components/LargeDualAvatars.js @@ -3,10 +3,9 @@ import PropTypes from 'prop-types'; import {View} from 'react-native'; import styles from '../styles/styles'; import Tooltip from './Tooltip'; -import Icon from './Icon'; -import themedefault from '../styles/themes/default'; +import themeColors from '../styles/themes/default'; import Avatar from './Avatar'; -import variables from '../styles/variables'; +import CONST from '../CONST'; const propTypes = { /** Array of avatar URL */ @@ -31,21 +30,12 @@ const LargeDualAvatars = props => ( - { props.avatarImageURLs[1] === '' - ? ( - - ) : ( - - )} + From 63d87a5b2fdb9d11c289daba516ea45e4c42c901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Fri, 25 Feb 2022 16:31:33 -0600 Subject: [PATCH 49/89] display workspace icon for empty workspace chats --- src/components/MultipleAvatars.js | 7 +++++++ src/pages/home/HeaderView.js | 1 + src/pages/home/sidebar/OptionRow.js | 1 + src/pages/settings/InitialSettingsPage.js | 2 +- 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/components/MultipleAvatars.js b/src/components/MultipleAvatars.js index 722239080840..e39eb0faa0b0 100644 --- a/src/components/MultipleAvatars.js +++ b/src/components/MultipleAvatars.js @@ -7,6 +7,7 @@ import Tooltip from './Tooltip'; import Text from './Text'; import SubscriptAvatar from './SubscriptAvatar'; import * as Expensicons from './Icon/Expensicons'; +import themeColors from '../styles/themes/default'; const propTypes = { /** Array of avatar URL */ @@ -25,6 +26,9 @@ const propTypes = { /** Whether this avatar is for an archived room */ isArchivedRoom: PropTypes.bool, + /** Whether this avatar is for a policyExpenseChat */ + isPolicyExpenseChat: PropTypes.bool, + /** Tooltip for the Avatar */ avatarTooltips: PropTypes.arrayOf(PropTypes.string), @@ -40,6 +44,7 @@ const defaultProps = { isArchivedRoom: false, avatarTooltips: [], showSubscript: false, + isPolicyExpenseChat: false, }; const MultipleAvatars = (props) => { @@ -63,6 +68,8 @@ const MultipleAvatars = (props) => { size={props.size} isChatRoom={props.isChatRoom} isArchivedRoom={props.isArchivedRoom} + isPolicyExpenseChat={props.isPolicyExpenseChat} + fill={themeColors.iconSuccessFill} /> diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js index 6ab32d087350..f22ed146ce3e 100644 --- a/src/pages/home/HeaderView.js +++ b/src/pages/home/HeaderView.js @@ -140,6 +140,7 @@ const HeaderView = (props) => { secondAvatarStyle={[styles.secondAvatarHovered]} isChatRoom={isChatRoom} isArchivedRoom={ReportUtils.isArchivedRoom(props.report)} + isPolicyExpenseChat={isPolicyExpenseChat} avatarTooltips={avatarTooltip} showSubscript={isPolicyExpenseChat && !props.report.isOwnPolicyExpenseChat} /> diff --git a/src/pages/home/sidebar/OptionRow.js b/src/pages/home/sidebar/OptionRow.js index 28bab0bd3ede..945c6f8d96df 100644 --- a/src/pages/home/sidebar/OptionRow.js +++ b/src/pages/home/sidebar/OptionRow.js @@ -177,6 +177,7 @@ const OptionRow = (props) => { ]} isChatRoom={props.option.isChatRoom} isArchivedRoom={props.option.isArchivedRoom} + isPolicyExpenseChat={props.option.isPolicyExpenseChat} avatarTooltips={avatarTooltips} showSubscript={props.option.showSubscript} /> diff --git a/src/pages/settings/InitialSettingsPage.js b/src/pages/settings/InitialSettingsPage.js index 7818eea0d521..375dc944d5da 100755 --- a/src/pages/settings/InitialSettingsPage.js +++ b/src/pages/settings/InitialSettingsPage.js @@ -161,7 +161,7 @@ const InitialSettingsPage = (props) => { Date: Fri, 25 Feb 2022 17:35:57 -0600 Subject: [PATCH 50/89] display workspace icon in OptionRow and RoomHeaderAvatar --- src/components/Avatar.js | 18 ++++++++++-------- src/components/RoomHeaderAvatars.js | 9 ++++++++- .../home/report/ReportActionItemCreated.js | 1 + 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/components/Avatar.js b/src/components/Avatar.js index 9ea7a19797c6..f0cba8be2c66 100644 --- a/src/components/Avatar.js +++ b/src/components/Avatar.js @@ -50,14 +50,16 @@ const defaultProps = { class Avatar extends PureComponent { render() { let source = this.props.source; - if (this.props.isChatRoom) { - source = Expensicons.ActiveRoomAvatar; - } - if (this.props.isArchivedRoom) { - source = Expensicons.DeletedRoomAvatar; - } - if (this.props.isPolicyExpenseChat) { - source = Expensicons.Workspace; + if (!source) { + if (this.props.isChatRoom) { + source = Expensicons.ActiveRoomAvatar; + } + if (this.props.isArchivedRoom) { + source = Expensicons.DeletedRoomAvatar; + } + if (this.props.isPolicyExpenseChat) { + source = Expensicons.Workspace; + } } if (!source) { diff --git a/src/components/RoomHeaderAvatars.js b/src/components/RoomHeaderAvatars.js index c3305c6ee85b..a2a7c5cfd8cf 100644 --- a/src/components/RoomHeaderAvatars.js +++ b/src/components/RoomHeaderAvatars.js @@ -6,6 +6,7 @@ import styles from '../styles/styles'; import Text from './Text'; import CONST from '../CONST'; import Avatar from './Avatar'; +import themeColors from '../styles/themes/default'; const propTypes = { /** Array of avatar URL */ @@ -16,12 +17,16 @@ const propTypes = { /** Whether this avatar is for an archived room */ isArchivedRoom: PropTypes.bool, + + /** Whether this avatar is for a policyExpenseChat */ + isPolicyExpenseChat: PropTypes.bool, }; const defaultProps = { avatarImageURLs: [], isChatRoom: false, isArchivedRoom: false, + isPolicyExpenseChat: false, }; const RoomHeaderAvatars = (props) => { @@ -29,13 +34,15 @@ const RoomHeaderAvatars = (props) => { return null; } - if (props.avatarImageURLs.length === 1 || props.isChatRoom) { + if (props.avatarImageURLs.length === 1) { return ( ); diff --git a/src/pages/home/report/ReportActionItemCreated.js b/src/pages/home/report/ReportActionItemCreated.js index cad50d1b376f..f917bc7c7f5a 100644 --- a/src/pages/home/report/ReportActionItemCreated.js +++ b/src/pages/home/report/ReportActionItemCreated.js @@ -46,6 +46,7 @@ const ReportActionItemCreated = (props) => { ) From e2bdea4b200b53d565eaf88bc8324fc572a3c3ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Sat, 26 Feb 2022 11:54:57 -0600 Subject: [PATCH 51/89] add functions getAvatarSource --- src/libs/OptionsListUtils.js | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 3f88380dcc36..484b7f106bf0 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -10,6 +10,7 @@ import * as ReportUtils from './reportUtils'; import * as Localize from './Localize'; import Permissions from './Permissions'; import md5 from './md5'; +import * as Expensicons from '../components/Icon/Expensicons'; /** * OptionsListUtils is used to build a list options passed to the OptionsList component. Several different UI views can @@ -838,9 +839,50 @@ function getReportIcons(report, personalDetails) { return _.map(sortedParticipants, item => item.avatar); } +/** + * Get the Avatar url or fallback to the default icon according to the chat type + * + * @param {String} source + * @param {Object} options + * @param {Boolean} [options.isChatRoom] + * @param {Boolean} [options.isArchivedRoom] + * @param {Boolean} [options.isPolicyExpenseChat] + * @returns {String | Function} + */ +function getAvatarSource(source, {isChatRoom, isArchivedRoom, isPolicyExpenseChat}) { + if (!source) { + if (isChatRoom) { + return Expensicons.ActiveRoomAvatar; + } + if (isArchivedRoom) { + return Expensicons.DeletedRoomAvatar; + } + if (isPolicyExpenseChat) { + return Expensicons.Workspace; + } + } + return source; +} + +/** + * Get the Avatar urls or fallback to the default icons according to the chat type + * + * @param {Object} report + * @returns {Array} + */ +function getAvatarSourceFromReport(report) { + return _.map(report.icons, source => getAvatarSource(source, { + isChatRoom: ReportUtils.isChatRoom(report), + isArchivedRoom: ReportUtils.isArchivedRoom(report), + isPolicyExpenseChat: ReportUtils.isPolicyExpenseChat(report), + })); +} + export { addSMSDomainIfPhoneNumber, isCurrentUser, + getAvatarSource, + getAvatarSourceFromReport, getSearchOptions, getNewChatOptions, getSidebarOptions, From 729301d9cc3a3ccffc8d921699b3995c0196e428 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Sat, 26 Feb 2022 11:57:22 -0600 Subject: [PATCH 52/89] use OptionsListUtils.getAvatarSource --- src/pages/ReportDetailsPage.js | 4 +--- src/pages/home/HeaderView.js | 5 +---- src/pages/home/report/ReportActionItemCreated.js | 6 ++---- src/pages/home/sidebar/OptionRow.js | 10 ++++++---- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/pages/ReportDetailsPage.js b/src/pages/ReportDetailsPage.js index 90e2061f3cb2..bf07e64a6e9a 100644 --- a/src/pages/ReportDetailsPage.js +++ b/src/pages/ReportDetailsPage.js @@ -132,11 +132,9 @@ class ReportDetailsPage extends Component { style={styles.reportDetailsTitleContainer} > diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js index f7dab9d69249..a863c7106bd9 100644 --- a/src/pages/home/HeaderView.js +++ b/src/pages/home/HeaderView.js @@ -136,11 +136,8 @@ const HeaderView = (props) => { style={[styles.flexRow, styles.alignItemsCenter, styles.flex1]} > diff --git a/src/pages/home/report/ReportActionItemCreated.js b/src/pages/home/report/ReportActionItemCreated.js index f917bc7c7f5a..0ec08bd956a1 100644 --- a/src/pages/home/report/ReportActionItemCreated.js +++ b/src/pages/home/report/ReportActionItemCreated.js @@ -9,6 +9,7 @@ import * as ReportUtils from '../../../libs/reportUtils'; import styles from '../../../styles/styles'; import * as Expensicons from '../../../components/Icon/Expensicons'; import LargeDualAvatars from '../../../components/LargeDualAvatars'; +import * as OptionsListUtils from '../../../libs/OptionsListUtils'; const propTypes = { /** The report currently being looked at */ @@ -44,10 +45,7 @@ const ReportActionItemCreated = (props) => { /> ) : ( ) } diff --git a/src/pages/home/sidebar/OptionRow.js b/src/pages/home/sidebar/OptionRow.js index 945c6f8d96df..42c7bb1a7b3d 100644 --- a/src/pages/home/sidebar/OptionRow.js +++ b/src/pages/home/sidebar/OptionRow.js @@ -21,6 +21,7 @@ import colors from '../../../styles/colors'; import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; import Text from '../../../components/Text'; import SelectCircle from '../../../components/SelectCircle'; +import * as OptionsListUtils from '../../../libs/OptionsListUtils'; const propTypes = { /** Background Color of the Option Row */ @@ -164,7 +165,11 @@ const OptionRow = (props) => { !_.isEmpty(props.option.icons) && ( OptionsListUtils.getAvatarSource(source, { + isChatRoom: props.option.isChatRoom, + isArchivedRoom: props.option.isArchivedRoom, + isPolicyExpenseChat: props.option.isPolicyExpenseChat, + }))} size={props.mode === 'compact' ? 'small' : 'default'} secondAvatarStyle={[ StyleUtils.getBackgroundAndBorderStyle(props.backgroundColor), @@ -175,9 +180,6 @@ const OptionRow = (props) => { ? StyleUtils.getBackgroundAndBorderStyle(hoveredBackgroundColor) : undefined, ]} - isChatRoom={props.option.isChatRoom} - isArchivedRoom={props.option.isArchivedRoom} - isPolicyExpenseChat={props.option.isPolicyExpenseChat} avatarTooltips={avatarTooltips} showSubscript={props.option.showSubscript} /> From dd69004c9fd698012e829869c3a4989bea4e2276 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Sat, 26 Feb 2022 11:58:49 -0600 Subject: [PATCH 53/89] remove logic to check avatar source from Avatar --- src/components/Avatar.js | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/src/components/Avatar.js b/src/components/Avatar.js index f0cba8be2c66..85f65df0ce5e 100644 --- a/src/components/Avatar.js +++ b/src/components/Avatar.js @@ -6,7 +6,6 @@ import styles from '../styles/styles'; import stylePropTypes from '../styles/stylePropTypes'; import Icon from './Icon'; import variables from '../styles/variables'; -import * as Expensicons from './Icon/Expensicons'; import themeColors from '../styles/themes/default'; import CONST from '../CONST'; @@ -24,15 +23,6 @@ const propTypes = { /** Set the size of Avatar */ size: PropTypes.oneOf(_.values(CONST.AVATAR_SIZE)), - /** Whether this avatar is for a chat room */ - isChatRoom: PropTypes.bool, - - /** Whether this avatar is for an archived default room */ - isArchivedRoom: PropTypes.bool, - - /** Whether this avatar is for a policyExpenseChat */ - isPolicyExpenseChat: PropTypes.bool, - /** The fill color for the icon. Can be hex, rgb, rgba, or valid react-native named color such as 'red' or 'blue' */ fill: PropTypes.string, }; @@ -41,27 +31,12 @@ const defaultProps = { imageStyles: [], containerStyles: [], size: CONST.AVATAR_SIZE.DEFAULT, - isChatRoom: false, - isArchivedRoom: false, - isPolicyExpenseChat: false, fill: themeColors.icon, }; class Avatar extends PureComponent { render() { - let source = this.props.source; - if (!source) { - if (this.props.isChatRoom) { - source = Expensicons.ActiveRoomAvatar; - } - if (this.props.isArchivedRoom) { - source = Expensicons.DeletedRoomAvatar; - } - if (this.props.isPolicyExpenseChat) { - source = Expensicons.Workspace; - } - } - + const source = this.props.source; if (!source) { return null; } From 00fb84eea4aafc804a38e264f488251537e87d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Sat, 26 Feb 2022 12:17:27 -0600 Subject: [PATCH 54/89] get avatar sources (url or icon) for OptionRow --- src/libs/OptionsListUtils.js | 84 ++++++++++++++--------------- src/pages/home/sidebar/OptionRow.js | 7 +-- 2 files changed, 43 insertions(+), 48 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 484b7f106bf0..b87a39661c88 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -224,6 +224,45 @@ function getParticipants(report) { return participants; } +/** + * Get the Avatar url or fallback to the default icon according to the chat type + * + * @param {String} source + * @param {Object} options + * @param {Boolean} [options.isChatRoom] + * @param {Boolean} [options.isArchivedRoom] + * @param {Boolean} [options.isPolicyExpenseChat] + * @returns {String | Function} + */ +function getAvatarSource(source, {isChatRoom, isArchivedRoom, isPolicyExpenseChat}) { + if (!source) { + if (isChatRoom) { + return Expensicons.ActiveRoomAvatar; + } + if (isArchivedRoom) { + return Expensicons.DeletedRoomAvatar; + } + if (isPolicyExpenseChat) { + return Expensicons.Workspace; + } + } + return source; +} + +/** + * Get the Avatar urls or fallback to the default icons according to the chat type + * + * @param {Object} report + * @returns {Array} + */ +function getAvatarSourceFromReport(report) { + return _.map(report.icons, source => getAvatarSource(source, { + isChatRoom: ReportUtils.isChatRoom(report), + isArchivedRoom: ReportUtils.isArchivedRoom(report), + isPolicyExpenseChat: ReportUtils.isPolicyExpenseChat(report), + })); +} + /** * Creates a report list option * @@ -238,6 +277,7 @@ function createOption(personalDetailList, report, { showChatPreviewLine = false, forcePolicyNamePreview = false, }) { const isChatRoom = ReportUtils.isChatRoom(report); + const isArchivedRoom = ReportUtils.isArchivedRoom(report); const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report); const hasMultipleParticipants = personalDetailList.length > 1 || isChatRoom || isPolicyExpenseChat; const personalDetail = personalDetailList[0]; @@ -283,7 +323,7 @@ function createOption(personalDetailList, report, { return { text, alternateText, - icons, + icons: _.map(icons, source => getAvatarSource(source, {isChatRoom, isArchivedRoom, isPolicyExpenseChat})), tooltipText, participantsList: personalDetailList, @@ -303,9 +343,9 @@ function createOption(personalDetailList, report, { isIOUReportOwner: lodashGet(iouReport, 'ownerEmail', '') === currentUserLogin, iouReportAmount: lodashGet(iouReport, 'total', 0), isChatRoom, + isArchivedRoom, isPolicyExpenseChat, showSubscript: isPolicyExpenseChat && !report.isOwnPolicyExpenseChat, - isArchivedRoom: ReportUtils.isArchivedRoom(report), }; } @@ -839,49 +879,9 @@ function getReportIcons(report, personalDetails) { return _.map(sortedParticipants, item => item.avatar); } -/** - * Get the Avatar url or fallback to the default icon according to the chat type - * - * @param {String} source - * @param {Object} options - * @param {Boolean} [options.isChatRoom] - * @param {Boolean} [options.isArchivedRoom] - * @param {Boolean} [options.isPolicyExpenseChat] - * @returns {String | Function} - */ -function getAvatarSource(source, {isChatRoom, isArchivedRoom, isPolicyExpenseChat}) { - if (!source) { - if (isChatRoom) { - return Expensicons.ActiveRoomAvatar; - } - if (isArchivedRoom) { - return Expensicons.DeletedRoomAvatar; - } - if (isPolicyExpenseChat) { - return Expensicons.Workspace; - } - } - return source; -} - -/** - * Get the Avatar urls or fallback to the default icons according to the chat type - * - * @param {Object} report - * @returns {Array} - */ -function getAvatarSourceFromReport(report) { - return _.map(report.icons, source => getAvatarSource(source, { - isChatRoom: ReportUtils.isChatRoom(report), - isArchivedRoom: ReportUtils.isArchivedRoom(report), - isPolicyExpenseChat: ReportUtils.isPolicyExpenseChat(report), - })); -} - export { addSMSDomainIfPhoneNumber, isCurrentUser, - getAvatarSource, getAvatarSourceFromReport, getSearchOptions, getNewChatOptions, diff --git a/src/pages/home/sidebar/OptionRow.js b/src/pages/home/sidebar/OptionRow.js index 42c7bb1a7b3d..5eed2a9c771b 100644 --- a/src/pages/home/sidebar/OptionRow.js +++ b/src/pages/home/sidebar/OptionRow.js @@ -21,7 +21,6 @@ import colors from '../../../styles/colors'; import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; import Text from '../../../components/Text'; import SelectCircle from '../../../components/SelectCircle'; -import * as OptionsListUtils from '../../../libs/OptionsListUtils'; const propTypes = { /** Background Color of the Option Row */ @@ -165,11 +164,7 @@ const OptionRow = (props) => { !_.isEmpty(props.option.icons) && ( OptionsListUtils.getAvatarSource(source, { - isChatRoom: props.option.isChatRoom, - isArchivedRoom: props.option.isArchivedRoom, - isPolicyExpenseChat: props.option.isPolicyExpenseChat, - }))} + avatarImageURLs={props.option.icons} size={props.mode === 'compact' ? 'small' : 'default'} secondAvatarStyle={[ StyleUtils.getBackgroundAndBorderStyle(props.backgroundColor), From 4775ec2ace5de81ab2308aeaa07fb149800595de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Sat, 26 Feb 2022 12:39:40 -0600 Subject: [PATCH 55/89] rename avatarImageURLs to avatarIcons and change props --- src/components/LargeDualAvatars.js | 6 ++--- src/components/MultipleAvatars.js | 22 +++++++++---------- src/components/ReportActionItem/IOUPreview.js | 2 +- src/components/RoomHeaderAvatars.js | 22 +++++++++---------- src/components/SubscriptAvatar.js | 6 ++--- src/components/optionPropTypes.js | 4 ++-- src/pages/home/HeaderView.js | 2 +- .../home/report/ReportActionItemCreated.js | 5 +++-- src/pages/home/sidebar/OptionRow.js | 2 +- src/pages/home/sidebar/optionPropTypes.js | 4 ++-- 10 files changed, 38 insertions(+), 37 deletions(-) diff --git a/src/components/LargeDualAvatars.js b/src/components/LargeDualAvatars.js index a2443ab7a352..9840d791bd3c 100644 --- a/src/components/LargeDualAvatars.js +++ b/src/components/LargeDualAvatars.js @@ -9,7 +9,7 @@ import CONST from '../CONST'; const propTypes = { /** Array of avatar URL */ - avatarImageURLs: PropTypes.arrayOf(PropTypes.string).isRequired, + avatarIcons: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.func])).isRequired, /** Tooltip for the Avatar */ avatarTooltips: PropTypes.arrayOf(PropTypes.string).isRequired, @@ -23,7 +23,7 @@ const LargeDualAvatars = props => ( @@ -31,7 +31,7 @@ const LargeDualAvatars = props => ( { ...props.secondAvatarStyle, ]; - if (!props.avatarImageURLs.length) { + if (!props.avatarIcons.length) { return null; } - if (props.avatarImageURLs.length === 1) { + if (props.avatarIcons.length === 1) { return ( { if (props.showSubscript) { return ( Expensicons.Workspace} /> @@ -93,17 +93,17 @@ const MultipleAvatars = (props) => { > - {props.avatarImageURLs.length === 2 ? ( + {props.avatarIcons.length === 2 ? ( @@ -116,7 +116,7 @@ const MultipleAvatars = (props) => { ? styles.avatarInnerTextSmall : styles.avatarInnerText} > - {`+${props.avatarImageURLs.length - 1}`} + {`+${props.avatarIcons.length - 1}`} diff --git a/src/components/ReportActionItem/IOUPreview.js b/src/components/ReportActionItem/IOUPreview.js index 4e4792c9086c..309a46bff735 100644 --- a/src/components/ReportActionItem/IOUPreview.js +++ b/src/components/ReportActionItem/IOUPreview.js @@ -139,7 +139,7 @@ const IOUPreview = (props) => { diff --git a/src/components/RoomHeaderAvatars.js b/src/components/RoomHeaderAvatars.js index a2a7c5cfd8cf..d680e231c2a6 100644 --- a/src/components/RoomHeaderAvatars.js +++ b/src/components/RoomHeaderAvatars.js @@ -9,8 +9,8 @@ import Avatar from './Avatar'; import themeColors from '../styles/themes/default'; const propTypes = { - /** Array of avatar URL */ - avatarImageURLs: PropTypes.arrayOf(PropTypes.string), + /** Array of avatar URLs or icons */ + avatarIcons: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.func])), /** Whether this avatar is for a custom/default room */ isChatRoom: PropTypes.bool, @@ -23,21 +23,21 @@ const propTypes = { }; const defaultProps = { - avatarImageURLs: [], + avatarIcons: [], isChatRoom: false, isArchivedRoom: false, isPolicyExpenseChat: false, }; const RoomHeaderAvatars = (props) => { - if (!props.avatarImageURLs.length) { + if (!props.avatarIcons.length) { return null; } - if (props.avatarImageURLs.length === 1) { + if (props.avatarIcons.length === 1) { return ( { ); } - // avatarImageURLsToDisplay - const avatarImageURLsToDisplay = props.avatarImageURLs.slice(0, CONST.REPORT.MAX_PREVIEW_AVATARS); + // avatarIconsToDisplay + const avatarIconsToDisplay = props.avatarIcons.slice(0, CONST.REPORT.MAX_PREVIEW_AVATARS); return ( - {_.map(avatarImageURLsToDisplay, (val, index) => ( + {_.map(avatarIconsToDisplay, (val, index) => ( - {index === CONST.REPORT.MAX_PREVIEW_AVATARS - 1 && props.avatarImageURLs.length - CONST.REPORT.MAX_PREVIEW_AVATARS !== 0 && ( + {index === CONST.REPORT.MAX_PREVIEW_AVATARS - 1 && props.avatarIcons.length - CONST.REPORT.MAX_PREVIEW_AVATARS !== 0 && ( <> { ]} /> - {`+${props.avatarImageURLs.length - CONST.REPORT.MAX_PREVIEW_AVATARS}`} + {`+${props.avatarIcons.length - CONST.REPORT.MAX_PREVIEW_AVATARS}`} )} diff --git a/src/components/SubscriptAvatar.js b/src/components/SubscriptAvatar.js index bd40f80ca044..6bf01456e4d6 100644 --- a/src/components/SubscriptAvatar.js +++ b/src/components/SubscriptAvatar.js @@ -9,7 +9,7 @@ import CONST from '../CONST'; const propTypes = { /** Array of avatar URL */ - avatarImageURLs: PropTypes.arrayOf(PropTypes.string).isRequired, + avatarIcons: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.func])).isRequired, /** Tooltip for the Avatar */ avatarTooltips: PropTypes.arrayOf(PropTypes.string).isRequired, @@ -23,7 +23,7 @@ const SubscriptAvatar = props => ( @@ -32,7 +32,7 @@ const SubscriptAvatar = props => ( > { style={[styles.flexRow, styles.alignItemsCenter, styles.flex1]} > { const isChatRoom = ReportUtils.isChatRoom(props.report); const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(props.report); + const avatarIcons = OptionsListUtils.getAvatarSourceFromReport(props.report); return ( { { isPolicyExpenseChat && !props.report.isOwnPolicyExpenseChat ? ( Expensicons.Workspace} /> ) : ( ) } diff --git a/src/pages/home/sidebar/OptionRow.js b/src/pages/home/sidebar/OptionRow.js index 5eed2a9c771b..8f52806825b8 100644 --- a/src/pages/home/sidebar/OptionRow.js +++ b/src/pages/home/sidebar/OptionRow.js @@ -164,7 +164,7 @@ const OptionRow = (props) => { !_.isEmpty(props.option.icons) && ( Date: Sat, 26 Feb 2022 12:45:38 -0600 Subject: [PATCH 56/89] remove unused isChatRoom, isArchivedRoom and isPolicyExpenseChat --- src/components/MultipleAvatars.js | 15 --------------- src/components/RoomHeaderAvatars.js | 15 --------------- src/libs/OptionsListUtils.js | 3 --- 3 files changed, 33 deletions(-) diff --git a/src/components/MultipleAvatars.js b/src/components/MultipleAvatars.js index 180025e8c5c2..6fc36990f329 100644 --- a/src/components/MultipleAvatars.js +++ b/src/components/MultipleAvatars.js @@ -20,15 +20,6 @@ const propTypes = { // eslint-disable-next-line react/forbid-prop-types secondAvatarStyle: PropTypes.arrayOf(PropTypes.object), - /** Whether this avatar is for a chat room */ - isChatRoom: PropTypes.bool, - - /** Whether this avatar is for an archived room */ - isArchivedRoom: PropTypes.bool, - - /** Whether this avatar is for a policyExpenseChat */ - isPolicyExpenseChat: PropTypes.bool, - /** Tooltip for the Avatar */ avatarTooltips: PropTypes.arrayOf(PropTypes.string), @@ -40,11 +31,8 @@ const defaultProps = { avatarIcons: [], size: 'default', secondAvatarStyle: [styles.secondAvatarHovered], - isChatRoom: false, - isArchivedRoom: false, avatarTooltips: [], showSubscript: false, - isPolicyExpenseChat: false, }; const MultipleAvatars = (props) => { @@ -66,9 +54,6 @@ const MultipleAvatars = (props) => { diff --git a/src/components/RoomHeaderAvatars.js b/src/components/RoomHeaderAvatars.js index d680e231c2a6..d01fdc5692df 100644 --- a/src/components/RoomHeaderAvatars.js +++ b/src/components/RoomHeaderAvatars.js @@ -11,22 +11,10 @@ import themeColors from '../styles/themes/default'; const propTypes = { /** Array of avatar URLs or icons */ avatarIcons: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.func])), - - /** Whether this avatar is for a custom/default room */ - isChatRoom: PropTypes.bool, - - /** Whether this avatar is for an archived room */ - isArchivedRoom: PropTypes.bool, - - /** Whether this avatar is for a policyExpenseChat */ - isPolicyExpenseChat: PropTypes.bool, }; const defaultProps = { avatarIcons: [], - isChatRoom: false, - isArchivedRoom: false, - isPolicyExpenseChat: false, }; const RoomHeaderAvatars = (props) => { @@ -39,9 +27,6 @@ const RoomHeaderAvatars = (props) => { diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index b87a39661c88..8704fde69982 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -342,9 +342,6 @@ function createOption(personalDetailList, report, { iouReportID: lodashGet(report, 'iouReportID'), isIOUReportOwner: lodashGet(iouReport, 'ownerEmail', '') === currentUserLogin, iouReportAmount: lodashGet(iouReport, 'total', 0), - isChatRoom, - isArchivedRoom, - isPolicyExpenseChat, showSubscript: isPolicyExpenseChat && !report.isOwnPolicyExpenseChat, }; } From a199aa6c279e4b451c9fd412db4477ed895abc48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Sat, 26 Feb 2022 13:42:31 -0600 Subject: [PATCH 57/89] change params to SubscriptAvatar --- src/components/Avatar.js | 3 ++- src/components/MultipleAvatars.js | 5 ++--- src/components/SubscriptAvatar.js | 14 +++++++------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/components/Avatar.js b/src/components/Avatar.js index 85f65df0ce5e..cae4480ef448 100644 --- a/src/components/Avatar.js +++ b/src/components/Avatar.js @@ -12,7 +12,7 @@ import CONST from '../CONST'; const propTypes = { /** Source for the avatar. Can be the URL of an image or an icon. */ - source: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired, + source: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), /** Extra styles to pass to Image */ imageStyles: PropTypes.arrayOf(PropTypes.object), @@ -28,6 +28,7 @@ const propTypes = { }; const defaultProps = { + source: null, imageStyles: [], containerStyles: [], size: CONST.AVATAR_SIZE.DEFAULT, diff --git a/src/components/MultipleAvatars.js b/src/components/MultipleAvatars.js index 6fc36990f329..2585fdeef6b1 100644 --- a/src/components/MultipleAvatars.js +++ b/src/components/MultipleAvatars.js @@ -6,7 +6,6 @@ import Avatar from './Avatar'; import Tooltip from './Tooltip'; import Text from './Text'; import SubscriptAvatar from './SubscriptAvatar'; -import * as Expensicons from './Icon/Expensicons'; import themeColors from '../styles/themes/default'; const propTypes = { @@ -64,9 +63,9 @@ const MultipleAvatars = (props) => { if (props.showSubscript) { return ( Expensicons.Workspace} /> ); } diff --git a/src/components/SubscriptAvatar.js b/src/components/SubscriptAvatar.js index 6bf01456e4d6..cddaa1816782 100644 --- a/src/components/SubscriptAvatar.js +++ b/src/components/SubscriptAvatar.js @@ -8,14 +8,14 @@ import Avatar from './Avatar'; import CONST from '../CONST'; const propTypes = { - /** Array of avatar URL */ - avatarIcons: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.func])).isRequired, + /** Avatar URL or icon */ + mainAvatar: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired, + + /** Subscript avatar URL or icon */ + secondaryAvatar: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired, /** Tooltip for the Avatar */ avatarTooltips: PropTypes.arrayOf(PropTypes.string).isRequired, - - /** Default icon if the subscript image is not set */ - defaultSubscriptIcon: PropTypes.func.isRequired, }; const SubscriptAvatar = props => ( @@ -23,7 +23,7 @@ const SubscriptAvatar = props => ( @@ -32,7 +32,7 @@ const SubscriptAvatar = props => ( > Date: Sat, 26 Feb 2022 14:02:30 -0600 Subject: [PATCH 58/89] use _.contains() instead of .includes() --- src/libs/OptionsListUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 8704fde69982..0f4abfc71e54 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -212,7 +212,7 @@ function hasReportDraftComment(report) { function getParticipants(report) { const participants = [...lodashGet(report, ['participants'], [])]; if (ReportUtils.isPolicyExpenseChat(report)) { - if (!participants.includes(report.ownerEmail)) { + if (!_.contains(participants, report.ownerEmail)) { participants.push(report.ownerEmail); } From d537a2835bc5e7f661c57fbf6b1631680eb9c949 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Sat, 26 Feb 2022 14:15:08 -0600 Subject: [PATCH 59/89] include participants in getParticipantEmailsFromReport --- src/libs/OptionsListUtils.js | 5 ----- src/libs/actions/Report.js | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 0f4abfc71e54..82266cc0431b 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -215,11 +215,6 @@ function getParticipants(report) { if (!_.contains(participants, report.ownerEmail)) { participants.push(report.ownerEmail); } - - // Include admin as participant - if (!report.isOwnPolicyExpenseChat) { - participants.push(currentUserLogin); - } } return participants; } diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index 6da07c7211fe..61ddc7b3a07a 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -123,7 +123,7 @@ function getUnreadActionCount(report) { */ function getParticipantEmailsFromReport({sharedReportList, reportNameValuePairs}) { const emailArray = _.map(sharedReportList, participant => participant.email); - return ReportUtils.isChatRoom(reportNameValuePairs) ? emailArray : _.without(emailArray, currentUserEmail); + return (ReportUtils.isChatRoom(reportNameValuePairs) || ReportUtils.isPolicyExpenseChat(reportNameValuePairs)) ? emailArray : _.without(emailArray, currentUserEmail); } /** From ca1b02436b0d9b6a7ccf0f8bfbe8bc8c6269de00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Sat, 26 Feb 2022 14:21:42 -0600 Subject: [PATCH 60/89] change showSubscript flag to shouldShowSubscript --- src/components/MultipleAvatars.js | 6 +++--- src/libs/OptionsListUtils.js | 2 +- src/pages/home/HeaderView.js | 2 +- src/pages/home/sidebar/OptionRow.js | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/MultipleAvatars.js b/src/components/MultipleAvatars.js index 2585fdeef6b1..a0c8d513d0d7 100644 --- a/src/components/MultipleAvatars.js +++ b/src/components/MultipleAvatars.js @@ -23,7 +23,7 @@ const propTypes = { avatarTooltips: PropTypes.arrayOf(PropTypes.string), /** Flag to show SubscriptAvatar component */ - showSubscript: PropTypes.bool, + shouldShowSubscript: PropTypes.bool, }; const defaultProps = { @@ -31,7 +31,7 @@ const defaultProps = { size: 'default', secondAvatarStyle: [styles.secondAvatarHovered], avatarTooltips: [], - showSubscript: false, + shouldShowSubscript: false, }; const MultipleAvatars = (props) => { @@ -60,7 +60,7 @@ const MultipleAvatars = (props) => { ); } - if (props.showSubscript) { + if (props.shouldShowSubscript) { return ( { avatarIcons={OptionsListUtils.getAvatarSourceFromReport(props.report)} secondAvatarStyle={[styles.secondAvatarHovered]} avatarTooltips={avatarTooltip} - showSubscript={isPolicyExpenseChat && !props.report.isOwnPolicyExpenseChat} + shouldShowSubscript={isPolicyExpenseChat && !props.report.isOwnPolicyExpenseChat} /> { : undefined, ]} avatarTooltips={avatarTooltips} - showSubscript={props.option.showSubscript} + shouldShowSubscript={props.option.shouldShowSubscript} /> ) } From d55c0f373b5442011cc7747c0bee69c6323f0542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Sat, 26 Feb 2022 14:51:47 -0600 Subject: [PATCH 61/89] revert condition for reportMapForLogins (fixed with report.participants fix) --- src/libs/OptionsListUtils.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 7bf8bb86abe7..5c993fcb0817 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -491,9 +491,9 @@ function getOptions(reports, personalDetails, activeReportID, { const reportPersonalDetails = getPersonalDetailsForLogins(logins, personalDetails); - // Save the report in the map if this is a single participant (with the exception of PolicyExpenseChat and - // default rooms) so we can associate the reportID with the personal detail option later. - if (logins.length <= 1 && !isPolicyExpenseChat && !isDefaultRoom) { + // Save the report in the map if this is a single participant so we can associate the reportID with the + // personal detail option later. + if (logins.length <= 1) { reportMapForLogins[logins[0]] = report; } const isSearchingSomeonesPolicyExpenseChat = !report.isOwnPolicyExpenseChat && searchValue !== ''; From 7aa05fa1880137748247a7db703a6875b5e9b369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Sat, 26 Feb 2022 14:54:34 -0600 Subject: [PATCH 62/89] give priority to isArchivedRoom in getAvatarSource --- src/libs/OptionsListUtils.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 5c993fcb0817..af079c51c074 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -231,12 +231,12 @@ function getParticipants(report) { */ function getAvatarSource(source, {isChatRoom, isArchivedRoom, isPolicyExpenseChat}) { if (!source) { - if (isChatRoom) { - return Expensicons.ActiveRoomAvatar; - } if (isArchivedRoom) { return Expensicons.DeletedRoomAvatar; } + if (isChatRoom) { + return Expensicons.ActiveRoomAvatar; + } if (isPolicyExpenseChat) { return Expensicons.Workspace; } From 46876129c79622fcbcafa12cb48224e08ad3f7f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Sat, 26 Feb 2022 15:04:32 -0600 Subject: [PATCH 63/89] update comment about returning workspace avatar --- src/libs/OptionsListUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index af079c51c074..fb507f9e949a 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -852,7 +852,7 @@ function getReportIcons(report, personalDetails) { `${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`, 'avatarURL', ]); - // If the user is not an admin for this workspace chat, return avatar of the workspace + // Return the workspace avatar if the user is the owner of the policy expense chat if (report.isOwnPolicyExpenseChat) { return [policyExpenseChatAvatarURL]; } From 8846c8d14f73ccdbaad50cb3ccb20f24cfb14c6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Sat, 26 Feb 2022 15:07:51 -0600 Subject: [PATCH 64/89] use props.source directly --- src/components/Avatar.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/components/Avatar.js b/src/components/Avatar.js index cae4480ef448..bbdb296cec35 100644 --- a/src/components/Avatar.js +++ b/src/components/Avatar.js @@ -37,8 +37,7 @@ const defaultProps = { class Avatar extends PureComponent { render() { - const source = this.props.source; - if (!source) { + if (!this.props.source) { return null; } @@ -57,9 +56,9 @@ class Avatar extends PureComponent { return ( { - _.isFunction(source) - ? - : + _.isFunction(this.props.source) + ? + : } ); From a7e2a00c937b02e75d0cbb810a48ba5a0f60450b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Sat, 26 Feb 2022 15:28:28 -0600 Subject: [PATCH 65/89] move large dual avatars to RoomHeaderAvatars and remove LargeDualAvatars --- src/components/LargeDualAvatars.js | 45 ------------------- src/components/RoomHeaderAvatars.js | 25 +++++++++++ .../home/report/ReportActionItemCreated.js | 19 ++------ 3 files changed, 29 insertions(+), 60 deletions(-) delete mode 100644 src/components/LargeDualAvatars.js diff --git a/src/components/LargeDualAvatars.js b/src/components/LargeDualAvatars.js deleted file mode 100644 index 9840d791bd3c..000000000000 --- a/src/components/LargeDualAvatars.js +++ /dev/null @@ -1,45 +0,0 @@ -import React, {memo} from 'react'; -import PropTypes from 'prop-types'; -import {View} from 'react-native'; -import styles from '../styles/styles'; -import Tooltip from './Tooltip'; -import themeColors from '../styles/themes/default'; -import Avatar from './Avatar'; -import CONST from '../CONST'; - -const propTypes = { - /** Array of avatar URL */ - avatarIcons: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.func])).isRequired, - - /** Tooltip for the Avatar */ - avatarTooltips: PropTypes.arrayOf(PropTypes.string).isRequired, - - /** Default icon if the subscript image is not set */ - defaultSubscriptIcon: PropTypes.func.isRequired, -}; - -const LargeDualAvatars = props => ( - - - - - - - - - - - - -); - -LargeDualAvatars.propTypes = propTypes; -export default memo(LargeDualAvatars); diff --git a/src/components/RoomHeaderAvatars.js b/src/components/RoomHeaderAvatars.js index d01fdc5692df..b374758e133a 100644 --- a/src/components/RoomHeaderAvatars.js +++ b/src/components/RoomHeaderAvatars.js @@ -11,10 +11,14 @@ import themeColors from '../styles/themes/default'; const propTypes = { /** Array of avatar URLs or icons */ avatarIcons: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.func])), + + /** Whether show large Avatars */ + shouldShowLargeAvatars: PropTypes.bool, }; const defaultProps = { avatarIcons: [], + shouldShowLargeAvatars: false, }; const RoomHeaderAvatars = (props) => { @@ -33,6 +37,27 @@ const RoomHeaderAvatars = (props) => { ); } + if (props.shouldShowLargeAvatars) { + return ( + + + + + + + + + ); + } + // avatarIconsToDisplay const avatarIconsToDisplay = props.avatarIcons.slice(0, CONST.REPORT.MAX_PREVIEW_AVATARS); diff --git a/src/pages/home/report/ReportActionItemCreated.js b/src/pages/home/report/ReportActionItemCreated.js index ad0287e21c0f..b1cdf25a7625 100644 --- a/src/pages/home/report/ReportActionItemCreated.js +++ b/src/pages/home/report/ReportActionItemCreated.js @@ -7,8 +7,6 @@ import RoomHeaderAvatars from '../../../components/RoomHeaderAvatars'; import ReportWelcomeText from '../../../components/ReportWelcomeText'; import * as ReportUtils from '../../../libs/reportUtils'; import styles from '../../../styles/styles'; -import * as Expensicons from '../../../components/Icon/Expensicons'; -import LargeDualAvatars from '../../../components/LargeDualAvatars'; import * as OptionsListUtils from '../../../libs/OptionsListUtils'; const propTypes = { @@ -37,19 +35,10 @@ const ReportActionItemCreated = (props) => { ]} > - { - isPolicyExpenseChat && !props.report.isOwnPolicyExpenseChat ? ( - Expensicons.Workspace} - /> - ) : ( - - ) - } + From 40325c727ed7d0e3dfa4f3edf6eaa2a0d673e8e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Sat, 26 Feb 2022 15:34:41 -0600 Subject: [PATCH 66/89] fix jsdoc for icons --- src/libs/OptionsListUtils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index fb507f9e949a..593eb442620a 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -227,7 +227,7 @@ function getParticipants(report) { * @param {Boolean} [options.isChatRoom] * @param {Boolean} [options.isArchivedRoom] * @param {Boolean} [options.isPolicyExpenseChat] - * @returns {String | Function} + * @returns {String | function():any} */ function getAvatarSource(source, {isChatRoom, isArchivedRoom, isPolicyExpenseChat}) { if (!source) { @@ -248,7 +248,7 @@ function getAvatarSource(source, {isChatRoom, isArchivedRoom, isPolicyExpenseCha * Get the Avatar urls or fallback to the default icons according to the chat type * * @param {Object} report - * @returns {Array} + * @returns {Array} */ function getAvatarSourceFromReport(report) { return _.map(report.icons, source => getAvatarSource(source, { From 9e694912e0eb39c4685e70f051538fa93a28899b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Mon, 28 Feb 2022 13:06:40 -0600 Subject: [PATCH 67/89] move avatar size logic to the new funciton getAvatarSize --- src/components/Avatar.js | 10 ++-------- src/styles/StyleUtils.js | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/components/Avatar.js b/src/components/Avatar.js index bbdb296cec35..c08fa262fbca 100644 --- a/src/components/Avatar.js +++ b/src/components/Avatar.js @@ -5,9 +5,9 @@ import _ from 'underscore'; import styles from '../styles/styles'; import stylePropTypes from '../styles/stylePropTypes'; import Icon from './Icon'; -import variables from '../styles/variables'; import themeColors from '../styles/themes/default'; import CONST from '../CONST'; +import * as StyleUtils from '../styles/StyleUtils'; const propTypes = { @@ -46,13 +46,7 @@ class Avatar extends PureComponent { ...this.props.imageStyles, ]; - const AVATAR_SIZES = { - [CONST.AVATAR_SIZE.DEFAULT]: variables.avatarSizeNormal, - [CONST.AVATAR_SIZE.SUBSCRIPT]: variables.avatarSizeSubscript, - [CONST.AVATAR_SIZE.SMALL]: variables.avatarSizeSmall, - [CONST.AVATAR_SIZE.LARGE]: variables.avatarSizeLarge, - }; - const iconSize = AVATAR_SIZES[this.props.size]; + const iconSize = StyleUtils.getAvatarSize(this.props.size); return ( { diff --git a/src/styles/StyleUtils.js b/src/styles/StyleUtils.js index 038ed6b5f5da..3a89b5463a93 100644 --- a/src/styles/StyleUtils.js +++ b/src/styles/StyleUtils.js @@ -7,6 +7,22 @@ import colors from './colors'; import positioning from './utilities/positioning'; import styles from './styles'; +/** + * Return the style size from an avatar size constant + * + * @param {String} size + * @returns {Number} + */ +function getAvatarSize(size) { + const AVATAR_SIZES = { + [CONST.AVATAR_SIZE.DEFAULT]: variables.avatarSizeNormal, + [CONST.AVATAR_SIZE.SUBSCRIPT]: variables.avatarSizeSubscript, + [CONST.AVATAR_SIZE.SMALL]: variables.avatarSizeSmall, + [CONST.AVATAR_SIZE.LARGE]: variables.avatarSizeLarge, + }; + return AVATAR_SIZES[size]; +} + /** * Takes safe area insets and returns padding to use for a View * @@ -405,6 +421,7 @@ function parseStyleAsArray(styleParam) { } export { + getAvatarSize, getSafeAreaPadding, getSafeAreaMargins, getNavigationDrawerStyle, From d47652bd177de0fc0b07a4c2ac12a52f81601bfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Mon, 28 Feb 2022 13:25:09 -0600 Subject: [PATCH 68/89] delete redundant comment --- src/components/RoomHeaderAvatars.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/RoomHeaderAvatars.js b/src/components/RoomHeaderAvatars.js index b374758e133a..13f28662fb53 100644 --- a/src/components/RoomHeaderAvatars.js +++ b/src/components/RoomHeaderAvatars.js @@ -58,9 +58,7 @@ const RoomHeaderAvatars = (props) => { ); } - // avatarIconsToDisplay const avatarIconsToDisplay = props.avatarIcons.slice(0, CONST.REPORT.MAX_PREVIEW_AVATARS); - return ( From bbff6ef36a9a76b1f89e91b74bc67324f4bd10a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Mon, 28 Feb 2022 13:28:14 -0600 Subject: [PATCH 69/89] move condition logic to one line --- src/libs/OptionsListUtils.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 593eb442620a..1eb805fcc1b2 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -211,10 +211,8 @@ function hasReportDraftComment(report) { */ function getParticipants(report) { const participants = [...lodashGet(report, ['participants'], [])]; - if (ReportUtils.isPolicyExpenseChat(report)) { - if (!_.contains(participants, report.ownerEmail)) { - participants.push(report.ownerEmail); - } + if (ReportUtils.isPolicyExpenseChat(report) && !_.contains(participants, report.ownerEmail)) { + participants.push(report.ownerEmail); } return participants; } From 41b6c253bcc217e88e4f113d7c2aaf6f0e6b7159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Mon, 28 Feb 2022 13:32:24 -0600 Subject: [PATCH 70/89] use {*} to follow jsdoc style guides --- src/libs/OptionsListUtils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 1eb805fcc1b2..849f8ab7a996 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -225,7 +225,7 @@ function getParticipants(report) { * @param {Boolean} [options.isChatRoom] * @param {Boolean} [options.isArchivedRoom] * @param {Boolean} [options.isPolicyExpenseChat] - * @returns {String | function():any} + * @returns {*} */ function getAvatarSource(source, {isChatRoom, isArchivedRoom, isPolicyExpenseChat}) { if (!source) { @@ -246,7 +246,7 @@ function getAvatarSource(source, {isChatRoom, isArchivedRoom, isPolicyExpenseCha * Get the Avatar urls or fallback to the default icons according to the chat type * * @param {Object} report - * @returns {Array} + * @returns {Array<*>} */ function getAvatarSourceFromReport(report) { return _.map(report.icons, source => getAvatarSource(source, { From f11c42326021ca42589334e4a77aa1ea43863476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Mon, 28 Feb 2022 14:50:16 -0600 Subject: [PATCH 71/89] merge logic of getAvatarSources --- src/libs/OptionsListUtils.js | 51 ++++++++++-------------------------- 1 file changed, 14 insertions(+), 37 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 849f8ab7a996..1d697c86aa85 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -218,42 +218,26 @@ function getParticipants(report) { } /** - * Get the Avatar url or fallback to the default icon according to the chat type + * Get the Avatar urls or return the icon according to the chat type * - * @param {String} source - * @param {Object} options - * @param {Boolean} [options.isChatRoom] - * @param {Boolean} [options.isArchivedRoom] - * @param {Boolean} [options.isPolicyExpenseChat] - * @returns {*} + * @param {Object} report + * @returns {Array<*>} */ -function getAvatarSource(source, {isChatRoom, isArchivedRoom, isPolicyExpenseChat}) { - if (!source) { - if (isArchivedRoom) { +function getAvatarSources(report) { + return _.map(lodashGet(report, 'icons', ['']), (source) => { + if (source) { + return source; + } + if (ReportUtils.isArchivedRoom(report)) { return Expensicons.DeletedRoomAvatar; } - if (isChatRoom) { + if (ReportUtils.isChatRoom(report)) { return Expensicons.ActiveRoomAvatar; } - if (isPolicyExpenseChat) { + if (ReportUtils.isPolicyExpenseChat(report)) { return Expensicons.Workspace; } - } - return source; -} - -/** - * Get the Avatar urls or fallback to the default icons according to the chat type - * - * @param {Object} report - * @returns {Array<*>} - */ -function getAvatarSourceFromReport(report) { - return _.map(report.icons, source => getAvatarSource(source, { - isChatRoom: ReportUtils.isChatRoom(report), - isArchivedRoom: ReportUtils.isArchivedRoom(report), - isPolicyExpenseChat: ReportUtils.isPolicyExpenseChat(report), - })); + }); } /** @@ -270,7 +254,6 @@ function createOption(personalDetailList, report, { showChatPreviewLine = false, forcePolicyNamePreview = false, }) { const isChatRoom = ReportUtils.isChatRoom(report); - const isArchivedRoom = ReportUtils.isArchivedRoom(report); const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(report); const hasMultipleParticipants = personalDetailList.length > 1 || isChatRoom || isPolicyExpenseChat; const personalDetail = personalDetailList[0]; @@ -293,16 +276,11 @@ function createOption(personalDetailList, report, { let text; let alternateText; - let icons; if (isChatRoom || isPolicyExpenseChat) { text = lodashGet(report, ['reportName'], ''); alternateText = (showChatPreviewLine && !forcePolicyNamePreview && lastMessageText) ? lastMessageText : ReportUtils.getChatRoomSubtitle(report, policies); - - // Chat rooms do not use icons from their users for the avatar so falling back on personalDetails - // doesn't make sense here - icons = lodashGet(report, 'icons', ['']); } else { text = hasMultipleParticipants ? _.map(personalDetailList, ({firstName, login}) => firstName || Str.removeSMSDomain(login)) @@ -311,12 +289,11 @@ function createOption(personalDetailList, report, { alternateText = (showChatPreviewLine && lastMessageText) ? lastMessageText : Str.removeSMSDomain(personalDetail.login); - icons = lodashGet(report, 'icons', [personalDetail.avatar]); } return { text, alternateText, - icons: _.map(icons, source => getAvatarSource(source, {isChatRoom, isArchivedRoom, isPolicyExpenseChat})), + icons: getAvatarSources(report), tooltipText, participantsList: personalDetailList, @@ -872,7 +849,7 @@ function getReportIcons(report, personalDetails) { export { addSMSDomainIfPhoneNumber, isCurrentUser, - getAvatarSourceFromReport, + getAvatarSources, getSearchOptions, getNewChatOptions, getSidebarOptions, From e827030c9da2e4c62b35b969b90dfd3cd86c48d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Mon, 28 Feb 2022 14:50:53 -0600 Subject: [PATCH 72/89] replace getAvatarSourceFromReport with getAvatarSources --- src/pages/ReportDetailsPage.js | 2 +- src/pages/home/HeaderView.js | 2 +- src/pages/home/report/ReportActionItemCreated.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/ReportDetailsPage.js b/src/pages/ReportDetailsPage.js index bf07e64a6e9a..9eb20e6f0117 100644 --- a/src/pages/ReportDetailsPage.js +++ b/src/pages/ReportDetailsPage.js @@ -134,7 +134,7 @@ class ReportDetailsPage extends Component { diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js index 1bdd227e204f..2196a02c7839 100644 --- a/src/pages/home/HeaderView.js +++ b/src/pages/home/HeaderView.js @@ -136,7 +136,7 @@ const HeaderView = (props) => { style={[styles.flexRow, styles.alignItemsCenter, styles.flex1]} > { const isChatRoom = ReportUtils.isChatRoom(props.report); const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(props.report); - const avatarIcons = OptionsListUtils.getAvatarSourceFromReport(props.report); + const avatarIcons = OptionsListUtils.getAvatarSources(props.report); return ( Date: Mon, 28 Feb 2022 14:52:26 -0600 Subject: [PATCH 73/89] return Profile icon instead of personalDetail.avatar --- src/libs/OptionsListUtils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 1d697c86aa85..82178a2e2544 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -237,6 +237,7 @@ function getAvatarSources(report) { if (ReportUtils.isPolicyExpenseChat(report)) { return Expensicons.Workspace; } + return Expensicons.Profile; }); } From 5bcca5f008d2029da444833d397a154a65cc4284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Mon, 28 Feb 2022 16:16:52 -0600 Subject: [PATCH 74/89] fix styles of large workspace room avatars --- src/components/RoomHeaderAvatars.js | 13 +++++++------ src/styles/styles.js | 22 +++++++++------------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/components/RoomHeaderAvatars.js b/src/components/RoomHeaderAvatars.js index 13f28662fb53..5791ead0602a 100644 --- a/src/components/RoomHeaderAvatars.js +++ b/src/components/RoomHeaderAvatars.js @@ -39,19 +39,20 @@ const RoomHeaderAvatars = (props) => { if (props.shouldShowLargeAvatars) { return ( - - + + - + diff --git a/src/styles/styles.js b/src/styles/styles.js index b995277f9922..07fef1cfcec7 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -1543,12 +1543,15 @@ const styles = { borderColor: 'transparent', }, - secondAvatarLarge: { - position: 'absolute', - left: -40, - borderWidth: 2, - borderRadius: 18, - borderColor: 'transparent', + leftSideLargeAvatar: { + left: 15, + }, + + rightSideLargeAvatar: { + right: 15, + zIndex: 2, + borderWidth: 4, + borderRadius: 100, }, secondAvatarInline: { @@ -1825,13 +1828,6 @@ const styles = { width: '100%', }, - rightSideLargeAvatar: { - zIndex: 2, - borderRadius: 100, - borderColor: themeColors.componentBG, - borderWidth: 4, - }, - avatarLarge: { width: variables.avatarSizeLarge, height: variables.avatarSizeLarge, From 5ac47134f7cb32067754a82a6c38c874d388b8c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Mon, 28 Feb 2022 16:29:57 -0600 Subject: [PATCH 75/89] call SubscriptAvatar directly --- src/components/MultipleAvatars.js | 15 ------------ src/pages/home/HeaderView.js | 24 ++++++++++++------ src/pages/home/sidebar/OptionRow.js | 38 +++++++++++++++++------------ 3 files changed, 39 insertions(+), 38 deletions(-) diff --git a/src/components/MultipleAvatars.js b/src/components/MultipleAvatars.js index a0c8d513d0d7..144d591185d2 100644 --- a/src/components/MultipleAvatars.js +++ b/src/components/MultipleAvatars.js @@ -5,7 +5,6 @@ import styles from '../styles/styles'; import Avatar from './Avatar'; import Tooltip from './Tooltip'; import Text from './Text'; -import SubscriptAvatar from './SubscriptAvatar'; import themeColors from '../styles/themes/default'; const propTypes = { @@ -21,9 +20,6 @@ const propTypes = { /** Tooltip for the Avatar */ avatarTooltips: PropTypes.arrayOf(PropTypes.string), - - /** Flag to show SubscriptAvatar component */ - shouldShowSubscript: PropTypes.bool, }; const defaultProps = { @@ -31,7 +27,6 @@ const defaultProps = { size: 'default', secondAvatarStyle: [styles.secondAvatarHovered], avatarTooltips: [], - shouldShowSubscript: false, }; const MultipleAvatars = (props) => { @@ -60,16 +55,6 @@ const MultipleAvatars = (props) => { ); } - if (props.shouldShowSubscript) { - return ( - - ); - } - return ( { // We hide the button when we are chatting with an automated Expensify account since it's not possible to contact // these users via alternative means. It is possible to request a call with Concierge so we leave the option for them. const shouldShowCallButton = isConcierge || !isAutomatedExpensifyAccount; - const avatarTooltip = isChatRoom ? undefined : _.pluck(displayNamesWithTooltips, 'tooltip'); - + const shouldShowSubscript = isPolicyExpenseChat && !props.report.isOwnPolicyExpenseChat; + const avatarIcons = OptionsListUtils.getAvatarSources(props.report); return ( @@ -135,12 +136,19 @@ const HeaderView = (props) => { }} style={[styles.flexRow, styles.alignItemsCenter, styles.flex1]} > - + {shouldShowSubscript ? ( + + ) : ( + + )} { { !_.isEmpty(props.option.icons) && ( - + props.option.shouldShowSubscript ? ( + + ) : ( + + ) ) } From 2ac7de79cbbef82a7447891544c37d2bdedc4968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Tue, 1 Mar 2022 11:20:35 -0600 Subject: [PATCH 76/89] set avatarTooltips as optional prop --- src/components/SubscriptAvatar.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/SubscriptAvatar.js b/src/components/SubscriptAvatar.js index cddaa1816782..6aea906c511a 100644 --- a/src/components/SubscriptAvatar.js +++ b/src/components/SubscriptAvatar.js @@ -15,7 +15,11 @@ const propTypes = { secondaryAvatar: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired, /** Tooltip for the Avatar */ - avatarTooltips: PropTypes.arrayOf(PropTypes.string).isRequired, + avatarTooltips: PropTypes.arrayOf(PropTypes.string), +}; + +const defaultProps = { + avatarTooltips: [], }; const SubscriptAvatar = props => ( @@ -43,4 +47,5 @@ const SubscriptAvatar = props => ( ); SubscriptAvatar.propTypes = propTypes; +SubscriptAvatar.defaultProps = defaultProps; export default memo(SubscriptAvatar); From e8fa8f38419df7ec04aedd76d431801dff50ee23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Tue, 1 Mar 2022 12:39:45 -0600 Subject: [PATCH 77/89] fix tooltips in SubscriptAvatar --- src/components/SubscriptAvatar.js | 14 +++++++++----- src/libs/OptionsListUtils.js | 9 +++++++-- src/pages/home/HeaderView.js | 3 ++- src/pages/home/sidebar/OptionRow.js | 5 +++-- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/components/SubscriptAvatar.js b/src/components/SubscriptAvatar.js index 6aea906c511a..1084c58a8d43 100644 --- a/src/components/SubscriptAvatar.js +++ b/src/components/SubscriptAvatar.js @@ -14,18 +14,22 @@ const propTypes = { /** Subscript avatar URL or icon */ secondaryAvatar: PropTypes.oneOfType([PropTypes.string, PropTypes.func]).isRequired, - /** Tooltip for the Avatar */ - avatarTooltips: PropTypes.arrayOf(PropTypes.string), + /** Tooltip for the main avatar */ + mainTooltip: PropTypes.string, + + /** Tooltip for the subscript avatar */ + secondaryTooltip: PropTypes.string, }; const defaultProps = { - avatarTooltips: [], + mainTooltip: '', + secondaryTooltip: '', }; const SubscriptAvatar = props => ( - + @@ -34,7 +38,7 @@ const SubscriptAvatar = props => ( - + firstName || Str.removeSMSDomain(login)) @@ -296,6 +296,8 @@ function createOption(personalDetailList, report, { alternateText, icons: getAvatarSources(report), tooltipText, + ownerEmail: lodashGet(report, ['ownerEmail']), + subtitle, participantsList: personalDetailList, // It doesn't make sense to provide a login in the case of a report with multiple participants since @@ -313,7 +315,10 @@ function createOption(personalDetailList, report, { iouReportID: lodashGet(report, 'iouReportID'), isIOUReportOwner: lodashGet(iouReport, 'ownerEmail', '') === currentUserLogin, iouReportAmount: lodashGet(iouReport, 'total', 0), + isChatRoom, + isArchivedRoom: ReportUtils.isArchivedRoom(report), shouldShowSubscript: isPolicyExpenseChat && !report.isOwnPolicyExpenseChat, + isPolicyExpenseChat, }; } diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js index bb9ef27f0d09..3cf7f0e56e3f 100644 --- a/src/pages/home/HeaderView.js +++ b/src/pages/home/HeaderView.js @@ -140,7 +140,8 @@ const HeaderView = (props) => { ) : ( { ) : ( { ? StyleUtils.getBackgroundAndBorderStyle(hoveredBackgroundColor) : undefined, ]} - avatarTooltips={avatarTooltips} + avatarTooltips={props.option.isPolicyExpenseChat ? [props.option.subtitle] : avatarTooltips} /> ) ) From 41115dd0e9b09544fb3787064c14b303538d19aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Tue, 1 Mar 2022 14:30:05 -0600 Subject: [PATCH 78/89] Update src/components/Avatar.js Co-authored-by: Rory Abraham <47436092+roryabraham@users.noreply.github.com> --- src/components/Avatar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Avatar.js b/src/components/Avatar.js index c08fa262fbca..4aa88b310ed1 100644 --- a/src/components/Avatar.js +++ b/src/components/Avatar.js @@ -11,7 +11,7 @@ import * as StyleUtils from '../styles/StyleUtils'; const propTypes = { - /** Source for the avatar. Can be the URL of an image or an icon. */ + /** Source for the avatar. Can be a URL or an icon. */ source: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), /** Extra styles to pass to Image */ From 34097c8f9f7843d322049b869ef3410700cd3d19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Tue, 1 Mar 2022 14:35:07 -0600 Subject: [PATCH 79/89] remove unnecessary View in SubscriptAvatar --- src/components/SubscriptAvatar.js | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/components/SubscriptAvatar.js b/src/components/SubscriptAvatar.js index 1084c58a8d43..8bb6274e1282 100644 --- a/src/components/SubscriptAvatar.js +++ b/src/components/SubscriptAvatar.js @@ -28,16 +28,12 @@ const defaultProps = { const SubscriptAvatar = props => ( - - - - - - + + + + Date: Tue, 1 Mar 2022 14:45:30 -0600 Subject: [PATCH 80/89] replace secondAvatarHovered with StyleUtils.getBackgroundAndBorderStyle --- src/components/MultipleAvatars.js | 3 ++- src/components/RoomHeaderAvatars.js | 3 ++- src/components/SubscriptAvatar.js | 3 ++- src/pages/home/HeaderView.js | 1 - src/styles/styles.js | 5 ----- 5 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/components/MultipleAvatars.js b/src/components/MultipleAvatars.js index 144d591185d2..681f2d5ae6c2 100644 --- a/src/components/MultipleAvatars.js +++ b/src/components/MultipleAvatars.js @@ -6,6 +6,7 @@ import Avatar from './Avatar'; import Tooltip from './Tooltip'; import Text from './Text'; import themeColors from '../styles/themes/default'; +import * as StyleUtils from '../styles/StyleUtils'; const propTypes = { /** Array of avatar URLs or icons */ @@ -25,7 +26,7 @@ const propTypes = { const defaultProps = { avatarIcons: [], size: 'default', - secondAvatarStyle: [styles.secondAvatarHovered], + secondAvatarStyle: [StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)], avatarTooltips: [], }; diff --git a/src/components/RoomHeaderAvatars.js b/src/components/RoomHeaderAvatars.js index 5791ead0602a..f9cf7351ae32 100644 --- a/src/components/RoomHeaderAvatars.js +++ b/src/components/RoomHeaderAvatars.js @@ -7,6 +7,7 @@ import Text from './Text'; import CONST from '../CONST'; import Avatar from './Avatar'; import themeColors from '../styles/themes/default'; +import * as StyleUtils from '../styles/StyleUtils'; const propTypes = { /** Array of avatar URLs or icons */ @@ -48,7 +49,7 @@ const RoomHeaderAvatars = (props) => { fill={themeColors.iconSuccessFill} /> - + ( source={props.mainAvatar} /> - + { ) : ( )} diff --git a/src/styles/styles.js b/src/styles/styles.js index 07fef1cfcec7..a2de25a4585b 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -1520,11 +1520,6 @@ const styles = { borderColor: 'transparent', }, - secondAvatarHovered: { - backgroundColor: themeColors.sidebarHover, - borderColor: themeColors.sidebarHover, - }, - secondAvatarSmall: { position: 'absolute', right: -13, From e3990d8873315a83bcaca6e8c00b0a1e7348187c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Tue, 1 Mar 2022 14:52:28 -0600 Subject: [PATCH 81/89] add missing displayName --- src/components/SubscriptAvatar.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/SubscriptAvatar.js b/src/components/SubscriptAvatar.js index b0fd552471ab..4c3a19392e44 100644 --- a/src/components/SubscriptAvatar.js +++ b/src/components/SubscriptAvatar.js @@ -47,6 +47,7 @@ const SubscriptAvatar = props => ( ); +SubscriptAvatar.displayName = 'SubscriptAvatar'; SubscriptAvatar.propTypes = propTypes; SubscriptAvatar.defaultProps = defaultProps; export default memo(SubscriptAvatar); From 5dc0073841c15dfef760e9875903a612b321d26c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Tue, 1 Mar 2022 15:06:26 -0600 Subject: [PATCH 82/89] get the first element of avatar sources in ReportDetailsPage --- src/pages/ReportDetailsPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/ReportDetailsPage.js b/src/pages/ReportDetailsPage.js index 9eb20e6f0117..589ac79a345f 100644 --- a/src/pages/ReportDetailsPage.js +++ b/src/pages/ReportDetailsPage.js @@ -134,7 +134,7 @@ class ReportDetailsPage extends Component { From 652a7d7ff9deb53600690d6c9fe0d306bde827b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Tue, 1 Mar 2022 17:32:46 -0600 Subject: [PATCH 83/89] change SubscriptAvatar size in #focus mode --- src/components/SubscriptAvatar.js | 6 ++++++ src/pages/home/sidebar/OptionRow.js | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/components/SubscriptAvatar.js b/src/components/SubscriptAvatar.js index 4c3a19392e44..d49845e6b967 100644 --- a/src/components/SubscriptAvatar.js +++ b/src/components/SubscriptAvatar.js @@ -1,6 +1,7 @@ import React, {memo} from 'react'; import PropTypes from 'prop-types'; import {View} from 'react-native'; +import _ from 'underscore'; import styles from '../styles/styles'; import Tooltip from './Tooltip'; import themeColors from '../styles/themes/default'; @@ -20,11 +21,15 @@ const propTypes = { /** Tooltip for the subscript avatar */ secondaryTooltip: PropTypes.string, + + /** Set the size of avatars */ + size: PropTypes.oneOf(_.values(CONST.AVATAR_SIZE)), }; const defaultProps = { mainTooltip: '', secondaryTooltip: '', + size: CONST.AVATAR_SIZE.DEFAULT, }; const SubscriptAvatar = props => ( @@ -32,6 +37,7 @@ const SubscriptAvatar = props => ( diff --git a/src/pages/home/sidebar/OptionRow.js b/src/pages/home/sidebar/OptionRow.js index d87ec7015ec9..f73dbbc41b46 100644 --- a/src/pages/home/sidebar/OptionRow.js +++ b/src/pages/home/sidebar/OptionRow.js @@ -22,6 +22,7 @@ import withLocalize, {withLocalizePropTypes} from '../../../components/withLocal import Text from '../../../components/Text'; import SelectCircle from '../../../components/SelectCircle'; import SubscriptAvatar from '../../../components/SubscriptAvatar'; +import CONST from '../../../CONST'; const propTypes = { /** Background Color of the Option Row */ @@ -170,11 +171,12 @@ const OptionRow = (props) => { secondaryAvatar={props.option.icons[1]} mainTooltip={props.option.ownerEmail} secondaryTooltip={props.option.subtitle} + size={props.mode === 'compact' ? CONST.AVATAR_SIZE.SMALL : CONST.AVATAR_SIZE.DEFAULT} /> ) : ( Date: Tue, 1 Mar 2022 17:35:16 -0600 Subject: [PATCH 84/89] use Avatar size const instead in MultipleAvatars --- src/components/MultipleAvatars.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/components/MultipleAvatars.js b/src/components/MultipleAvatars.js index 681f2d5ae6c2..993d36123c3a 100644 --- a/src/components/MultipleAvatars.js +++ b/src/components/MultipleAvatars.js @@ -1,19 +1,21 @@ import React, {memo} from 'react'; import PropTypes from 'prop-types'; import {Image, View} from 'react-native'; +import _ from 'underscore'; import styles from '../styles/styles'; import Avatar from './Avatar'; import Tooltip from './Tooltip'; import Text from './Text'; import themeColors from '../styles/themes/default'; import * as StyleUtils from '../styles/StyleUtils'; +import CONST from '../CONST'; const propTypes = { /** Array of avatar URLs or icons */ avatarIcons: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.func])), - /** Set the sie of avatars */ - size: PropTypes.oneOf(['default', 'small']), + /** Set the size of avatars */ + size: PropTypes.oneOf(_.values(CONST.AVATAR_SIZE)), /** Style for Second Avatar */ // eslint-disable-next-line react/forbid-prop-types @@ -25,16 +27,16 @@ const propTypes = { const defaultProps = { avatarIcons: [], - size: 'default', + size: CONST.AVATAR_SIZE.DEFAULT, secondAvatarStyle: [StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)], avatarTooltips: [], }; const MultipleAvatars = (props) => { - const avatarContainerStyles = props.size === 'small' ? styles.emptyAvatarSmall : styles.emptyAvatar; - const singleAvatarStyles = props.size === 'small' ? styles.singleAvatarSmall : styles.singleAvatar; + const avatarContainerStyles = props.size === CONST.AVATAR_SIZE.SMALL ? styles.emptyAvatarSmall : styles.emptyAvatar; + const singleAvatarStyles = props.size === CONST.AVATAR_SIZE.SMALL ? styles.singleAvatarSmall : styles.singleAvatar; const secondAvatarStyles = [ - props.size === 'small' ? styles.secondAvatarSmall : styles.secondAvatar, + props.size === CONST.AVATAR_SIZE.SMALL ? styles.secondAvatarSmall : styles.secondAvatar, ...props.secondAvatarStyle, ]; @@ -82,7 +84,7 @@ const MultipleAvatars = (props) => { - From b78492a2f8d0887a43fd27e3d5732c6fab13e3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Wed, 2 Mar 2022 13:39:28 -0600 Subject: [PATCH 85/89] create getAvatarStyle function and add SMALL_SUBSCRIPT size --- src/CONST.js | 1 + src/styles/StyleUtils.js | 17 +++++++++++++++++ src/styles/variables.js | 1 + 3 files changed, 19 insertions(+) diff --git a/src/CONST.js b/src/CONST.js index e4ba83359014..138b908a3af1 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -554,6 +554,7 @@ const CONST = { DEFAULT: 'default', SMALL: 'small', SUBSCRIPT: 'subscript', + SMALL_SUBSCRIPT: 'small-subscript', }, PHONE_MAX_LENGTH: 15, diff --git a/src/styles/StyleUtils.js b/src/styles/StyleUtils.js index 3a89b5463a93..1e587ca90871 100644 --- a/src/styles/StyleUtils.js +++ b/src/styles/StyleUtils.js @@ -16,6 +16,7 @@ import styles from './styles'; function getAvatarSize(size) { const AVATAR_SIZES = { [CONST.AVATAR_SIZE.DEFAULT]: variables.avatarSizeNormal, + [CONST.AVATAR_SIZE.SMALL_SUBSCRIPT]: variables.avatarSizeSmallSubscript, [CONST.AVATAR_SIZE.SUBSCRIPT]: variables.avatarSizeSubscript, [CONST.AVATAR_SIZE.SMALL]: variables.avatarSizeSmall, [CONST.AVATAR_SIZE.LARGE]: variables.avatarSizeLarge, @@ -23,6 +24,21 @@ function getAvatarSize(size) { return AVATAR_SIZES[size]; } +/** + * Return the style from an avatar size constant + * + * @param {String} size + * @returns {Object} + */ +function getAvatarStyle(size) { + const avatarSize = getAvatarSize(size); + return { + height: avatarSize, + width: avatarSize, + borderRadius: avatarSize, + }; +} + /** * Takes safe area insets and returns padding to use for a View * @@ -422,6 +438,7 @@ function parseStyleAsArray(styleParam) { export { getAvatarSize, + getAvatarStyle, getSafeAreaPadding, getSafeAreaMargins, getNavigationDrawerStyle, diff --git a/src/styles/variables.js b/src/styles/variables.js index c92ba7a9b557..5ffd6bf29131 100644 --- a/src/styles/variables.js +++ b/src/styles/variables.js @@ -12,6 +12,7 @@ export default { avatarSizeNormal: 40, avatarSizeSmall: 28, avatarSizeSubscript: 20, + avatarSizeSmallSubscript: 14, fontSizeSingleEmoji: 30, fontSizeSingleEmojiHeight: 35, fontSizeSmall: 11, From 565cf0c6165d24eeaf6c56543d4a95dd35344c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Wed, 2 Mar 2022 13:40:15 -0600 Subject: [PATCH 86/89] use StyleUtils.getAvatarStyle in Avatar --- src/components/Avatar.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/Avatar.js b/src/components/Avatar.js index 4aa88b310ed1..fd3571ab4a9e 100644 --- a/src/components/Avatar.js +++ b/src/components/Avatar.js @@ -2,7 +2,6 @@ import React, {PureComponent} from 'react'; import {Image, View} from 'react-native'; import PropTypes from 'prop-types'; import _ from 'underscore'; -import styles from '../styles/styles'; import stylePropTypes from '../styles/stylePropTypes'; import Icon from './Icon'; import themeColors from '../styles/themes/default'; @@ -42,7 +41,7 @@ class Avatar extends PureComponent { } const imageStyle = [ - this.props.size === CONST.AVATAR_SIZE.SMALL ? styles.avatarSmall : styles.avatarNormal, + StyleUtils.getAvatarStyle(this.props.size), ...this.props.imageStyles, ]; From 3f66b17318a623003f9aa35001aa9b90289771b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ch=C3=A1vez?= Date: Wed, 2 Mar 2022 13:51:10 -0600 Subject: [PATCH 87/89] create OPTION_MODE and replace string literals --- src/CONST.js | 5 ++++- src/components/OptionsList/optionsListPropTypes.js | 4 +++- src/pages/home/sidebar/OptionRow.js | 14 +++++++------- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/CONST.js b/src/CONST.js index 138b908a3af1..4f05bc37e770 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -556,7 +556,10 @@ const CONST = { SUBSCRIPT: 'subscript', SMALL_SUBSCRIPT: 'small-subscript', }, - + OPTION_MODE: { + COMPACT: 'compact', + DEFAULT: 'default', + }, PHONE_MAX_LENGTH: 15, PHONE_MIN_LENGTH: 5, REGEX: { diff --git a/src/components/OptionsList/optionsListPropTypes.js b/src/components/OptionsList/optionsListPropTypes.js index 4ca0cf3ab4f9..7b2e20c8828c 100644 --- a/src/components/OptionsList/optionsListPropTypes.js +++ b/src/components/OptionsList/optionsListPropTypes.js @@ -1,7 +1,9 @@ import PropTypes from 'prop-types'; +import _ from 'underscore'; import SectionList from '../SectionList'; import styles from '../../styles/styles'; import optionPropTypes from '../optionPropTypes'; +import CONST from '../../CONST'; const propTypes = { /** option Background Color */ @@ -69,7 +71,7 @@ const propTypes = { showTitleTooltip: PropTypes.bool, /** Toggle between compact and default view of the option */ - optionMode: PropTypes.oneOf(['compact', 'default']), + optionMode: PropTypes.oneOf(_.values(CONST.OPTION_MODE)), /** Whether to disable the interactivity of the list's option row(s) */ disableRowInteractivity: PropTypes.bool, diff --git a/src/pages/home/sidebar/OptionRow.js b/src/pages/home/sidebar/OptionRow.js index f73dbbc41b46..41ffa5d96b26 100644 --- a/src/pages/home/sidebar/OptionRow.js +++ b/src/pages/home/sidebar/OptionRow.js @@ -57,7 +57,7 @@ const propTypes = { showTitleTooltip: PropTypes.bool, /** Toggle between compact and default view */ - mode: PropTypes.oneOf(['compact', 'default']), + mode: PropTypes.oneOf(_.values(CONST.OPTION_MODE)), /** Whether this option should be disabled */ isDisabled: PropTypes.bool, @@ -89,16 +89,16 @@ const OptionRow = (props) => { : styles.sidebarLinkText; const textUnreadStyle = (props.option.isUnread || props.forceTextUnreadStyle) ? [textStyle, styles.sidebarLinkTextUnread] : [textStyle]; - const displayNameStyle = props.mode === 'compact' + const displayNameStyle = props.mode === CONST.OPTION_MODE.COMPACT ? [styles.optionDisplayName, ...textUnreadStyle, styles.optionDisplayNameCompact, styles.mr2] : [styles.optionDisplayName, ...textUnreadStyle]; - const alternateTextStyle = props.mode === 'compact' + const alternateTextStyle = props.mode === CONST.OPTION_MODE.COMPACT ? [textStyle, styles.optionAlternateText, styles.textLabelSupporting, styles.optionAlternateTextCompact] : [textStyle, styles.optionAlternateText, styles.textLabelSupporting]; - const contentContainerStyles = props.mode === 'compact' + const contentContainerStyles = props.mode === CONST.OPTION_MODE.COMPACT ? [styles.flex1, styles.flexRow, styles.overflowHidden, styles.alignItemsCenter] : [styles.flex1]; - const sidebarInnerRowStyle = StyleSheet.flatten(props.mode === 'compact' ? [ + const sidebarInnerRowStyle = StyleSheet.flatten(props.mode === CONST.OPTION_MODE.COMPACT ? [ styles.chatLinkRowPressable, styles.flexGrow1, styles.optionItemAvatarNameWrapper, @@ -171,12 +171,12 @@ const OptionRow = (props) => { secondaryAvatar={props.option.icons[1]} mainTooltip={props.option.ownerEmail} secondaryTooltip={props.option.subtitle} - size={props.mode === 'compact' ? CONST.AVATAR_SIZE.SMALL : CONST.AVATAR_SIZE.DEFAULT} + size={props.mode === CONST.OPTION_MODE.COMPACT ? CONST.AVATAR_SIZE.SMALL : CONST.AVATAR_SIZE.DEFAULT} /> ) : ( Date: Wed, 2 Mar 2022 13:59:31 -0600 Subject: [PATCH 88/89] add mode to SubscriptAvatar and secondAvatarSubscriptCompact style --- src/components/SubscriptAvatar.js | 14 ++++++++------ src/pages/home/sidebar/OptionRow.js | 2 +- src/styles/styles.js | 19 ++++++++++++++----- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/components/SubscriptAvatar.js b/src/components/SubscriptAvatar.js index d49845e6b967..55462e999b49 100644 --- a/src/components/SubscriptAvatar.js +++ b/src/components/SubscriptAvatar.js @@ -23,13 +23,13 @@ const propTypes = { secondaryTooltip: PropTypes.string, /** Set the size of avatars */ - size: PropTypes.oneOf(_.values(CONST.AVATAR_SIZE)), + mode: PropTypes.oneOf(_.values(CONST.OPTION_MODE)), }; const defaultProps = { mainTooltip: '', secondaryTooltip: '', - size: CONST.AVATAR_SIZE.DEFAULT, + mode: CONST.OPTION_MODE.DEFAULT, }; const SubscriptAvatar = props => ( @@ -37,15 +37,17 @@ const SubscriptAvatar = props => ( - + diff --git a/src/pages/home/sidebar/OptionRow.js b/src/pages/home/sidebar/OptionRow.js index 41ffa5d96b26..159f722b6208 100644 --- a/src/pages/home/sidebar/OptionRow.js +++ b/src/pages/home/sidebar/OptionRow.js @@ -171,7 +171,7 @@ const OptionRow = (props) => { secondaryAvatar={props.option.icons[1]} mainTooltip={props.option.ownerEmail} secondaryTooltip={props.option.subtitle} - size={props.mode === CONST.OPTION_MODE.COMPACT ? CONST.AVATAR_SIZE.SMALL : CONST.AVATAR_SIZE.DEFAULT} + mode={props.mode} /> ) : ( Date: Wed, 2 Mar 2022 14:09:35 -0600 Subject: [PATCH 89/89] set emptyAvatarSmall and update style for subscript avatar --- src/components/SubscriptAvatar.js | 2 +- src/styles/styles.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/SubscriptAvatar.js b/src/components/SubscriptAvatar.js index 55462e999b49..61c007b00c2d 100644 --- a/src/components/SubscriptAvatar.js +++ b/src/components/SubscriptAvatar.js @@ -33,7 +33,7 @@ const defaultProps = { }; const SubscriptAvatar = props => ( - +