From d18ed40a230b6d1defb6ed320510f0b696c8f372 Mon Sep 17 00:00:00 2001
From: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com>
Date: Thu, 24 Mar 2022 14:46:17 -0700
Subject: [PATCH] Don't pass full group to spoofing review dialog
---
.../ContactSpoofingReviewDialog.stories.tsx | 2 +-
.../ContactSpoofingReviewDialog.tsx | 2 +-
.../conversation/Timeline.stories.tsx | 22 +++++++-
ts/components/conversation/Timeline.tsx | 39 ++++++-------
.../smart/ContactSpoofingReviewDialog.tsx | 55 +++++++++++++++++++
ts/state/smart/Timeline.tsx | 10 +++-
6 files changed, 105 insertions(+), 25 deletions(-)
create mode 100644 ts/state/smart/ContactSpoofingReviewDialog.tsx
diff --git a/ts/components/conversation/ContactSpoofingReviewDialog.stories.tsx b/ts/components/conversation/ContactSpoofingReviewDialog.stories.tsx
index d39aab03c2a1..a289c5fadb59 100644
--- a/ts/components/conversation/ContactSpoofingReviewDialog.stories.tsx
+++ b/ts/components/conversation/ContactSpoofingReviewDialog.stories.tsx
@@ -23,7 +23,7 @@ const story = storiesOf(
const getCommonProps = () => ({
getPreferredBadge: () => undefined,
i18n,
- group: getDefaultConversation(),
+ groupConversationId: 'convo-id',
onBlock: action('onBlock'),
onBlockAndReportSpam: action('onBlockAndReportSpam'),
onClose: action('onClose'),
diff --git a/ts/components/conversation/ContactSpoofingReviewDialog.tsx b/ts/components/conversation/ContactSpoofingReviewDialog.tsx
index a7555ba6d153..aa2d8378e8db 100644
--- a/ts/components/conversation/ContactSpoofingReviewDialog.tsx
+++ b/ts/components/conversation/ContactSpoofingReviewDialog.tsx
@@ -24,7 +24,7 @@ import { assert } from '../../util/assert';
import { missingCaseError } from '../../util/missingCaseError';
import { isInSystemContacts } from '../../util/isInSystemContacts';
-type PropsType = {
+export type PropsType = {
getPreferredBadge: PreferredBadgeSelectorType;
i18n: LocalizerType;
onBlock: (conversationId: string) => unknown;
diff --git a/ts/components/conversation/Timeline.stories.tsx b/ts/components/conversation/Timeline.stories.tsx
index 4ecc521043b8..0a214192248a 100644
--- a/ts/components/conversation/Timeline.stories.tsx
+++ b/ts/components/conversation/Timeline.stories.tsx
@@ -15,8 +15,10 @@ import type { PropsType } from './Timeline';
import { Timeline } from './Timeline';
import type { TimelineItemType } from './TimelineItem';
import { TimelineItem } from './TimelineItem';
+import { ContactSpoofingReviewDialog } from './ContactSpoofingReviewDialog';
import { StorybookThemeContext } from '../../../.storybook/StorybookThemeContext';
import { ConversationHero } from './ConversationHero';
+import type { PropsType as SmartContactSpoofingReviewDialogPropsType } from '../../state/smart/ContactSpoofingReviewDialog';
import { getDefaultConversation } from '../../test-both/helpers/getDefaultConversation';
import { getRandomColor } from '../../test-both/helpers/getRandomColor';
import { TypingBubble } from './TypingBubble';
@@ -453,6 +455,24 @@ const renderItem = ({
/>
);
+const renderContactSpoofingReviewDialog = (
+ props: SmartContactSpoofingReviewDialogPropsType
+) => {
+ if (props.type === ContactSpoofingType.MultipleGroupMembersWithSameTitle) {
+ return (
+
+ );
+ }
+
+ return ;
+};
+
const getAbout = () => text('about', '👍 Free to chat');
const getTitle = () => text('name', 'Cayce Bollard');
const getName = () => text('name', 'Cayce Bollard');
@@ -502,7 +522,6 @@ const renderTypingBubble = () => (
);
const useProps = (overrideProps: Partial = {}): PropsType => ({
- conversation: overrideProps.conversation || getDefaultConversation(),
discardMessages: action('discardMessages'),
getPreferredBadge: () => undefined,
i18n,
@@ -531,6 +550,7 @@ const useProps = (overrideProps: Partial = {}): PropsType => ({
renderItem,
renderHeroRow,
renderTypingBubble,
+ renderContactSpoofingReviewDialog,
isSomeoneTyping: overrideProps.isSomeoneTyping || false,
...actions(),
diff --git a/ts/components/conversation/Timeline.tsx b/ts/components/conversation/Timeline.tsx
index 7f0334d86084..019a9a7c2155 100644
--- a/ts/components/conversation/Timeline.tsx
+++ b/ts/components/conversation/Timeline.tsx
@@ -29,7 +29,7 @@ import { TimelineWarning } from './TimelineWarning';
import { TimelineWarnings } from './TimelineWarnings';
import { NewlyCreatedGroupInvitedContactsDialog } from '../NewlyCreatedGroupInvitedContactsDialog';
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 { hasUnacknowledgedCollisions } from '../../util/groupMemberNameCollisions';
import { TimelineFloatingHeader } from './TimelineFloatingHeader';
@@ -95,7 +95,6 @@ export type PropsDataType = {
type PropsHousekeepingType = {
id: string;
- conversation: ConversationType;
isConversationSelected: boolean;
isGroupV1AndDisabled?: boolean;
isIncomingMessageRequest: boolean;
@@ -133,6 +132,9 @@ type PropsHousekeepingType = {
updateSharedGroups: () => unknown
) => JSX.Element;
renderTypingBubble: (id: string) => JSX.Element;
+ renderContactSpoofingReviewDialog: (
+ props: SmartContactSpoofingReviewDialogPropsType
+ ) => JSX.Element;
};
export type PropsActionsType = {
@@ -764,7 +766,6 @@ export class Timeline extends React.Component<
clearInvitedUuidsForNewlyCreatedGroup,
closeContactSpoofingReview,
contactSpoofingReview,
- conversation,
getPreferredBadge,
getTimestampForMessage,
haveNewest,
@@ -786,6 +787,7 @@ export class Timeline extends React.Component<
renderHeroRow,
renderItem,
renderTypingBubble,
+ renderContactSpoofingReviewDialog,
reviewGroupMemberNameCollision,
reviewMessageRequestNameCollision,
showContactModal,
@@ -1029,26 +1031,21 @@ export class Timeline extends React.Component<
switch (contactSpoofingReview.type) {
case ContactSpoofingType.DirectConversationWithSameTitle:
- contactSpoofingReviewDialog = (
-
- );
+ contactSpoofingReviewDialog = renderContactSpoofingReviewDialog({
+ ...commonProps,
+ type: ContactSpoofingType.DirectConversationWithSameTitle,
+ possiblyUnsafeConversation:
+ contactSpoofingReview.possiblyUnsafeConversation,
+ safeConversation: contactSpoofingReview.safeConversation,
+ });
break;
case ContactSpoofingType.MultipleGroupMembersWithSameTitle:
- contactSpoofingReviewDialog = (
-
- );
+ contactSpoofingReviewDialog = renderContactSpoofingReviewDialog({
+ ...commonProps,
+ type: ContactSpoofingType.MultipleGroupMembersWithSameTitle,
+ groupConversationId: id,
+ collisionInfoByTitle: contactSpoofingReview.collisionInfoByTitle,
+ });
break;
default:
throw missingCaseError(contactSpoofingReview);
diff --git a/ts/state/smart/ContactSpoofingReviewDialog.tsx b/ts/state/smart/ContactSpoofingReviewDialog.tsx
new file mode 100644
index 000000000000..46ffacb61481
--- /dev/null
+++ b/ts/state/smart/ContactSpoofingReviewDialog.tsx
@@ -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 &
+ (
+ | {
+ 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(
+ getConversationSelector
+ );
+
+ if (type === ContactSpoofingType.MultipleGroupMembersWithSameTitle) {
+ return (
+
+ );
+ }
+
+ return ;
+};
diff --git a/ts/state/smart/Timeline.tsx b/ts/state/smart/Timeline.tsx
index 3a773e594238..526a06f18ff9 100644
--- a/ts/state/smart/Timeline.tsx
+++ b/ts/state/smart/Timeline.tsx
@@ -29,6 +29,8 @@ import {
} from '../selectors/conversations';
import { SmartTimelineItem } from './TimelineItem';
+import { SmartContactSpoofingReviewDialog } from './ContactSpoofingReviewDialog';
+import type { PropsType as SmartContactSpoofingReviewDialogPropsType } from './ContactSpoofingReviewDialog';
import { SmartTypingBubble } from './TypingBubble';
import { SmartHeroRow } from './HeroRow';
import { renderAudioAttachment } from './renderAudioAttachment';
@@ -139,6 +141,12 @@ function renderItem({
);
}
+function renderContactSpoofingReviewDialog(
+ props: SmartContactSpoofingReviewDialogPropsType
+): JSX.Element {
+ return ;
+}
+
function renderHeroRow(
id: string,
unblurAvatar: () => void,
@@ -286,7 +294,6 @@ const mapStateToProps = (state: StateType, props: ExternalProps) => {
return {
id,
...pick(conversation, ['unreadCount', 'isGroupV1AndDisabled']),
- conversation,
isConversationSelected: state.conversations.selectedConversationId === id,
isIncomingMessageRequest: Boolean(
conversation.messageRequestsEnabled &&
@@ -306,6 +313,7 @@ const mapStateToProps = (state: StateType, props: ExternalProps) => {
i18n: getIntl(state),
theme: getTheme(state),
renderItem,
+ renderContactSpoofingReviewDialog,
renderHeroRow,
renderTypingBubble,
...actions,