Skip to content

Commit

Permalink
Introduce TitleTransition notification
Browse files Browse the repository at this point in the history
Co-authored-by: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com>
  • Loading branch information
automated-signal and indutny-signal committed Mar 7, 2024
1 parent 4b39639 commit edd2816
Show file tree
Hide file tree
Showing 16 changed files with 329 additions and 44 deletions.
4 changes: 4 additions & 0 deletions _locales/en/messages.json
Expand Up @@ -1541,6 +1541,10 @@
"messageformat": "{phoneNumber} belongs to {conversationTitle}",
"description": "Shown when we've discovered a phone number for a contact you've been communicating with, but you have no shared groups."
},
"icu:TitleTransition--notification": {
"messageformat": "You started this chat with {oldTitle}",
"description": "Shown when we've received profile information for a contact we have been messaging by username/phone number"
},
"icu:quoteThumbnailAlt": {
"messageformat": "Thumbnail of image from quoted message",
"description": "Used in alt tag of thumbnail images inside of an embedded message quote"
Expand Down
4 changes: 4 additions & 0 deletions images/icons/v3/thread/thread-compact.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions stylesheets/components/SystemMessage.scss
Expand Up @@ -166,6 +166,12 @@
@include system-message-icon('../images/icons/v3/refresh/refresh.svg');
}

&--icon-thread::before {
@include system-message-icon(
'../images/icons/v3/thread/thread-compact.svg'
);
}

