Fix mutation in CallingParticipantList component

This commit is contained in:
Evan Hahn 2020-12-03 11:24:44 -06:00 committed by GitHub
parent 7aaa5ab294
commit 511ad14137
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 45 additions and 6 deletions

View file

@ -10,6 +10,7 @@ import { ContactName } from './conversation/ContactName';
import { InContactsIcon } from './InContactsIcon';
import { LocalizerType } from '../types/Util';
import { GroupCallPeekedParticipantType } from '../types/Calling';
import { sortByTitle } from '../util/sortByTitle';
interface ParticipantType extends GroupCallPeekedParticipantType {
hasAudio?: boolean;
@ -27,7 +28,7 @@ export const CallingParticipantsList = React.memo(
const [root, setRoot] = React.useState<HTMLElement | null>(null);
const sortedParticipants = React.useMemo<Array<ParticipantType>>(
() => participants.sort((a, b) => a.title.localeCompare(b.title)),
() => sortByTitle(participants),
[participants]
);

View file

@ -6,6 +6,7 @@ import classNames from 'classnames';
import { LocalizerType } from '../types/Util';
import { ConversationType } from '../state/ducks/conversations';
import { Avatar } from './Avatar';
import { sortByTitle } from '../util/sortByTitle';
export type ActionSpec = {
text: string;
@ -36,10 +37,6 @@ function focusRef(el: HTMLElement | null) {
}
}
function sort(list: Array<ConversationType>): Array<ConversationType> {
return [...list].sort((a, b) => a.title.localeCompare(b.title));
}
export const GroupV1MigrationDialog = React.memo((props: PropsType) => {
const {
areWeInvited,
@ -172,7 +169,7 @@ function renderMembers(
<div className="module-group-v2-migration-dialog__item__bullet" />
<div className="module-group-v2-migration-dialog__item__content">
<div>{i18n(key)}</div>
{sort(members).map(member => (
{sortByTitle(members).map(member => (
<div
key={member.id}
className="module-group-v2-migration-dialog__member"

View file

@ -0,0 +1,29 @@
// Copyright 2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { assert } from 'chai';
import { sortByTitle } from '../../util/sortByTitle';
describe('sortByTitle', () => {
it("does nothing to arrays that don't need to be sorted", () => {
assert.deepEqual(sortByTitle([]), []);
assert.deepEqual(sortByTitle([{ title: 'foo' }]), [{ title: 'foo' }]);
});
it('sorts the array by title', () => {
// Because the function relies on locale-aware comparisons, we don't have very
// thorough tests here, as it can change based on platform.
assert.deepEqual(sortByTitle([{ title: 'foo' }, { title: 'bar' }]), [
{ title: 'bar' },
{ title: 'foo' },
]);
});
it("doesn't mutate its argument", () => {
const arr = [{ title: 'foo' }, { title: 'bar' }];
sortByTitle(arr);
assert.deepEqual(arr, [{ title: 'foo' }, { title: 'bar' }]);
});
});

12
ts/util/sortByTitle.ts Normal file
View file

@ -0,0 +1,12 @@
// Copyright 2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
interface HasTitle {
title: string;
}
export function sortByTitle<T extends HasTitle>(
arr: ReadonlyArray<T>
): Array<T> {
return [...arr].sort((a, b) => a.title.localeCompare(b.title));
}