Make sure that storySendMode is in group types

This commit is contained in:
Fedor Indutny 2022-11-19 00:31:18 -08:00 committed by GitHub
parent fa2fd5eef3
commit a2f1b469ea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 101 additions and 110 deletions

View file

@ -24,6 +24,7 @@ import { setupI18n } from '../util/setupI18n';
import type { SafetyNumberProps } from './SafetyNumberChangeDialog';
import enMessages from '../../_locales/en/messages.json';
import { ThemeType } from '../types/Util';
import { StorySendMode } from '../types/Stories';
const i18n = setupI18n('en', enMessages);
@ -194,6 +195,8 @@ export function RingingGroupCall(): JSX.Element {
...getConversation(),
type: 'group',
title: 'Tahoe Trip',
acknowledgedGroupNameCollisions: {},
storySendMode: StorySendMode.IfActive,
},
otherMembersRung: [
{ firstName: 'Morty', title: 'Morty Smith' },

View file

@ -7,6 +7,7 @@ import { times } from 'lodash';
import { action } from '@storybook/addon-actions';
import { UUID } from '../../../types/UUID';
import { StorySendMode } from '../../../types/Stories';
import { setupI18n } from '../../../util/setupI18n';
import enMessages from '../../../../_locales/en/messages.json';
import type { PropsType } from './PendingInvites';
@ -40,6 +41,8 @@ const conversation: ConversationType = {
title: 'Some Conversation',
type: 'group',
sharedGroupNames: [],
acknowledgedGroupNameCollisions: {},
storySendMode: StorySendMode.IfActive,
};
const OUR_UUID = UUID.generate().toString();

View file

@ -1884,7 +1884,6 @@ export class ConversationModel extends window.Backbone
groupVersion,
groupId: this.get('groupId'),
groupLink: this.getGroupLink(),
storySendMode: this.getStorySendMode(),
hideStory: Boolean(this.get('hideStory')),
inboxPosition,
isArchived: this.get('isArchived'),
@ -1945,6 +1944,7 @@ export class ConversationModel extends window.Backbone
acknowledgedGroupNameCollisions:
this.get('acknowledgedGroupNameCollisions') || {},
sharedGroupNames: [],
storySendMode: this.getGroupStorySendMode(),
}),
voiceNotePlaybackRate: this.get('voiceNotePlaybackRate'),
};
@ -5548,10 +5548,21 @@ export class ConversationModel extends window.Backbone
/** @return only undefined if not a group */
getStorySendMode(): StorySendMode | undefined {
if (!isGroup(this.attributes)) {
// isDirectConversation is used instead of isGroup because this is what
// used in `format()` when sending conversation "type" to redux.
if (isDirectConversation(this.attributes)) {
return undefined;
}
return this.getGroupStorySendMode();
}
private getGroupStorySendMode(): StorySendMode {
strictAssert(
!isDirectConversation(this.attributes),
'Must be a group to have send story mode'
);
return this.get('storySendMode') ?? StorySendMode.IfActive;
}
}

View file

@ -192,7 +192,6 @@ export type ConversationType = {
bannedMemberships?: Array<UUIDStringType>;
muteExpiresAt?: number;
dontNotifyForMentionsIfMuted?: boolean;
type: ConversationTypeType;
isMe: boolean;
lastUpdated?: number;
// This is used by the CompositionInput for @mentions
@ -217,12 +216,10 @@ export type ConversationType = {
groupVersion?: 1 | 2;
groupId?: string;
groupLink?: string;
storySendMode?: StorySendMode;
messageRequestsEnabled?: boolean;
acceptedMessageRequest: boolean;
secretParams?: string;
publicParams?: string;
acknowledgedGroupNameCollisions?: GroupNameCollisionsWithIdsByTitle;
profileKey?: string;
voiceNotePlaybackRate?: number;
@ -236,7 +233,18 @@ export type ConversationType = {
isVisible: boolean;
}
>;
};
} & (
| {
type: 'direct';
storySendMode?: undefined;
acknowledgedGroupNameCollisions?: undefined;
}
| {
type: 'group';
storySendMode: StorySendMode;
acknowledgedGroupNameCollisions: GroupNameCollisionsWithIdsByTitle;
}
);
export type ProfileDataType = {
firstName: string;
} & Pick<ConversationType, 'aboutEmoji' | 'aboutText' | 'familyName'>;

