Don't pass full group to spoofing review dialog

This commit is contained in:
Fedor Indutny 2022-03-24 14:46:17 -07:00 committed by GitHub
parent ca3f8b7df0
commit d18ed40a23
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 105 additions and 25 deletions

View file

@ -23,7 +23,7 @@ const story = storiesOf(
const getCommonProps = () => ({ const getCommonProps = () => ({
getPreferredBadge: () => undefined, getPreferredBadge: () => undefined,
i18n, i18n,
group: getDefaultConversation(), groupConversationId: 'convo-id',
onBlock: action('onBlock'), onBlock: action('onBlock'),
onBlockAndReportSpam: action('onBlockAndReportSpam'), onBlockAndReportSpam: action('onBlockAndReportSpam'),
onClose: action('onClose'), onClose: action('onClose'),

View file

@ -24,7 +24,7 @@ import { assert } from '../../util/assert';
import { missingCaseError } from '../../util/missingCaseError'; import { missingCaseError } from '../../util/missingCaseError';
import { isInSystemContacts } from '../../util/isInSystemContacts'; import { isInSystemContacts } from '../../util/isInSystemContacts';
type PropsType = { export type PropsType = {
getPreferredBadge: PreferredBadgeSelectorType; getPreferredBadge: PreferredBadgeSelectorType;
i18n: LocalizerType; i18n: LocalizerType;
onBlock: (conversationId: string) => unknown; onBlock: (conversationId: string) => unknown;

View file

@ -15,8 +15,10 @@ import type { PropsType } from './Timeline';
import { Timeline } from './Timeline'; import { Timeline } from './Timeline';
import type { TimelineItemType } from './TimelineItem'; import type { TimelineItemType } from './TimelineItem';
import { TimelineItem } from './TimelineItem'; import { TimelineItem } from './TimelineItem';
import { ContactSpoofingReviewDialog } from './ContactSpoofingReviewDialog';
import { StorybookThemeContext } from '../../../.storybook/StorybookThemeContext'; import { StorybookThemeContext } from '../../../.storybook/StorybookThemeContext';
import { ConversationHero } from './ConversationHero'; import { ConversationHero } from './ConversationHero';
import type { PropsType as SmartContactSpoofingReviewDialogPropsType } from '../../state/smart/ContactSpoofingReviewDialog';
import { getDefaultConversation } from '../../test-both/helpers/getDefaultConversation'; import { getDefaultConversation } from '../../test-both/helpers/getDefaultConversation';
import { getRandomColor } from '../../test-both/helpers/getRandomColor'; import { getRandomColor } from '../../test-both/helpers/getRandomColor';
import { TypingBubble } from './TypingBubble'; import { TypingBubble } from './TypingBubble';
@ -453,6 +455,24 @@ const renderItem = ({
/> />
); );
const renderContactSpoofingReviewDialog = (
props: SmartContactSpoofingReviewDialogPropsType
) => {
if (props.type === ContactSpoofingType.MultipleGroupMembersWithSameTitle) {
return (
<ContactSpoofingReviewDialog
{...props}
group={{
...getDefaultConversation(),
areWeAdmin: true,
}}
/>
);
}
return <ContactSpoofingReviewDialog {...props} />;
};
const getAbout = () => text('about', '👍 Free to chat'); const getAbout = () => text('about', '👍 Free to chat');
const getTitle = () => text('name', 'Cayce Bollard'); const getTitle = () => text('name', 'Cayce Bollard');
const getName = () => text('name', 'Cayce Bollard'); const getName = () => text('name', 'Cayce Bollard');
@ -502,7 +522,6 @@ const renderTypingBubble = () => (
); );
const useProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({ const useProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
conversation: overrideProps.conversation || getDefaultConversation(),
discardMessages: action('discardMessages'), discardMessages: action('discardMessages'),
getPreferredBadge: () => undefined, getPreferredBadge: () => undefined,
i18n, i18n,
@ -531,6 +550,7 @@ const useProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
renderItem, renderItem,
renderHeroRow, renderHeroRow,
renderTypingBubble, renderTypingBubble,
renderContactSpoofingReviewDialog,
isSomeoneTyping: overrideProps.isSomeoneTyping || false, isSomeoneTyping: overrideProps.isSomeoneTyping || false,
...actions(), ...actions(),

View file

@ -29,7 +29,7 @@ import { TimelineWarning } from './TimelineWarning';
import { TimelineWarnings } from './TimelineWarnings'; import { TimelineWarnings } from './TimelineWarnings';
import { NewlyCreatedGroupInvitedContactsDialog } from '../NewlyCreatedGroupInvitedContactsDialog'; import { NewlyCreatedGroupInvitedContactsDialog } from '../NewlyCreatedGroupInvitedContactsDialog';
import { ContactSpoofingType } from '../../util/contactSpoofing'; import { ContactSpoofingType } from '../../util/contactSpoofing';
import { ContactSpoofingReviewDialog } from './ContactSpoofingReviewDialog'; import type { PropsType as SmartContactSpoofingReviewDialogPropsType } from '../../state/smart/ContactSpoofingReviewDialog';
import type { GroupNameCollisionsWithIdsByTitle } from '../../util/groupMemberNameCollisions'; import type { GroupNameCollisionsWithIdsByTitle } from '../../util/groupMemberNameCollisions';
import { hasUnacknowledgedCollisions } from '../../util/groupMemberNameCollisions'; import { hasUnacknowledgedCollisions } from '../../util/groupMemberNameCollisions';
import { TimelineFloatingHeader } from './TimelineFloatingHeader'; import { TimelineFloatingHeader } from './TimelineFloatingHeader';
@ -95,7 +95,6 @@ export type PropsDataType = {
type PropsHousekeepingType = { type PropsHousekeepingType = {
id: string; id: string;
conversation: ConversationType;
isConversationSelected: boolean; isConversationSelected: boolean;
isGroupV1AndDisabled?: boolean; isGroupV1AndDisabled?: boolean;
isIncomingMessageRequest: boolean; isIncomingMessageRequest: boolean;
@ -133,6 +132,9 @@ type PropsHousekeepingType = {
updateSharedGroups: () => unknown updateSharedGroups: () => unknown
) => JSX.Element; ) => JSX.Element;
renderTypingBubble: (id: string) => JSX.Element; renderTypingBubble: (id: string) => JSX.Element;
renderContactSpoofingReviewDialog: (
props: SmartContactSpoofingReviewDialogPropsType
) => JSX.Element;
}; };
export type PropsActionsType = { export type PropsActionsType = {
@ -764,7 +766,6 @@ export class Timeline extends React.Component<
clearInvitedUuidsForNewlyCreatedGroup, clearInvitedUuidsForNewlyCreatedGroup,
closeContactSpoofingReview, closeContactSpoofingReview,
contactSpoofingReview, contactSpoofingReview,
conversation,
getPreferredBadge, getPreferredBadge,
getTimestampForMessage, getTimestampForMessage,
haveNewest, haveNewest,
@ -786,6 +787,7 @@ export class Timeline extends React.Component<
renderHeroRow, renderHeroRow,
renderItem, renderItem,
renderTypingBubble, renderTypingBubble,
renderContactSpoofingReviewDialog,
reviewGroupMemberNameCollision, reviewGroupMemberNameCollision,
reviewMessageRequestNameCollision, reviewMessageRequestNameCollision,
showContactModal, showContactModal,
@ -1029,26 +1031,21 @@ export class Timeline extends React.Component<
switch (contactSpoofingReview.type) { switch (contactSpoofingReview.type) {
case ContactSpoofingType.DirectConversationWithSameTitle: case ContactSpoofingType.DirectConversationWithSameTitle:
contactSpoofingReviewDialog = ( contactSpoofingReviewDialog = renderContactSpoofingReviewDialog({
<ContactSpoofingReviewDialog ...commonProps,
{...commonProps} type: ContactSpoofingType.DirectConversationWithSameTitle,
type={ContactSpoofingType.DirectConversationWithSameTitle} possiblyUnsafeConversation:
possiblyUnsafeConversation={ contactSpoofingReview.possiblyUnsafeConversation,
contactSpoofingReview.possiblyUnsafeConversation safeConversation: contactSpoofingReview.safeConversation,
} });
safeConversation={contactSpoofingReview.safeConversation}
/>
);
break; break;
case ContactSpoofingType.MultipleGroupMembersWithSameTitle: case ContactSpoofingType.MultipleGroupMembersWithSameTitle:
contactSpoofingReviewDialog = ( contactSpoofingReviewDialog = renderContactSpoofingReviewDialog({
<ContactSpoofingReviewDialog ...commonProps,
{...commonProps} type: ContactSpoofingType.MultipleGroupMembersWithSameTitle,
type={ContactSpoofingType.MultipleGroupMembersWithSameTitle} groupConversationId: id,
group={conversation} collisionInfoByTitle: contactSpoofingReview.collisionInfoByTitle,
collisionInfoByTitle={contactSpoofingReview.collisionInfoByTitle} });
/>
);
break; break;
default: default:
throw missingCaseError(contactSpoofingReview); throw missingCaseError(contactSpoofingReview);

View file

@ -0,0 +1,55 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
import { useSelector } from 'react-redux';
import type { StateType } from '../reducer';
import type { PropsType as DownstreamPropsType } from '../../components/conversation/ContactSpoofingReviewDialog';
import { ContactSpoofingReviewDialog } from '../../components/conversation/ContactSpoofingReviewDialog';
import type { ConversationType } from '../ducks/conversations';
import type { GetConversationByIdType } from '../selectors/conversations';
import { getConversationSelector } from '../selectors/conversations';
import { ContactSpoofingType } from '../../util/contactSpoofing';
export type PropsType = Omit<DownstreamPropsType, 'type'> &
(
| {
type: ContactSpoofingType.DirectConversationWithSameTitle;
possiblyUnsafeConversation: ConversationType;
safeConversation: ConversationType;
}
| {
type: ContactSpoofingType.MultipleGroupMembersWithSameTitle;
groupConversationId: string;
collisionInfoByTitle: Record<
string,
Array<{
oldName?: string;
conversation: ConversationType;
}>
>;
}
);
export const SmartContactSpoofingReviewDialog: React.ComponentType<
PropsType
> = props => {
const { type } = props;
const getConversation = useSelector<StateType, GetConversationByIdType>(
getConversationSelector
);
if (type === ContactSpoofingType.MultipleGroupMembersWithSameTitle) {
return (
<ContactSpoofingReviewDialog
{...props}
group={getConversation(props.groupConversationId)}
/>
);
}
return <ContactSpoofingReviewDialog {...props} />;
};

View file

@ -29,6 +29,8 @@ import {
} from '../selectors/conversations'; } from '../selectors/conversations';
import { SmartTimelineItem } from './TimelineItem'; import { SmartTimelineItem } from './TimelineItem';
import { SmartContactSpoofingReviewDialog } from './ContactSpoofingReviewDialog';
import type { PropsType as SmartContactSpoofingReviewDialogPropsType } from './ContactSpoofingReviewDialog';
import { SmartTypingBubble } from './TypingBubble'; import { SmartTypingBubble } from './TypingBubble';
import { SmartHeroRow } from './HeroRow'; import { SmartHeroRow } from './HeroRow';
import { renderAudioAttachment } from './renderAudioAttachment'; import { renderAudioAttachment } from './renderAudioAttachment';
@ -139,6 +141,12 @@ function renderItem({
); );
} }
function renderContactSpoofingReviewDialog(
props: SmartContactSpoofingReviewDialogPropsType
): JSX.Element {
return <SmartContactSpoofingReviewDialog {...props} />;
}
function renderHeroRow( function renderHeroRow(
id: string, id: string,
unblurAvatar: () => void, unblurAvatar: () => void,
@ -286,7 +294,6 @@ const mapStateToProps = (state: StateType, props: ExternalProps) => {
return { return {
id, id,
...pick(conversation, ['unreadCount', 'isGroupV1AndDisabled']), ...pick(conversation, ['unreadCount', 'isGroupV1AndDisabled']),
conversation,
isConversationSelected: state.conversations.selectedConversationId === id, isConversationSelected: state.conversations.selectedConversationId === id,
isIncomingMessageRequest: Boolean( isIncomingMessageRequest: Boolean(
conversation.messageRequestsEnabled && conversation.messageRequestsEnabled &&
@ -306,6 +313,7 @@ const mapStateToProps = (state: StateType, props: ExternalProps) => {
i18n: getIntl(state), i18n: getIntl(state),
theme: getTheme(state), theme: getTheme(state),
renderItem, renderItem,
renderContactSpoofingReviewDialog,
renderHeroRow, renderHeroRow,
renderTypingBubble, renderTypingBubble,
...actions, ...actions,