diff --git a/src/components/LHNOptionsList/OptionRowLHN.js b/src/components/LHNOptionsList/OptionRowLHN.js index ba035c8b3baf..05cb5a8233a2 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.js +++ b/src/components/LHNOptionsList/OptionRowLHN.js @@ -154,6 +154,10 @@ function OptionRowLHN(props) { const statusContent = formattedDate ? `${statusText} (${formattedDate})` : statusText; const isStatusVisible = Permissions.canUseCustomStatus(props.betas) && !!emojiCode && ReportUtils.isOneOnOneChat(optionItem); + const isGroupChat = + optionItem.type === CONST.REPORT.TYPE.CHAT && _.isEmpty(optionItem.chatType) && !optionItem.isThread && lodashGet(optionItem, 'displayNamesWithTooltips.length', 0) > 2; + const fullTitle = isGroupChat ? ReportUtils.getDisplayNamesStringFromTooltips(optionItem.displayNamesWithTooltips) : optionItem.text; + return ( { - const accountID = Number(user.accountID); - const displayName = getDisplayNameForParticipant(accountID, isMultipleParticipantReport) || user.login || ''; - const avatar = UserUtils.getDefaultAvatar(accountID); - - let pronouns = user.pronouns; - if (pronouns && pronouns.startsWith(CONST.PRONOUNS.PREFIX)) { - const pronounTranslationKey = pronouns.replace(CONST.PRONOUNS.PREFIX, ''); - pronouns = Localize.translateLocal(`pronouns.${pronounTranslationKey}`); - } + return _.chain(personalDetailsList) + .map((user) => { + const accountID = Number(user.accountID); + const displayName = getDisplayNameForParticipant(accountID, isMultipleParticipantReport) || user.login || ''; + const avatar = UserUtils.getDefaultAvatar(accountID); + + let pronouns = user.pronouns; + if (pronouns && pronouns.startsWith(CONST.PRONOUNS.PREFIX)) { + const pronounTranslationKey = pronouns.replace(CONST.PRONOUNS.PREFIX, ''); + pronouns = Localize.translateLocal(`pronouns.${pronounTranslationKey}`); + } - return { - displayName, - avatar, - login: user.login || '', - accountID, - pronouns, - }; - }); + return { + displayName, + avatar, + login: user.login || '', + accountID, + pronouns, + }; + }) + .sort((first, second) => { + // First sort by displayName/login + const displayNameLoginOrder = first.displayName.localeCompare(second.displayName); + if (displayNameLoginOrder !== 0) { + return displayNameLoginOrder; + } + + // Then fallback on accountID as the final sorting criteria. + return first.accountID > second.accountID; + }) + .value(); +} + +/** + * Gets a joined string of display names from the list of display name with tooltip objects. + * + * @param {Object} displayNamesWithTooltips + * @returns {String} + */ +function getDisplayNamesStringFromTooltips(displayNamesWithTooltips) { + return _.filter( + _.map(displayNamesWithTooltips, ({displayName}) => displayName), + (displayName) => !_.isEmpty(displayName), + ).join(', '); } /** @@ -4038,6 +4063,32 @@ function getIOUReportActionDisplayMessage(reportAction) { return displayMessage; } +/** + * Checks if a report is a group chat. + * + * A report is a group chat if it meets the following conditions: + * - Not a chat thread. + * - Not a task report. + * - Not a money request / IOU report. + * - Not an archived room. + * - Not a public / admin / announce chat room (chat type doesn't match any of the specified types). + * - More than 2 participants. + * + * @param {Object} report + * @returns {Boolean} + */ +function isGroupChat(report) { + return ( + report && + !isChatThread(report) && + !isTaskReport(report) && + !isMoneyRequestReport(report) && + !isArchivedRoom(report) && + !Object.values(CONST.REPORT.CHAT_TYPE).includes(getChatType(report)) && + lodashGet(report, 'participantAccountIDs.length', 0) > 2 + ); +} + /** * @param {Object} report * @returns {Boolean} @@ -4098,6 +4149,7 @@ export { getIcons, getRoomWelcomeMessage, getDisplayNamesWithTooltips, + getDisplayNamesStringFromTooltips, getReportName, getReport, getReportIDFromLink, @@ -4204,6 +4256,7 @@ export { hasMissingSmartscanFields, getIOUReportActionDisplayMessage, isWaitingForTaskCompleteFromAssignee, + isGroupChat, isReportDraft, shouldUseFullTitleToDisplay, parseReportRouteParams, diff --git a/src/pages/home/HeaderView.js b/src/pages/home/HeaderView.js index 8ddbf066a774..5557ed1e73c8 100644 --- a/src/pages/home/HeaderView.js +++ b/src/pages/home/HeaderView.js @@ -80,7 +80,8 @@ function HeaderView(props) { const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(props.report); const isTaskReport = ReportUtils.isTaskReport(props.report); const reportHeaderData = !isTaskReport && !isChatThread && props.report.parentReportID ? props.parentReport : props.report; - const title = ReportUtils.getReportName(reportHeaderData); + // Use sorted display names for the title for group chats on native small screen widths + const title = ReportUtils.isGroupChat(props.report) ? ReportUtils.getDisplayNamesStringFromTooltips(displayNamesWithTooltips) : ReportUtils.getReportName(reportHeaderData); const subtitle = ReportUtils.getChatRoomSubtitle(reportHeaderData); const parentNavigationSubtitleData = ReportUtils.getParentNavigationSubtitle(reportHeaderData); const isConcierge = ReportUtils.hasSingleParticipant(props.report) && _.contains(participants, CONST.ACCOUNT_ID.CONCIERGE); diff --git a/tests/unit/ReportUtilsTest.js b/tests/unit/ReportUtilsTest.js index 25f093cbd711..26257b469939 100644 --- a/tests/unit/ReportUtilsTest.js +++ b/tests/unit/ReportUtilsTest.js @@ -84,11 +84,8 @@ describe('ReportUtils', () => { const participants = ReportUtils.getDisplayNamesWithTooltips(participantsPersonalDetails, false); expect(participants).toHaveLength(5); - expect(participants[0].avatar).toBeInstanceOf(Function); - expect(participants[0].displayName).toBe('Ragnar Lothbrok'); - expect(participants[0].login).toBe('ragnar@vikings.net'); - expect(participants[0].accountID).toBe(1); - expect(participants[0].pronouns).toBeUndefined(); + expect(participants[0].displayName).toBe('(833) 240-3627'); + expect(participants[0].login).toBe('+18332403627@expensify.sms'); expect(participants[2].avatar).toBeInstanceOf(Function); expect(participants[2].displayName).toBe('Lagertha Lothbrok'); @@ -96,8 +93,11 @@ describe('ReportUtils', () => { expect(participants[2].accountID).toBe(3); expect(participants[2].pronouns).toBe('She/her'); - expect(participants[3].displayName).toBe('(833) 240-3627'); - expect(participants[3].login).toBe('+18332403627@expensify.sms'); + expect(participants[4].avatar).toBeInstanceOf(Function); + expect(participants[4].displayName).toBe('Ragnar Lothbrok'); + expect(participants[4].login).toBe('ragnar@vikings.net'); + expect(participants[4].accountID).toBe(1); + expect(participants[4].pronouns).toBeUndefined(); }); });