View file

@ -214,7 +214,7 @@ const getWarning = (
return {
type: ContactSpoofingType.MultipleGroupMembersWithSameTitle,
acknowledgedGroupNameCollisions:
conversation.acknowledgedGroupNameCollisions || {},
conversation.acknowledgedGroupNameCollisions,
groupNameCollisions:
dehydrateCollisionsWithConversations(groupNameCollisions),
};
@ -223,7 +223,7 @@ const getWarning = (
return undefined;
}
default:
throw missingCaseError(conversation.type);
throw missingCaseError(conversation);
}
};
@ -251,6 +251,10 @@ const getContactSpoofingReview = (
),
};
case ContactSpoofingType.MultipleGroupMembersWithSameTitle: {
assertDev(
currentConversation.type === 'group',
'MultipleGroupMembersWithSameTitle: expects group conversation'
);
const { memberships } = getGroupMemberships(
currentConversation,
getConversationByUuid
@ -258,7 +262,7 @@ const getContactSpoofingReview = (
const groupNameCollisions = getCollisionsFromMemberships(memberships);
const previouslyAcknowledgedTitlesById = invertIdsByTitle(
currentConversation.acknowledgedGroupNameCollisions || {}
currentConversation.acknowledgedGroupNameCollisions
);
const collisionInfoByTitle = mapValues(

View file

@ -8,6 +8,7 @@ import { UUID } from '../../types/UUID';
import type { UUIDStringType } from '../../types/UUID';
import { getRandomColor } from './getRandomColor';
import { ConversationColors } from '../../types/Colors';
import { StorySendMode } from '../../types/Stories';
export const getAvatarPath = (): string =>
sample([
@ -37,9 +38,11 @@ export function getDefaultConversation(
sharedGroupNames: [],
title: `${firstName} ${lastName}`,
titleNoDefault: `${firstName} ${lastName}`,
type: 'direct' as const,
uuid: UUID.generate().toString(),
...overrideProps,
type: 'direct' as const,
acknowledgedGroupNameCollisions: undefined,
storySendMode: undefined,
};
}
@ -70,9 +73,11 @@ export function getDefaultGroup(
memberships,
sharedGroupNames: [],
title: casual.title,
type: 'group' as const,
uuid: UUID.generate().toString(),
acknowledgedGroupNameCollisions: {},
storySendMode: StorySendMode.IfActive,
...overrideProps,
type: 'group' as const,
};
}

View file

@ -51,6 +51,7 @@ import type { UUIDStringType } from '../../../types/UUID';
import enMessages from '../../../../_locales/en/messages.json';
import {
getDefaultConversation,
getDefaultGroup,
getDefaultConversationWithUuid,
} from '../../helpers/getDefaultConversation';
import {
@ -77,6 +78,16 @@ describe('both/state/selectors/conversations-extra', () => {
});
}
function makeGroup(id: string): ConversationType {
const title = `${id} title`;
return getDefaultGroup({
id,
searchableTitle: title,
title,
titleNoDefault: title,
});
}
function makeConversationWithUuid(
id: string
): ConversationType & { uuid: UUIDStringType } {
@ -535,15 +546,13 @@ describe('both/state/selectors/conversations-extra', () => {
title: 'A',
},
'convo-2': {
...makeConversation('convo-2'),
type: 'group',
...makeGroup('convo-2'),
isGroupV1AndDisabled: true,
name: '2',
title: 'Should Be Dropped (GV1)',
},
'convo-3': {
...makeConversation('convo-3'),
type: 'group',
...makeGroup('convo-3'),
name: 'B',
title: 'B',
},
@ -624,10 +633,8 @@ describe('both/state/selectors/conversations-extra', () => {
profileSharing: false,
},
'convo-1': {
...makeConversation('convo-1'),
type: 'group' as const,
...makeGroup('convo-1'),
name: 'Friends!',
sharedGroupNames: [],
},
'convo-2': {
...makeConversation('convo-2'),
@ -707,10 +714,8 @@ describe('both/state/selectors/conversations-extra', () => {
name: 'Me!',
},
'convo-1': {
...makeConversation('convo-1'),
type: 'group' as const,
...makeGroup('convo-1'),
name: 'Friends!',
sharedGroupNames: [],
},
'convo-2': {
...makeConversation('convo-2'),
@ -790,15 +795,11 @@ describe('both/state/selectors/conversations-extra', () => {
name: 'Me!',
},
'convo-1': {
...makeConversation('convo-1'),
type: 'group' as const,
...makeGroup('convo-1'),
name: 'Friends!',
sharedGroupNames: [],
},
'convo-2': {
...makeConversation('convo-2'),
type: 'group' as const,
sharedGroupNames: [],
...makeGroup('convo-2'),
},
},
},
@ -816,22 +817,16 @@ describe('both/state/selectors/conversations-extra', () => {
...getEmptyState(),
conversationLookup: {
'convo-0': {
...makeConversation('convo-0'),
type: 'group' as const,
...makeGroup('convo-0'),
name: 'Family!',
isBlocked: true,
sharedGroupNames: [],
},
'convo-1': {
...makeConversation('convo-1'),
type: 'group' as const,
...makeGroup('convo-1'),
name: 'Friends!',
sharedGroupNames: [],
},
'convo-2': {
...makeConversation('convo-2'),
type: 'group' as const,
sharedGroupNames: [],
...makeGroup('convo-2'),
},
},
},
@ -886,8 +881,7 @@ describe('both/state/selectors/conversations-extra', () => {
title: 'Should Be Dropped (no name, no profile sharing)',
},
'convo-3': {
...makeConversation('convo-3'),
type: 'group',
...makeGroup('convo-3'),
title: 'Should Be Dropped (group)',
},
'convo-4': {
@ -983,39 +977,29 @@ describe('both/state/selectors/conversations-extra', () => {
title: 'Should be dropped (contact)',
},
'convo-3': {
...makeConversation('convo-3'),
type: 'group',
...makeGroup('convo-3'),
name: 'Hello World',
title: 'Hello World',
sharedGroupNames: [],
},
'convo-4': {
...makeConversation('convo-4'),
type: 'group',
...makeGroup('convo-4'),
isBlocked: true,
title: 'Should be dropped (blocked)',
sharedGroupNames: [],
},
'convo-5': {
...makeConversation('convo-5'),
type: 'group',
...makeGroup('convo-5'),
title: 'Unknown Group',
sharedGroupNames: [],
},
'convo-6': {
...makeConversation('convo-6'),
type: 'group',
...makeGroup('convo-6'),
name: 'Signal',
title: 'Signal',
sharedGroupNames: [],
},
'convo-7': {
...makeConversation('convo-7'),
...makeGroup('convo-7'),
profileSharing: false,
type: 'group',
name: 'Signal Fake',
title: 'Signal Fake',
sharedGroupNames: [],
},
},
composer: {
@ -1070,10 +1054,8 @@ describe('both/state/selectors/conversations-extra', () => {
title: 'Should be dropped (has no name)',
},
'convo-3': {
...makeConversation('convo-3'),
type: 'group',
...makeGroup('convo-3'),
title: 'Should Be Dropped (group)',
sharedGroupNames: [],
},
'convo-4': {
...makeConversation('convo-4'),
@ -1654,17 +1636,18 @@ describe('both/state/selectors/conversations-extra', () => {
describe('#getContactNameColorSelector', () => {
it('returns the right color order sorted by UUID ASC', () => {
const group = makeConversation('group');
group.type = 'group';
group.sortedGroupMembers = [
makeConversationWithUuid('fff'),
makeConversationWithUuid('f00'),
makeConversationWithUuid('e00'),
makeConversationWithUuid('d00'),
makeConversationWithUuid('c00'),
makeConversationWithUuid('b00'),
makeConversationWithUuid('a00'),
];
const group: ConversationType = {
...makeGroup('group'),
sortedGroupMembers: [
makeConversationWithUuid('fff'),
makeConversationWithUuid('f00'),
makeConversationWithUuid('e00'),
makeConversationWithUuid('d00'),
makeConversationWithUuid('c00'),
makeConversationWithUuid('b00'),
makeConversationWithUuid('a00'),
],
};
const state = {
...getEmptyRootState(),
conversations: {

View file

@ -38,6 +38,7 @@ import { UUID } from '../../../types/UUID';
import {
getDefaultConversation,
getDefaultConversationWithUuid,
getDefaultGroup,
} from '../../../test-both/helpers/getDefaultConversation';
import { getDefaultAvatars } from '../../../types/Avatar';
import {
@ -111,6 +112,7 @@ describe('both/state/ducks/conversations', () => {
describe('helpers', () => {
describe('getConversationCallMode', () => {
const fakeConversation: ConversationType = getDefaultConversation();
const fakeGroup: ConversationType = getDefaultGroup();
it("returns CallMode.None if you've left the conversation", () => {
assert.strictEqual(
@ -155,19 +157,16 @@ describe('both/state/ducks/conversations', () => {
it('returns CallMode.None for v1 groups', () => {
assert.strictEqual(
getConversationCallMode({
...fakeConversation,
type: 'group',
...fakeGroup,
groupVersion: 1,
sharedGroupNames: [],
}),
CallMode.None
);
assert.strictEqual(
getConversationCallMode({
...fakeConversation,
type: 'group',
sharedGroupNames: [],
...fakeGroup,
groupVersion: undefined,
}),
CallMode.None
);
@ -183,10 +182,8 @@ describe('both/state/ducks/conversations', () => {
it('returns CallMode.Group if the conversation is a v2 group', () => {
assert.strictEqual(
getConversationCallMode({
...fakeConversation,
type: 'group',
...fakeGroup,
groupVersion: 2,
sharedGroupNames: [],
}),
CallMode.Group
);

View file

@ -10,6 +10,10 @@ import type {
ShallowChallengeError,
} from '../../../model-types.d';
import type { ConversationType } from '../../../state/ducks/conversations';
import {
getDefaultConversation,
getDefaultGroup,
} from '../../../test-both/helpers/getDefaultConversation';
import {
canDeleteForEveryone,
@ -156,15 +160,7 @@ describe('state/selectors/messages', () => {
});
describe('canReact', () => {
const defaultConversation: ConversationType = {
id: uuid(),
type: 'direct',
title: 'Test conversation',
isMe: false,
sharedGroupNames: [],
acceptedMessageRequest: true,
badges: [],
};
const defaultConversation = getDefaultConversation();
it('returns false for disabled v1 groups', () => {
const message = {
@ -172,8 +168,7 @@ describe('state/selectors/messages', () => {
type: 'incoming' as const,
};
const getConversationById = () => ({
...defaultConversation,
type: 'group' as const,
...getDefaultGroup(),
isGroupV1AndDisabled: true,
});
@ -249,8 +244,7 @@ describe('state/selectors/messages', () => {
},
};
const getConversationById = () => ({
...defaultConversation,
type: 'group' as const,
...getDefaultGroup(),
});
assert.isTrue(canReact(message, ourConversationId, getConversationById));
@ -284,8 +278,7 @@ describe('state/selectors/messages', () => {
type: 'incoming' as const,
};
const getConversationById = () => ({
...defaultConversation,
type: 'group' as const,
...getDefaultGroup(),
isGroupV1AndDisabled: true,
});
@ -360,10 +353,7 @@ describe('state/selectors/messages', () => {
},
},
};
const getConversationById = () => ({
...defaultConversation,
type: 'group' as const,
});
const getConversationById = () => getDefaultGroup();
assert.isTrue(canReply(message, ourConversationId, getConversationById));
});

View file

@ -4,20 +4,7 @@
import type { ConversationType } from '../state/ducks/conversations';
import { format, isValidNumber } from '../types/PhoneNumber';
type FormattedContact = Partial<ConversationType> &
Pick<
ConversationType,
| 'acceptedMessageRequest'
| 'badges'
| 'id'
| 'isMe'
| 'sharedGroupNames'
| 'title'
| 'type'
| 'unblurredAvatarPath'
>;
const PLACEHOLDER_CONTACT: FormattedContact = {
const PLACEHOLDER_CONTACT: ConversationType = {
acceptedMessageRequest: false,
badges: [],
id: 'placeholder-contact',
@ -27,7 +14,7 @@ const PLACEHOLDER_CONTACT: FormattedContact = {
type: 'direct',
};
export function findAndFormatContact(identifier?: string): FormattedContact {
export function findAndFormatContact(identifier?: string): ConversationType {
if (!identifier) {
return PLACEHOLDER_CONTACT;
}