Sort contacts and conversations alphabetically when composing message

This commit is contained in:
trevor-signal 2023-06-21 12:33:59 -04:00 committed by GitHub
parent 65b6d9c2bc
commit 83c1acedd8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 87 additions and 12 deletions

View file

@ -30,7 +30,10 @@ import { deconstructLookup } from '../../util/deconstructLookup';
import type { PropsDataType as TimelinePropsType } from '../../components/conversation/Timeline';
import { assertDev } from '../../util/assert';
import { isConversationUnregistered } from '../../util/isConversationUnregistered';
import { filterAndSortConversationsByRecent } from '../../util/filterAndSortConversations';
import {
filterAndSortConversationsAlphabetically,
filterAndSortConversationsByRecent,
} from '../../util/filterAndSortConversations';
import type { ContactNameColorType } from '../../types/Colors';
import { ContactNameColors } from '../../types/Colors';
import type { AvatarDataType } from '../../types/Avatar';
@ -648,7 +651,11 @@ export const getFilteredComposeContacts = createSelector(
contacts: ReadonlyArray<ConversationType>,
regionCode: string | undefined
): Array<ConversationType> => {
return filterAndSortConversationsByRecent(contacts, searchTerm, regionCode);
return filterAndSortConversationsAlphabetically(
contacts,
searchTerm,
regionCode
);
}
);
@ -667,7 +674,7 @@ export const getFilteredComposeGroups = createSelector(
memberships: ReadonlyArray<unknown>;
}
> => {
return filterAndSortConversationsByRecent(
return filterAndSortConversationsAlphabetically(
groups,
searchTerm,
regionCode

View file

@ -923,10 +923,10 @@ describe('both/state/selectors/conversations-extra', () => {
const ids = result.map(contact => contact.id);
assert.deepEqual(ids, [
'our-conversation-id',
'convo-1',
'convo-5',
'convo-6',
'our-conversation-id',
]);
});

View file

@ -4,16 +4,19 @@
import { assert } from 'chai';
import { getDefaultConversation } from '../helpers/getDefaultConversation';
import { filterAndSortConversationsByRecent } from '../../util/filterAndSortConversations';
import {
filterAndSortConversationsAlphabetically,
filterAndSortConversationsByRecent,
} from '../../util/filterAndSortConversations';
describe('filterAndSortConversationsByRecent', () => {
describe('filterAndSortConversations', () => {
const conversations = [
getDefaultConversation({
title: '+16505551234',
activeAt: 1,
}),
getDefaultConversation({
title: 'Abraham Lincoln',
title: 'The Abraham Lincoln Club',
activeAt: 4,
}),
getDefaultConversation({
@ -33,22 +36,50 @@ describe('filterAndSortConversationsByRecent', () => {
}),
];
it('sorts by recency when no search term is provided', () => {
it('filterAndSortConversationsByRecent sorts by recency when no search term is provided', () => {
const titles = filterAndSortConversationsByRecent(
conversations,
'',
'US'
).map(contact => contact.title);
assert.sameMembers(titles, [
'+16505551234',
'George Washington',
assert.sameOrderedMembers(titles, [
'The Abraham Lincoln Club',
'Boxing Club',
'Abraham Lincoln',
'George Washington',
'+16505551234',
'Not recent',
'A long long long title ending with burrito',
]);
});
it('filterAndSortConversationsAlphabetically sorts by title when no search term is provided', () => {
const titles = filterAndSortConversationsAlphabetically(
conversations,
'',
'US'
).map(contact => contact.title);
assert.sameOrderedMembers(titles, [
'A long long long title ending with burrito',
'Boxing Club',
'George Washington',
'Not recent',
'The Abraham Lincoln Club',
'+16505551234',
]);
});
it('filterAndSortConversationsAlphabetically sorts by title when a search term is provided', () => {
const titles = filterAndSortConversationsAlphabetically(
conversations,
'club',
'US'
).map(contact => contact.title);
assert.sameOrderedMembers(titles, [
'Boxing Club',
'The Abraham Lincoln Club',
]);
});
it('finds a conversation when the search term is at the end of a long title', () => {
const titles = filterAndSortConversationsByRecent(
conversations,

View file

@ -163,3 +163,40 @@ export function filterAndSortConversationsByRecent(
return a.activeAt && !b.activeAt ? -1 : 1;
});
}
function startsWithLetter(title: string) {
// Uses \p, the unicode character class escape, to check if a the first character is a
// letter
return /^\p{Letter}/u.test(title);
}
function sortAlphabetically(a: ConversationType, b: ConversationType) {
// Sort alphabetically with conversations starting with a letter first (and phone
// numbers last)
const aStartsWithLetter = startsWithLetter(a.title);
const bStartsWithLetter = startsWithLetter(b.title);
if (aStartsWithLetter && !bStartsWithLetter) {
return -1;
}
if (!aStartsWithLetter && bStartsWithLetter) {
return 1;
}
return a.title.localeCompare(b.title);
}
export function filterAndSortConversationsAlphabetically(
conversations: ReadonlyArray<ConversationType>,
searchTerm: string,
regionCode: string | undefined
): Array<ConversationType> {
if (searchTerm.length) {
const withoutUnknown = conversations.filter(item => item.titleNoDefault);
return searchConversations(withoutUnknown, searchTerm, regionCode)
.slice()
.map(result => result.item)
.sort(sortAlphabetically);
}
return conversations.concat().sort(sortAlphabetically);
}