Skip to content

Commit

Permalink
Merge pull request #28991 from akinwale/task-28048-2
Browse files Browse the repository at this point in the history
fix: sort header display names and avatars in a group chat view
  • Loading branch information
stitesExpensify authored Oct 23, 2023
2 parents 2299ab8 + e5662c3 commit 55f86ce
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 27 deletions.
6 changes: 5 additions & 1 deletion src/components/LHNOptionsList/OptionRowLHN.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<OfflineWithFeedback
pendingAction={optionItem.pendingAction}
Expand Down Expand Up @@ -233,7 +237,7 @@ function OptionRowLHN(props) {
<View style={[styles.flexRow, styles.alignItemsCenter, styles.mw100, styles.overflowHidden]}>
<DisplayNames
accessibilityLabel={translate('accessibilityHints.chatUserDisplayNames')}
fullTitle={optionItem.text}
fullTitle={fullTitle}
displayNamesWithTooltips={optionItem.displayNamesWithTooltips}
tooltipEnabled
numberOfLines={1}
Expand Down
89 changes: 71 additions & 18 deletions src/libs/ReportUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -1208,25 +1208,50 @@ function getDisplayNameForParticipant(accountID, shouldUseShortForm = false) {
* @returns {Array}
*/
function getDisplayNamesWithTooltips(personalDetailsList, isMultipleParticipantReport) {
return _.map(personalDetailsList, (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 _.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(', ');
}

/**
Expand Down Expand Up @@ -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}
Expand Down Expand Up @@ -4098,6 +4149,7 @@ export {
getIcons,
getRoomWelcomeMessage,
getDisplayNamesWithTooltips,
getDisplayNamesStringFromTooltips,
getReportName,
getReport,
getReportIDFromLink,
Expand Down Expand Up @@ -4204,6 +4256,7 @@ export {
hasMissingSmartscanFields,
getIOUReportActionDisplayMessage,
isWaitingForTaskCompleteFromAssignee,
isGroupChat,
isReportDraft,
shouldUseFullTitleToDisplay,
parseReportRouteParams,
Expand Down
3 changes: 2 additions & 1 deletion src/pages/home/HeaderView.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
14 changes: 7 additions & 7 deletions tests/unit/ReportUtilsTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,20 +84,20 @@ 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');
expect(participants[2].login).toBe('lagertha@vikings.net');
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();
});
});

Expand Down

0 comments on commit 55f86ce

Please sign in to comment.