Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix - Feature Request: Add '...' to the end of names at the top of group chats if there are more members in the room #57752

1 change: 1 addition & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1663,6 +1663,7 @@ const CONST = {
EMOJI_NUM_PER_ROW: 8,

EMOJI_DEFAULT_SKIN_TONE: -1,
DISPLAY_PARTICIPANTS_LIMIT: 5,

// Amount of emojis to render ahead at the end of the update cycle
EMOJI_DRAW_AMOUNT: 250,
Expand Down
15 changes: 12 additions & 3 deletions src/components/DisplayNames/DisplayNamesWithTooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,21 @@ import {View} from 'react-native';
import Text from '@components/Text';
import Tooltip from '@components/Tooltip';
import useThemeStyles from '@hooks/useThemeStyles';
import * as ReportUtils from '@libs/ReportUtils';
import {formatReportLastMessageText} from '@libs/ReportUtils';
import DisplayNamesTooltipItem from './DisplayNamesTooltipItem';
import type DisplayNamesProps from './types';

type HTMLElementWithText = HTMLElement & RNText;

function DisplayNamesWithToolTip({shouldUseFullTitle, fullTitle, displayNamesWithTooltips, textStyles = [], numberOfLines = 1, renderAdditionalText}: DisplayNamesProps) {
function DisplayNamesWithToolTip({
shouldUseFullTitle,
fullTitle,
displayNamesWithTooltips,
shouldAddEllipsis = false,
textStyles = [],
numberOfLines = 1,
renderAdditionalText,
}: DisplayNamesProps) {
const styles = useThemeStyles();
const containerRef = useRef<HTMLElementWithText>(null);
const childRefs = useRef<HTMLElementWithText[]>([]);
Expand Down Expand Up @@ -57,7 +65,7 @@ function DisplayNamesWithToolTip({shouldUseFullTitle, fullTitle, displayNamesWit
testID={DisplayNamesWithToolTip.displayName}
>
{shouldUseFullTitle
? ReportUtils.formatReportLastMessageText(fullTitle)
? formatReportLastMessageText(fullTitle)
: displayNamesWithTooltips?.map(({displayName, accountID, avatar, login}, index) => (
// eslint-disable-next-line react/no-array-index-key
<Fragment key={index}>
Expand All @@ -72,6 +80,7 @@ function DisplayNamesWithToolTip({shouldUseFullTitle, fullTitle, displayNamesWit
childRefs={childRefs}
/>
{index < displayNamesWithTooltips.length - 1 && <Text style={textStyles}>,&nbsp;</Text>}
{shouldAddEllipsis && index === displayNamesWithTooltips.length - 1 && <Text style={textStyles}>...</Text>}
</Fragment>
))}
{renderAdditionalText?.()}
Expand Down
3 changes: 2 additions & 1 deletion src/components/DisplayNames/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import DisplayNamesWithoutTooltip from './DisplayNamesWithoutTooltip';
import DisplayNamesWithToolTip from './DisplayNamesWithTooltip';
import type DisplayNamesProps from './types';

function DisplayNames({fullTitle, tooltipEnabled, textStyles, numberOfLines, shouldUseFullTitle, displayNamesWithTooltips, renderAdditionalText}: DisplayNamesProps) {
function DisplayNames({fullTitle, tooltipEnabled, textStyles, numberOfLines, shouldAddEllipsis, shouldUseFullTitle, displayNamesWithTooltips, renderAdditionalText}: DisplayNamesProps) {
const {translate} = useLocalize();
const title = fullTitle || translate('common.hidden');

Expand Down Expand Up @@ -36,6 +36,7 @@ function DisplayNames({fullTitle, tooltipEnabled, textStyles, numberOfLines, sho
fullTitle={title}
displayNamesWithTooltips={displayNamesWithTooltips}
textStyles={textStyles}
shouldAddEllipsis={shouldAddEllipsis}
numberOfLines={numberOfLines}
renderAdditionalText={renderAdditionalText}
/>
Expand Down
3 changes: 3 additions & 0 deletions src/components/DisplayNames/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ type DisplayNamesProps = {
/** If the full title needs to be displayed */
shouldUseFullTitle?: boolean;

/** If we should add an ellipsis after the participants list */
shouldAddEllipsis?: boolean;

/** Additional Text component to render after the displayNames */
renderAdditionalText?: () => React.ReactNode;
};
Expand Down
6 changes: 4 additions & 2 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2602,8 +2602,9 @@ function getGroupChatName(participants?: SelectedParticipant[], shouldApplyLimit
Object.keys(report?.participants ?? {})
.map(Number)
.filter((accountID) => !pendingMemberAccountIDs.has(accountID.toString()));
const shouldAddEllipsis = participantAccountIDs.length > CONST.DISPLAY_PARTICIPANTS_LIMIT && shouldApplyLimit;
if (shouldApplyLimit) {
participantAccountIDs = participantAccountIDs.slice(0, 5);
participantAccountIDs = participantAccountIDs.slice(0, CONST.DISPLAY_PARTICIPANTS_LIMIT);
}
const isMultipleParticipantReport = participantAccountIDs.length > 1;

Expand All @@ -2616,7 +2617,8 @@ function getGroupChatName(participants?: SelectedParticipant[], shouldApplyLimit
.sort((first, second) => localeCompare(first ?? '', second ?? ''))
.filter(Boolean)
.join(', ')
.slice(0, CONST.REPORT_NAME_LIMIT);
.slice(0, CONST.REPORT_NAME_LIMIT)
.concat(shouldAddEllipsis ? '...' : '');
}

return translateLocal('groupChat.defaultReportName', {displayName: getDisplayNameForParticipant({accountID: participantAccountIDs.at(0)})});
Expand Down
5 changes: 4 additions & 1 deletion src/pages/home/HeaderView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@ function HeaderView({report, parentReportAction, onNavigationMenuButtonClicked,
const isSelfDM = isSelfDMReportUtils(report);
const isGroupChat = isGroupChatReportUtils(report) || isDeprecatedGroupDM(report);

const participants = getParticipantsAccountIDsForDisplay(report, false, true).slice(0, 5);
const allParticipants = getParticipantsAccountIDsForDisplay(report, false, true);
const shouldAddEllipsis = allParticipants?.length > CONST.DISPLAY_PARTICIPANTS_LIMIT;
const participants = allParticipants.slice(0, CONST.DISPLAY_PARTICIPANTS_LIMIT);
const isMultipleParticipant = participants.length > 1;

const participantPersonalDetails = getPersonalDetailsForAccountIDs(participants, personalDetails);
Expand Down Expand Up @@ -293,6 +295,7 @@ function HeaderView({report, parentReportAction, onNavigationMenuButtonClicked,
textStyles={[styles.headerText, styles.pre]}
shouldUseFullTitle={isChatRoom || isPolicyExpenseChat || isChatThread || isTaskReport || shouldUseGroupTitle}
renderAdditionalText={renderAdditionalText}
shouldAddEllipsis={shouldAddEllipsis}
/>
</CaretWrapper>
{!isEmptyObject(parentNavigationSubtitleData) && (
Expand Down
10 changes: 5 additions & 5 deletions tests/ui/GroupChatNameTests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ describe('Tests for group chat name', () => {
return waitFor(() => expect(displayNameText?.props?.children?.[0]).toBe('A, B, C, D'));
}));

it('Should show limited names in LHN when 8 participants are present', () =>
it('Should show limited names with ellipsis in LHN when 8 participants are present', () =>
signInAndGetApp('', participantAccountIDs8).then(() => {
// Verify the sidebar links are rendered
const sidebarLinksHintText = translateLocal('sidebarScreen.listOfChats');
Expand All @@ -191,7 +191,7 @@ describe('Tests for group chat name', () => {
const displayNameHintText = translateLocal('accessibilityHints.chatUserDisplayNames');
const displayNameText = screen.queryByLabelText(displayNameHintText);

return waitFor(() => expect(displayNameText?.props?.children?.[0]).toBe('A, B, C, D, E'));
return waitFor(() => expect(displayNameText?.props?.children?.[0]).toBe('A, B, C, D, E...'));
}));

it('Check if group name shows fine for report header', () =>
Expand Down Expand Up @@ -222,7 +222,7 @@ describe('Tests for group chat name', () => {
return waitFor(() => expect(displayNameTexts).toHaveLength(1));
}));

it('Should show only 5 names when there are 8 participants in the report header', () =>
it('Should show only 5 names with ellipsis when there are 8 participants in the report header', () =>
signInAndGetApp('', participantAccountIDs8)
.then(() => {
// Verify the sidebar links are rendered
Expand All @@ -238,14 +238,14 @@ describe('Tests for group chat name', () => {
const displayNameHintText = translateLocal('accessibilityHints.chatUserDisplayNames');
const displayNameText = screen.queryByLabelText(displayNameHintText);

expect(displayNameText?.props?.children?.[0]).toBe('A, B, C, D, E');
expect(displayNameText?.props?.children?.[0]).toBe('A, B, C, D, E...');

return navigateToSidebarOption(0);
})
.then(waitForBatchedUpdates)
.then(async () => {
await act(() => transitionEndCB?.());
const name = 'A, B, C, D, E';
const name = 'A, B, C, D, E...';
const displayNameTexts = screen.queryAllByLabelText(name);
return waitFor(() => expect(displayNameTexts).toHaveLength(1));
}));
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/ReportUtilsTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1321,9 +1321,9 @@ describe('ReportUtils', () => {
expect(getGroupChatName(fourParticipants)).toEqual('Four, One, Three, Two');
});

it('Should show 5 participants name if count > 5 and shouldApplyLimit is true', async () => {
it('Should show 5 participants name with ellipsis if count > 5 and shouldApplyLimit is true', async () => {
await Onyx.merge(ONYXKEYS.PERSONAL_DETAILS_LIST, fakePersonalDetails);
expect(getGroupChatName(eightParticipants, true)).toEqual('Five, Four, One, Three, Two');
expect(getGroupChatName(eightParticipants, true)).toEqual('Five, Four, One, Three, Two...');
});

it('Should show all participants name if count > 5 and shouldApplyLimit is false', async () => {
Expand Down