&--icon-timer::before {
@include system-message-icon(
'../images/icons/v3/timer/timer-compact.svg'
Expand Down
14 changes: 13 additions & 1 deletion ts/ConversationController.ts
Expand Up @@ -720,6 +720,7 @@ export class ConversationController {
(targetOldServiceIds.pni !== pni ||
(aci && targetOldServiceIds.aci !== aci))
) {
targetConversation.unset('needsTitleTransition');
mergePromises.push(
targetConversation.addPhoneNumberDiscoveryIfNeeded(
targetOldServiceIds.pni
Expand Down Expand Up @@ -1056,6 +1057,8 @@ export class ConversationController {
}
current.set('active_at', activeAt);

const currentHadMessages = (current.get('messageCount') ?? 0) > 0;

const dataToCopy: Partial<ConversationAttributesType> = pick(
obsolete.attributes,
[
Expand All @@ -1067,6 +1070,7 @@ export class ConversationController {
'draftTimestamp',
'messageCount',
'messageRequestResponseType',
'needsTitleTransition',
'profileSharing',
'quotedMessageId',
'sentMessageCount',
Expand Down Expand Up @@ -1196,7 +1200,15 @@ export class ConversationController {
const titleIsUseful = Boolean(
obsoleteTitleInfo && getTitleNoDefault(obsoleteTitleInfo)
);
if (obsoleteTitleInfo && titleIsUseful && obsoleteHadMessages) {
// If both conversations had messages - add merge
if (
titleIsUseful &&
conversationType === 'private' &&
currentHadMessages &&
obsoleteHadMessages
) {
assertDev(obsoleteTitleInfo, 'part of titleIsUseful boolean');

drop(current.addConversationMerge(obsoleteTitleInfo));
}

Expand Down
34 changes: 33 additions & 1 deletion ts/components/conversation/SystemMessage.tsx
Expand Up @@ -12,7 +12,39 @@ export enum SystemMessageKind {
}

export type PropsType = {
icon: string;
icon:
| 'audio-incoming'
| 'audio-missed'
| 'audio-outgoing'
| 'group'
| 'group-access'
| 'group-add'
| 'group-approved'
| 'group-avatar'
| 'group-decline'
| 'group-edit'
| 'group-leave'
| 'group-remove'
| 'group-summary'
| 'info'
| 'phone'
| 'profile'
| 'safety-number'
| 'session-refresh'
| 'thread'
| 'timer'
| 'timer-disabled'
| 'unsupported'
| 'unsupported--can-process'
| 'verified'
| 'verified-not'
| 'video'
| 'video-incoming'
| 'video-missed'
| 'video-outgoing'
| 'warning'
| 'payment-event'
| 'merge';
contents: ReactNode;
button?: ReactNode;
kind?: SystemMessageKind;
Expand Down
6 changes: 6 additions & 0 deletions ts/components/conversation/TimelineItem.stories.tsx
Expand Up @@ -193,6 +193,12 @@ export function Notification(): JSX.Element {
timestamp: Date.now(),
},
},
{
type: 'titleTransitionNotification',
data: {
oldTitle: 'alice.01',
},
},
{
type: 'callHistory',
data: {
Expand Down
15 changes: 15 additions & 0 deletions ts/components/conversation/TimelineItem.tsx
Expand Up @@ -20,6 +20,8 @@ import type { PropsDataType as DeliveryIssueProps } from './DeliveryIssueNotific
import { DeliveryIssueNotification } from './DeliveryIssueNotification';
import type { PropsData as ChangeNumberNotificationProps } from './ChangeNumberNotification';
import { ChangeNumberNotification } from './ChangeNumberNotification';
import type { PropsData as TitleTransitionNotificationProps } from './TitleTransitionNotification';
import { TitleTransitionNotification } from './TitleTransitionNotification';
import type { CallingNotificationType } from '../../util/callingNotification';
import { InlineNotificationWrapper } from './InlineNotificationWrapper';
import type { PropsData as UnsupportedMessageProps } from './UnsupportedMessage';
Expand Down Expand Up @@ -91,6 +93,10 @@ type ChangeNumberNotificationType = {
type: 'changeNumberNotification';
data: ChangeNumberNotificationProps;
};
type TitleTransitionNotificationType = {
type: 'titleTransitionNotification';
data: TitleTransitionNotificationProps;
};
type SafetyNumberNotificationType = {
type: 'safetyNumberNotification';
data: SafetyNumberNotificationProps;
Expand Down Expand Up @@ -148,6 +154,7 @@ export type TimelineItemType = (
| SafetyNumberNotificationType
| TimerNotificationType
| UniversalTimerNotificationType
| TitleTransitionNotificationType
| ContactRemovedNotificationType
| UnsupportedMessageType
| VerificationNotificationType
Expand Down Expand Up @@ -296,6 +303,14 @@ export const TimelineItem = memo(function TimelineItem({
i18n={i18n}
/>
);
} else if (item.type === 'titleTransitionNotification') {
notification = (
<TitleTransitionNotification
{...reducedProps}
{...item.data}
i18n={i18n}
/>
);
} else if (item.type === 'safetyNumberNotification') {
notification = (
<SafetyNumberNotification
Expand Down
19 changes: 19 additions & 0 deletions ts/components/conversation/TitleTransitionNotification.stories.tsx
@@ -0,0 +1,19 @@
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only

import * as React from 'react';
import type { Meta } from '@storybook/react';
import { setupI18n } from '../../util/setupI18n';
import enMessages from '../../../_locales/en/messages.json';
import type { Props } from './TitleTransitionNotification';
import { TitleTransitionNotification } from './TitleTransitionNotification';

export default {
title: 'Components/Conversation/TitleTransitionNotification',
} satisfies Meta<Props>;

const i18n = setupI18n('en', enMessages);

export function Default(): JSX.Element {
return <TitleTransitionNotification oldTitle="alice.01" i18n={i18n} />;
}
39 changes: 39 additions & 0 deletions ts/components/conversation/TitleTransitionNotification.tsx
@@ -0,0 +1,39 @@
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only

import React from 'react';

import type { LocalizerType } from '../../types/Util';
import { Intl } from '../Intl';

import { SystemMessage } from './SystemMessage';
import { UserText } from '../UserText';

export type PropsData = {
oldTitle: string;
};

export type PropsHousekeeping = {
i18n: LocalizerType;
};

export type Props = PropsData & PropsHousekeeping;

export function TitleTransitionNotification(props: Props): JSX.Element {
const { i18n, oldTitle } = props;

return (
<SystemMessage
contents={
<Intl
id="icu:TitleTransition--notification"
components={{
oldTitle: <UserText text={oldTitle} />,
}}
i18n={i18n}
/>
}
icon="thread"
/>
);
}
5 changes: 5 additions & 0 deletions ts/model-types.d.ts
Expand Up @@ -191,6 +191,7 @@ export type MessageAttributesType = {
| 'timer-notification'
| 'universal-timer-notification'
| 'contact-removed-notification'
| 'title-transition-notification'
| 'verified-change';
body?: string;
attachments?: Array<AttachmentType>;
Expand Down Expand Up @@ -225,6 +226,9 @@ export type MessageAttributesType = {
conversationMerge?: {
renderInfo: ConversationRenderInfoType;
};
titleTransition?: {
renderInfo: ConversationRenderInfoType;
};

// Legacy fields for timer update notification only
flags?: number;
Expand Down Expand Up @@ -338,6 +342,7 @@ export type ConversationAttributesType = {
profileKeyCredential?: string | null;
profileKeyCredentialExpiration?: number | null;
lastProfile?: ConversationLastProfileType;
needsTitleTransition?: boolean;
quotedMessageId?: string | null;
sealedSender?: unknown;
sentMessageCount?: number;
Expand Down

0 comments on commit edd2816

Please sign in to comment.