Fix mutation in CallingParticipantList component
This commit is contained in:
parent
7aaa5ab294
commit
511ad14137
4 changed files with 45 additions and 6 deletions
|
@ -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]
|
||||
);
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
29
ts/test/util/sortByTitle_test.ts
Normal file
29
ts/test/util/sortByTitle_test.ts
Normal 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
12
ts/util/sortByTitle.ts
Normal 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));
|
||||
}
|
Loading…
Reference in a new issue