Conversation details changes for PNP

Co-authored-by: Scott Nonnenberg <scott@signal.org>
This commit is contained in:
Fedor Indutny 2024-02-05 18:13:13 -08:00 committed by GitHub
parent 1a74da0c26
commit eb82ace2de
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
49 changed files with 1660 additions and 699 deletions

View file

@ -17,11 +17,35 @@ import { Modal } from '../Modal';
import { RemoveGroupMemberConfirmationDialog } from './RemoveGroupMemberConfirmationDialog';
import { ContactSpoofingReviewDialogPerson } from './ContactSpoofingReviewDialogPerson';
import { Button, ButtonVariant } from '../Button';
import { Intl } from '../Intl';
import { assertDev } from '../../util/assert';
import { missingCaseError } from '../../util/missingCaseError';
import { isInSystemContacts } from '../../util/isInSystemContacts';
import { UserText } from '../UserText';
export type ReviewPropsType = Readonly<
| {
type: ContactSpoofingType.DirectConversationWithSameTitle;
possiblyUnsafe: {
conversation: ConversationType;
isSignalConnection: boolean;
};
safe: {
conversation: ConversationType;
isSignalConnection: boolean;
};
}
| {
type: ContactSpoofingType.MultipleGroupMembersWithSameTitle;
group: ConversationType;
collisionInfoByTitle: Record<
string,
Array<{
oldName?: string;
isSignalConnection: boolean;
conversation: ConversationType;
}>
>;
}
>;
export type PropsType = {
conversationId: string;
@ -29,6 +53,7 @@ export type PropsType = {
blockAndReportSpam: (conversationId: string) => unknown;
blockConversation: (conversationId: string) => unknown;
deleteConversation: (conversationId: string) => unknown;
toggleSignalConnectionsModal: () => void;
getPreferredBadge: PreferredBadgeSelectorType;
i18n: LocalizerType;
onClose: () => void;
@ -38,24 +63,7 @@ export type PropsType = {
memberConversationId: string
) => unknown;
theme: ThemeType;
} & (
| {
type: ContactSpoofingType.DirectConversationWithSameTitle;
possiblyUnsafeConversation: ConversationType;
safeConversation: ConversationType;
}
| {
type: ContactSpoofingType.MultipleGroupMembersWithSameTitle;
group: ConversationType;
collisionInfoByTitle: Record<
string,
Array<{
oldName?: string;
conversation: ConversationType;
}>
>;
}
);
} & ReviewPropsType;
enum ConfirmationStateType {
ConfirmingDelete,
@ -70,6 +78,7 @@ export function ContactSpoofingReviewDialog(props: PropsType): JSX.Element {
blockConversation,
conversationId,
deleteConversation,
toggleSignalConnectionsModal,
getPreferredBadge,
i18n,
onClose,
@ -169,13 +178,13 @@ export function ContactSpoofingReviewDialog(props: PropsType): JSX.Element {
switch (props.type) {
case ContactSpoofingType.DirectConversationWithSameTitle: {
const { possiblyUnsafeConversation, safeConversation } = props;
const { possiblyUnsafe, safe } = props;
assertDev(
possiblyUnsafeConversation.type === 'direct',
possiblyUnsafe.conversation.type === 'direct',
'<ContactSpoofingReviewDialog> expected a direct conversation for the "possibly unsafe" conversation'
);
assertDev(
safeConversation.type === 'direct',
safe.conversation.type === 'direct',
'<ContactSpoofingReviewDialog> expected a direct conversation for the "safe" conversation'
);
@ -187,10 +196,13 @@ export function ContactSpoofingReviewDialog(props: PropsType): JSX.Element {
{i18n('icu:ContactSpoofingReviewDialog__possibly-unsafe-title')}
</h2>
<ContactSpoofingReviewDialogPerson
conversation={possiblyUnsafeConversation}
conversation={possiblyUnsafe.conversation}
getPreferredBadge={getPreferredBadge}
toggleSignalConnectionsModal={toggleSignalConnectionsModal}
i18n={i18n}
theme={theme}
isSignalConnection={possiblyUnsafe.isSignalConnection}
oldName={undefined}
>
<div className="module-ContactSpoofingReviewDialog__buttons">
<Button
@ -198,7 +210,7 @@ export function ContactSpoofingReviewDialog(props: PropsType): JSX.Element {
onClick={() => {
setConfirmationState({
type: ConfirmationStateType.ConfirmingDelete,
affectedConversation: possiblyUnsafeConversation,
affectedConversation: possiblyUnsafe.conversation,
});
}}
>
@ -209,7 +221,7 @@ export function ContactSpoofingReviewDialog(props: PropsType): JSX.Element {
onClick={() => {
setConfirmationState({
type: ConfirmationStateType.ConfirmingBlock,
affectedConversation: possiblyUnsafeConversation,
affectedConversation: possiblyUnsafe.conversation,
});
}}
>
@ -220,13 +232,16 @@ export function ContactSpoofingReviewDialog(props: PropsType): JSX.Element {
<hr />
<h2>{i18n('icu:ContactSpoofingReviewDialog__safe-title')}</h2>
<ContactSpoofingReviewDialogPerson
conversation={safeConversation}
conversation={safe.conversation}
getPreferredBadge={getPreferredBadge}
toggleSignalConnectionsModal={toggleSignalConnectionsModal}
i18n={i18n}
onClick={() => {
showContactModal(safeConversation.id);
showContactModal(safe.conversation.id);
}}
theme={theme}
isSignalConnection={safe.isSignalConnection}
oldName={undefined}
/>
</>
);
@ -257,117 +272,83 @@ export function ContactSpoofingReviewDialog(props: PropsType): JSX.Element {
})}
</p>
{Object.values(collisionInfoByTitle).map(
(conversationInfos, titleIdx) => {
return (
<>
<h2>
{i18n(
'icu:ContactSpoofingReviewDialog__group__members-header'
)}
</h2>
{conversationInfos.map(
(conversationInfo, conversationIdx) => {
let button: ReactNode;
if (group.areWeAdmin) {
button = (
<Button
variant={ButtonVariant.SecondaryAffirmative}
onClick={() => {
setConfirmationState({
type: ConfirmationStateType.ConfirmingGroupRemoval,
affectedConversation:
conversationInfo.conversation,
group,
});
}}
>
{i18n(
'icu:RemoveGroupMemberConfirmation__remove-button'
)}
</Button>
);
} else if (conversationInfo.conversation.isBlocked) {
button = (
<Button
variant={ButtonVariant.SecondaryAffirmative}
onClick={() => {
acceptConversation(
conversationInfo.conversation.id
);
}}
>
{i18n('icu:MessageRequests--unblock')}
</Button>
);
} else if (
!isInSystemContacts(conversationInfo.conversation)
) {
button = (
<Button
variant={ButtonVariant.SecondaryDestructive}
onClick={() => {
setConfirmationState({
type: ConfirmationStateType.ConfirmingBlock,
affectedConversation:
conversationInfo.conversation,
});
}}
>
{i18n('icu:MessageRequests--block')}
</Button>
);
{Object.values(collisionInfoByTitle)
.map((conversationInfos, titleIdx) =>
conversationInfos.map((conversationInfo, conversationIdx) => {
let button: ReactNode;
if (group.areWeAdmin) {
button = (
<Button
variant={ButtonVariant.SecondaryAffirmative}
onClick={() => {
setConfirmationState({
type: ConfirmationStateType.ConfirmingGroupRemoval,
affectedConversation: conversationInfo.conversation,
group,
});
}}
>
{i18n('icu:RemoveGroupMemberConfirmation__remove-button')}
</Button>
);
} else if (conversationInfo.conversation.isBlocked) {
button = (
<Button
variant={ButtonVariant.SecondaryAffirmative}
onClick={() => {
acceptConversation(conversationInfo.conversation.id);
}}
>
{i18n('icu:MessageRequests--unblock')}
</Button>
);
} else if (!isInSystemContacts(conversationInfo.conversation)) {
button = (
<Button
variant={ButtonVariant.SecondaryDestructive}
onClick={() => {
setConfirmationState({
type: ConfirmationStateType.ConfirmingBlock,
affectedConversation: conversationInfo.conversation,
});
}}
>
{i18n('icu:MessageRequests--block')}
</Button>
);
}
const { oldName, isSignalConnection } = conversationInfo;
return (
<>
<ContactSpoofingReviewDialogPerson
key={conversationInfo.conversation.id}
conversation={conversationInfo.conversation}
toggleSignalConnectionsModal={
toggleSignalConnectionsModal
}
const { oldName } = conversationInfo;
const newName =
conversationInfo.conversation.profileName ||
conversationInfo.conversation.title;
let callout: JSX.Element | undefined;
if (oldName && oldName !== newName) {
callout = (
<div className="module-ContactSpoofingReviewDialogPerson__info__property module-ContactSpoofingReviewDialogPerson__info__property--callout">
<Intl
i18n={i18n}
id="icu:ContactSpoofingReviewDialog__group__name-change-info"
components={{
oldName: <UserText text={oldName} />,
newName: <UserText text={newName} />,
}}
/>
</div>
);
}
return (
<>
<ContactSpoofingReviewDialogPerson
key={conversationInfo.conversation.id}
conversation={conversationInfo.conversation}
getPreferredBadge={getPreferredBadge}
i18n={i18n}
theme={theme}
>
{callout}
{button && (
<div className="module-ContactSpoofingReviewDialog__buttons">
{button}
</div>
)}
</ContactSpoofingReviewDialogPerson>
{titleIdx < sharedTitles.length - 1 ||
conversationIdx < conversationInfos.length - 1 ? (
<hr />
) : null}
</>
);
}
)}
</>
);
}
)}
getPreferredBadge={getPreferredBadge}
i18n={i18n}
theme={theme}
oldName={oldName}
isSignalConnection={isSignalConnection}
>
{button && (
<div className="module-ContactSpoofingReviewDialog__buttons">
{button}
</div>
)}
</ContactSpoofingReviewDialogPerson>
{titleIdx < sharedTitles.length - 1 ||
conversationIdx < conversationInfos.length - 1 ? (
<hr />
) : null}
</>
);
})
)
.flat()}
</>
);
break;