diff --git a/stylesheets/_modules.scss b/stylesheets/_modules.scss
index 8b03a16348..80d067f6fe 100644
--- a/stylesheets/_modules.scss
+++ b/stylesheets/_modules.scss
@@ -2060,7 +2060,6 @@ $timer-icons: '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '05',
.module-inline-notification-wrapper {
outline: none;
- padding: 5px;
&:focus {
@include keyboard-mode {
@@ -2074,11 +2073,6 @@ $timer-icons: '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '05',
// Module: Group Notification
-.module-group-notification__change {
- margin-top: 2px;
- margin-bottom: 2px;
-}
-
.module-group-notification__contact {
font-weight: bold;
}
diff --git a/stylesheets/components/Button.scss b/stylesheets/components/Button.scss
index a6af7ba6f7..cb628a467c 100644
--- a/stylesheets/components/Button.scss
+++ b/stylesheets/components/Button.scss
@@ -160,6 +160,14 @@
&--system-message {
@include rounded-corners;
+ &.module-Button--small {
+ padding: {
+ top: 5px;
+ bottom: 5px;
+ }
+ font-weight: 500;
+ }
+
@include light-theme {
$color: $color-ultramarine;
$background-color: $color-gray-02;
diff --git a/stylesheets/components/SystemMessage.scss b/stylesheets/components/SystemMessage.scss
index 1cc784e98f..a4e2fcfe20 100644
--- a/stylesheets/components/SystemMessage.scss
+++ b/stylesheets/components/SystemMessage.scss
@@ -16,245 +16,259 @@
@include font-body-2;
align-items: center;
display: flex;
- flex-direction: row;
+ flex-direction: column;
justify-content: center;
- text-align: center;
+ line-height: 16px;
+ margin-bottom: 16px;
+ margin-top: 16px;
@include light-theme {
- color: $color-black;
+ color: $color-gray-60;
}
@include dark-theme {
color: $color-gray-25;
}
- &--multiline {
- flex-direction: column;
- }
-
- &__line {
- align-items: center;
- display: flex;
-
- &:not(:first-child) {
- margin-top: 12px;
- }
- }
-
- &__text {
+ &__contents {
max-width: 400px;
- }
+ text-align: center;
+ user-select: none;
- &__icon {
- height: 16px;
- flex: 0 0 16px;
- margin-right: 8px;
- width: 16px;
- vertical-align: middle;
+ p {
+ display: block;
+ margin: {
+ block: {
+ start: 0;
+ end: 4px;
+ }
+ inline: {
+ start: 0;
+ end: 0;
+ }
+ }
- @include light-theme {
- background-color: $color-black;
- }
- @include dark-theme {
- background-color: $color-gray-25;
+ &:first-child {
+ display: inline-block;
+ }
+
+ &:last-child {
+ margin-block-end: 0;
+ }
}
- &--audio-incoming {
+ &::before {
+ content: '';
+ display: inline-block;
+ height: 16px;
+ margin-right: 8px;
+ width: 16px;
+ vertical-align: middle;
+
+ @include light-theme {
+ background-color: $color-gray-60;
+ }
+ @include dark-theme {
+ background-color: $color-gray-25;
+ }
+ }
+
+ &--icon-audio-incoming::before {
@include system-message-icon(
'../images/icons/v2/phone-incoming-16.svg',
'../images/icons/v2/phone-incoming-solid-16.svg'
);
}
- &--audio-missed {
+ &--icon-audio-missed::before {
@include system-message-icon(
'../images/icons/v2/phone-x-16.svg',
'../images/icons/v2/phone-x-solid-16.svg'
);
}
- &--audio-outgoing {
+ &--icon-audio-outgoing::before {
@include system-message-icon(
'../images/icons/v2/phone-outgoing-16.svg',
'../images/icons/v2/phone-outgoing-solid-16.svg'
);
}
- &--group {
+ &--icon-group::before {
@include system-message-icon(
'../images/icons/v2/group-outline-24.svg',
'../images/icons/v2/group-solid-24.svg'
);
}
- &--group-access {
+ &--icon-group-access::before {
@include system-message-icon(
'../images/icons/v2/megaphone-16.svg',
'../images/icons/v2/megaphone-solid-16.svg'
);
}
- &--group-add {
+ &--icon-group-add::before {
@include system-message-icon(
'../images/icons/v2/member-added-16.svg',
'../images/icons/v2/member-added-solid-16.svg'
);
}
- &--group-approved {
+ &--icon-group-approved::before {
@include system-message-icon(
'../images/icons/v2/member-accepted-16.svg',
'../images/icons/v2/member-accepted-solid-16.svg'
);
}
- &--group-avatar {
+ &--icon-group-avatar::before {
@include system-message-icon(
'../images/icons/v2/photo-16.svg',
'../images/icons/v2/photo-solid-16.svg'
);
}
- &--group-decline {
+ &--icon-group-decline::before {
@include system-message-icon(
'../images/icons/v2/member-declined-16.svg',
'../images/icons/v2/member-declined-solid-16.svg'
);
}
- &--group-edit {
+ &--icon-group-edit::before {
@include system-message-icon(
'../images/icons/v2/edit-16.svg',
'../images/icons/v2/edit-solid-16.svg'
);
}
- &--group-leave {
+ &--icon-group-leave::before {
@include system-message-icon(
'../images/icons/v2/leave-16.svg',
'../images/icons/v2/leave-solid-16.svg'
);
}
- &--group-remove {
+ &--icon-group-remove::before {
@include system-message-icon(
'../images/icons/v2/member-remove-16.svg',
'../images/icons/v2/member-remove-solid-16.svg'
);
}
- &--info {
+ &--icon-info::before {
@include system-message-icon(
'../images/icons/v2/info-16.svg',
'../images/icons/v2/info-solid-24.svg'
);
}
- &--phone {
+ &--icon-phone::before {
@include system-message-icon(
'../images/icons/v2/phone-right-outline-24.svg',
'../images/icons/v2/phone-right-solid-24.svg'
);
}
- &--profile {
+ &--icon-profile::before {
@include system-message-icon(
'../images/icons/v2/profile-outline-20.svg',
'../images/icons/v2/profile-outline-20.svg'
);
}
- &--safety-number {
+ &--icon-safety-number::before {
@include system-message-icon(
'../images/icons/v2/safety-number-outline-24.svg',
'../images/icons/v2/safety-number-solid-24.svg'
);
}
- &--session-refresh {
+ &--icon-session-refresh::before {
@include system-message-icon(
'../images/icons/v2/refresh-16.svg',
'../images/icons/v2/refresh-16.svg'
);
}
- &--timer {
+ &--icon-timer::before {
@include system-message-icon(
'../images/icons/v2/timer-outline-24.svg',
'../images/icons/v2/timer-solid-16.svg'
);
}
- &--timer-disabled {
+ &--icon-timer-disabled::before {
@include system-message-icon(
'../images/icons/v2/timer-disabled-outline-24.svg',
'../images/icons/v2/timer-disabled-solid-16.svg'
);
}
- &--unsupported {
+ &--icon-unsupported::before {
@include system-message-icon(
'../images/icons/v2/error-outline-24.svg',
'../images/icons/v2/error-solid-24.svg'
);
-
- &--can-process {
- @include system-message-icon(
- '../images/icons/v2/check-circle-outline-24.svg',
- '../images/icons/v2/check-circle-solid-24.svg'
- );
- }
}
- &--unsynced {
+ &--icon-unsupported--can-process::before {
+ @include system-message-icon(
+ '../images/icons/v2/check-circle-outline-24.svg',
+ '../images/icons/v2/check-circle-solid-24.svg'
+ );
+ }
+
+ &--icon-unsynced::before {
@include system-message-icon(
'../images/icons/v2/info-outline-24.svg',
'../images/icons/v2/info-solid-24.svg'
);
}
- &--verified {
+ &--icon-verified::before {
@include system-message-icon(
'../images/icons/v2/check-24.svg',
'../images/icons/v2/check-24.svg'
);
}
- &--verified-not {
+ &--icon-verified-not::before {
@include system-message-icon(
'../images/icons/v2/safety-number-outline-24.svg',
'../images/icons/v2/safety-number-solid-24.svg'
);
}
- &--video {
+ &--icon-video::before {
@include system-message-icon(
'../images/icons/v2/video-outline-24.svg',
'../images/icons/v2/video-outline-24.svg'
);
}
- &--video-incoming {
+ &--icon-video-incoming::before {
@include system-message-icon(
'../images/icons/v2/video-incoming-16.svg',
'../images/icons/v2/video-incoming-solid-16.svg'
);
}
- &--video-missed {
+ &--icon-video-missed::before {
@include system-message-icon(
'../images/icons/v2/video-x-16.svg',
'../images/icons/v2/video-x-solid-16.svg'
);
}
- &--video-outgoing {
+ &--icon-video-outgoing::before {
@include system-message-icon(
'../images/icons/v2/video-outgoing-16.svg',
'../images/icons/v2/video-outgoing-solid-16.svg'
);
}
- &--warning {
+ &--icon-warning::before {
@include system-message-icon(
'../images/icons/v2/error-outline-12.svg',
'../images/icons/v2/error-outline-12.svg'
@@ -265,13 +279,12 @@
&--error {
color: $color-accent-red;
- .SystemMessage__icon {
+ .SystemMessage__contents::before {
background: $color-accent-red;
}
}
- img.emoji {
- // The negative bottom margin offset doesn't play well with align-items center
- margin-bottom: 0;
+ &__button-container {
+ margin-top: 12px;
}
}
diff --git a/ts/components/conversation/CallingNotification.tsx b/ts/components/conversation/CallingNotification.tsx
index e3a285da31..259f90fa6f 100644
--- a/ts/components/conversation/CallingNotification.tsx
+++ b/ts/components/conversation/CallingNotification.tsx
@@ -2,10 +2,10 @@
// SPDX-License-Identifier: AGPL-3.0-only
import React, { useState, useEffect } from 'react';
-import classNames from 'classnames';
import Measure from 'react-measure';
import { noop } from 'lodash';
+import { SystemMessage } from './SystemMessage';
import { Button, ButtonSize, ButtonVariant } from '../Button';
import { Timestamp } from './Timestamp';
import { LocalizerType } from '../../types/Util';
@@ -86,17 +86,12 @@ export const CallingNotification: React.FC = React.memo(props => {
}}
>
{({ measureRef }) => (
-
-
-
-
+ : undefined
+ }
+ contents={
+ <>
{getCallingNotificationText(props, i18n)} ·{' '}
= React.memo(props => {
withSticker={false}
withTapToViewExpired={false}
/>
-
-
- {hasButton ? (
-
-
-
- ) : null}
-
+ >
+ }
+ icon={icon}
+ isError={wasMissed}
+ ref={measureRef}
+ />
)}
);
diff --git a/ts/components/conversation/ChangeNumberNotification.stories.tsx b/ts/components/conversation/ChangeNumberNotification.stories.tsx
new file mode 100644
index 0000000000..e744c2c0d1
--- /dev/null
+++ b/ts/components/conversation/ChangeNumberNotification.stories.tsx
@@ -0,0 +1,36 @@
+// Copyright 2021 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+
+import * as React from 'react';
+
+import { storiesOf } from '@storybook/react';
+import { setup as setupI18n } from '../../../js/modules/i18n';
+import enMessages from '../../../_locales/en/messages.json';
+import { getDefaultConversation } from '../../test-both/helpers/getDefaultConversation';
+
+import { ChangeNumberNotification } from './ChangeNumberNotification';
+
+const story = storiesOf(
+ 'Components/Conversation/ChangeNumberNotification',
+ module
+);
+
+const i18n = setupI18n('en', enMessages);
+
+story.add('Default', () => (
+
+));
+
+story.add('Long name', () => (
+
+));
diff --git a/ts/components/conversation/ChangeNumberNotification.tsx b/ts/components/conversation/ChangeNumberNotification.tsx
index d022eee9ed..b24ff6fc57 100644
--- a/ts/components/conversation/ChangeNumberNotification.tsx
+++ b/ts/components/conversation/ChangeNumberNotification.tsx
@@ -7,6 +7,7 @@ import { ConversationType } from '../../state/ducks/conversations';
import { LocalizerType } from '../../types/Util';
import { Intl } from '../Intl';
+import { SystemMessage } from './SystemMessage';
import { Timestamp } from './Timestamp';
import { Emojify } from './Emojify';
@@ -25,17 +26,21 @@ export const ChangeNumberNotification: React.FC = props => {
const { i18n, sender, timestamp } = props;
return (
-
-
- ,
- }}
- i18n={i18n}
- />
- ยท
-
-
+
+ ,
+ }}
+ i18n={i18n}
+ />
+ ยท
+
+ >
+ }
+ icon="phone"
+ />
);
};
diff --git a/ts/components/conversation/ChatSessionRefreshedNotification.tsx b/ts/components/conversation/ChatSessionRefreshedNotification.tsx
index e57a7292f7..a9e67a46ac 100644
--- a/ts/components/conversation/ChatSessionRefreshedNotification.tsx
+++ b/ts/components/conversation/ChatSessionRefreshedNotification.tsx
@@ -6,6 +6,7 @@ import React, { useCallback, useState, ReactElement } from 'react';
import { LocalizerType } from '../../types/Util';
import { Button, ButtonSize, ButtonVariant } from '../Button';
+import { SystemMessage } from './SystemMessage';
import { ChatSessionRefreshedDialog } from './ChatSessionRefreshedDialog';
type PropsHousekeepingType = {
@@ -37,20 +38,20 @@ export function ChatSessionRefreshedNotification(
}, [contactSupport, setIsDialogOpen]);
return (
-
-
-
- {i18n('ChatRefresh--notification')}
-
-
-
-
+ <>
+
+ {i18n('ChatRefresh--learnMore')}
+
+ }
+ icon="session-refresh"
+ />
{isDialogOpen ? (
) : null}
-
+ >
);
}
diff --git a/ts/components/conversation/DeliveryIssueNotification.tsx b/ts/components/conversation/DeliveryIssueNotification.tsx
index d047882b4a..0c4f4ba062 100644
--- a/ts/components/conversation/DeliveryIssueNotification.tsx
+++ b/ts/components/conversation/DeliveryIssueNotification.tsx
@@ -4,6 +4,7 @@
import React, { useCallback, useState, ReactElement } from 'react';
import { Button, ButtonSize, ButtonVariant } from '../Button';
+import { SystemMessage } from './SystemMessage';
import { ConversationType } from '../../state/ducks/conversations';
import { LocalizerType } from '../../types/Util';
import { Intl } from '../Intl';
@@ -46,10 +47,9 @@ export function DeliveryIssueNotification(
}
return (
-
-
-
-
+ <>
+
-
-
-
-
-
+ }
+ icon="info"
+ button={
+
+ }
+ />
{isDialogOpen ? (
) : null}
-
+ >
);
}
diff --git a/ts/components/conversation/GroupNotification.tsx b/ts/components/conversation/GroupNotification.tsx
index 5b0dd80202..14fe9b31e7 100644
--- a/ts/components/conversation/GroupNotification.tsx
+++ b/ts/components/conversation/GroupNotification.tsx
@@ -1,10 +1,11 @@
-// Copyright 2018-2020 Signal Messenger, LLC
+// Copyright 2018-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
-import React from 'react';
+import React, { ReactNode } from 'react';
import { compact, flatten } from 'lodash';
import { ContactName } from './ContactName';
+import { SystemMessage } from './SystemMessage';
import { Intl } from '../Intl';
import { LocalizerType } from '../../types/Util';
@@ -133,12 +134,15 @@ export class GroupNotification extends React.Component {
}
public render(): JSX.Element {
- const { changes, i18n, from } = this.props;
+ const { changes: rawChanges, i18n, from } = this.props;
+
+ // This check is just to be extra careful, and can probably be removed.
+ const changes: Array = Array.isArray(rawChanges) ? rawChanges : [];
// Leave messages are always from the person leaving, so we omit the fromLabel if
// the change is a 'leave.'
- const isLeftOnly =
- changes && changes.length === 1 && changes[0].type === 'remove';
+ const firstChange: undefined | Change = changes[0];
+ const isLeftOnly = changes.length === 1 && firstChange?.type === 'remove';
const fromContact = (
{
);
- return (
-
-
- {isLeftOnly ? null : (
- <>
- {fromLabel}
-
- >
- )}
- {(changes || []).map((change, i) => (
+ let contents: ReactNode;
+ if (isLeftOnly) {
+ contents = this.renderChange(firstChange, from);
+ } else {
+ contents = (
+ <>
+
{fromLabel}
+ {changes.map((change, i) => (
// eslint-disable-next-line react/no-array-index-key
-
+
{this.renderChange(change, from)}
-
+
))}
-
-
- );
+ >
+ );
+ }
+
+ return ;
}
}
diff --git a/ts/components/conversation/GroupV1Migration.tsx b/ts/components/conversation/GroupV1Migration.tsx
index 7975312e0d..4b135e1103 100644
--- a/ts/components/conversation/GroupV1Migration.tsx
+++ b/ts/components/conversation/GroupV1Migration.tsx
@@ -1,9 +1,10 @@
-// Copyright 2020 Signal Messenger, LLC
+// Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
import { Button, ButtonSize, ButtonVariant } from '../Button';
+import { SystemMessage } from './SystemMessage';
import { LocalizerType } from '../../types/Util';
import { ConversationType } from '../../state/ducks/conversations';
import { Intl } from '../Intl';
@@ -35,40 +36,42 @@ export function GroupV1Migration(props: PropsType): React.ReactElement {
}, [setShowingDialog]);
return (
-
-
-
-
-
{i18n('GroupV1--Migration--was-upgraded')}
-
- {areWeInvited ? (
- i18n('GroupV1--Migration--invited--you')
- ) : (
- <>
- {renderUsers(
- invitedMembers,
- i18n,
- 'GroupV1--Migration--invited'
- )}
- {renderUsers(
- droppedMembers,
- i18n,
- 'GroupV1--Migration--removed'
- )}
- >
- )}
-
-
-
-
-
-
+ <>
+
+ {i18n('GroupV1--Migration--was-upgraded')}
+
+ {areWeInvited ? (
+ i18n('GroupV1--Migration--invited--you')
+ ) : (
+ <>
+ {renderUsers(
+ invitedMembers,
+ i18n,
+ 'GroupV1--Migration--invited'
+ )}
+ {renderUsers(
+ droppedMembers,
+ i18n,
+ 'GroupV1--Migration--removed'
+ )}
+ >
+ )}
+
+ >
+ }
+ button={
+
+ }
+ />
{showingDialog ? (
) : null}
-
+ >
);
}
@@ -95,23 +98,17 @@ function renderUsers(
return null;
}
- const className = 'module-group-v1-migration--text';
-
if (members.length === 1) {
return (
-
+
);
}
- return (
-
- {i18n(`${keyPrefix}--many`, [members.length.toString()])}
-
- );
+ return {i18n(`${keyPrefix}--many`, [members.length.toString()])}
;
}
diff --git a/ts/components/conversation/GroupV2Change.tsx b/ts/components/conversation/GroupV2Change.tsx
index abffbf26b1..1f4b18767c 100644
--- a/ts/components/conversation/GroupV2Change.tsx
+++ b/ts/components/conversation/GroupV2Change.tsx
@@ -2,7 +2,6 @@
// SPDX-License-Identifier: AGPL-3.0-only
import React, { ReactElement, useState } from 'react';
-import classNames from 'classnames';
import { get } from 'lodash';
import { ReplacementValuesType } from '../../types/I18N';
@@ -10,6 +9,7 @@ import { FullJSXType, Intl } from '../Intl';
import { LocalizerType } from '../../types/Util';
import { GroupDescriptionText } from '../GroupDescriptionText';
import { Button, ButtonSize, ButtonVariant } from '../Button';
+import { SystemMessage } from './SystemMessage';
import { GroupV2ChangeType, GroupV2ChangeDetailType } from '../../groups';
@@ -110,17 +110,11 @@ function GroupV2Detail({
detail.type === 'description' && get(detail, 'description');
return (
-
-
- {newGroupDescription ? (
-
+ onButtonClick(newGroupDescription)}
size={ButtonSize.Small}
@@ -128,9 +122,9 @@ function GroupV2Detail({
>
{i18n('view')}
-
- ) : null}
-
+ ) : undefined
+ }
+ />
);
}
diff --git a/ts/components/conversation/LinkNotification.stories.tsx b/ts/components/conversation/LinkNotification.stories.tsx
new file mode 100644
index 0000000000..fa769ea418
--- /dev/null
+++ b/ts/components/conversation/LinkNotification.stories.tsx
@@ -0,0 +1,16 @@
+// Copyright 2021 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+
+import * as React from 'react';
+
+import { storiesOf } from '@storybook/react';
+import { setup as setupI18n } from '../../../js/modules/i18n';
+import enMessages from '../../../_locales/en/messages.json';
+
+import { LinkNotification } from './LinkNotification';
+
+const story = storiesOf('Components/Conversation/LinkNotification', module);
+
+const i18n = setupI18n('en', enMessages);
+
+story.add('Default', () => );
diff --git a/ts/components/conversation/LinkNotification.tsx b/ts/components/conversation/LinkNotification.tsx
new file mode 100644
index 0000000000..d5a667dafc
--- /dev/null
+++ b/ts/components/conversation/LinkNotification.tsx
@@ -0,0 +1,13 @@
+// Copyright 2021 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+
+import * as React from 'react';
+
+import { SystemMessage } from './SystemMessage';
+import type { LocalizerType } from '../../types/Util';
+
+export const LinkNotification = ({
+ i18n,
+}: Readonly<{ i18n: LocalizerType }>): JSX.Element => (
+
+);
diff --git a/ts/components/conversation/ProfileChangeNotification.tsx b/ts/components/conversation/ProfileChangeNotification.tsx
index d03812d086..9f0ef8ddf9 100644
--- a/ts/components/conversation/ProfileChangeNotification.tsx
+++ b/ts/components/conversation/ProfileChangeNotification.tsx
@@ -1,10 +1,11 @@
-// Copyright 2020 Signal Messenger, LLC
+// Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
import { LocalizerType } from '../../types/Util';
import { ConversationType } from '../../state/ducks/conversations';
+import { SystemMessage } from './SystemMessage';
import { Emojify } from './Emojify';
import {
getStringForProfileChange,
@@ -21,12 +22,5 @@ export function ProfileChangeNotification(props: PropsType): JSX.Element {
const { change, changedContact, i18n } = props;
const message = getStringForProfileChange(change, changedContact, i18n);
- return (
-
- );
+ return } />;
}
diff --git a/ts/components/conversation/ResetSessionNotification.tsx b/ts/components/conversation/ResetSessionNotification.tsx
index 422a27ec3b..e2358e4f52 100644
--- a/ts/components/conversation/ResetSessionNotification.tsx
+++ b/ts/components/conversation/ResetSessionNotification.tsx
@@ -1,14 +1,15 @@
-// Copyright 2018-2020 Signal Messenger, LLC
+// Copyright 2018-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
import { LocalizerType } from '../../types/Util';
+import { SystemMessage } from './SystemMessage';
export type Props = {
i18n: LocalizerType;
};
export const ResetSessionNotification = ({ i18n }: Props): JSX.Element => (
- {i18n('sessionEnded')}
+
);
diff --git a/ts/components/conversation/SafetyNumberNotification.tsx b/ts/components/conversation/SafetyNumberNotification.tsx
index f7c137bfe8..c190c14a52 100644
--- a/ts/components/conversation/SafetyNumberNotification.tsx
+++ b/ts/components/conversation/SafetyNumberNotification.tsx
@@ -1,9 +1,10 @@
-// Copyright 2018-2020 Signal Messenger, LLC
+// Copyright 2018-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
import { Button, ButtonSize, ButtonVariant } from '../Button';
+import { SystemMessage } from './SystemMessage';
import { ContactName } from './ContactName';
import { Intl } from '../Intl';
import { LocalizerType } from '../../types/Util';
@@ -42,32 +43,30 @@ export const SafetyNumberNotification = ({
: 'safetyNumberChanged';
return (
-
-
-
-
-
-
- ,
- ]}
- i18n={i18n}
- />
-
-
-
+
+
+ ,
+ ]}
+ i18n={i18n}
+ />
+ }
+ button={
-
-
+ }
+ />
);
};
diff --git a/ts/components/conversation/SystemMessage.tsx b/ts/components/conversation/SystemMessage.tsx
new file mode 100644
index 0000000000..ffed776037
--- /dev/null
+++ b/ts/components/conversation/SystemMessage.tsx
@@ -0,0 +1,38 @@
+// Copyright 2021 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+
+import React, { ReactNode, forwardRef } from 'react';
+import classNames from 'classnames';
+
+type PropsType = {
+ icon: string;
+ contents: ReactNode;
+ button?: ReactNode;
+ isError?: boolean;
+};
+
+export const SystemMessage = forwardRef(
+ ({ icon, contents, button, isError }, ref) => {
+ return (
+
+
+ {contents}
+
+ {button && (
+
{button}
+ )}
+
+ );
+ }
+);
diff --git a/ts/components/conversation/TimelineItem.tsx b/ts/components/conversation/TimelineItem.tsx
index 30119d5082..cbb29267e8 100644
--- a/ts/components/conversation/TimelineItem.tsx
+++ b/ts/components/conversation/TimelineItem.tsx
@@ -26,6 +26,7 @@ import {
PropsActionsType as DeliveryIssueActionProps,
PropsDataType as DeliveryIssueProps,
} from './DeliveryIssueNotification';
+import { LinkNotification } from './LinkNotification';
import {
ChangeNumberNotification,
PropsData as ChangeNumberNotificationProps,
@@ -245,12 +246,7 @@ export class TimelineItem extends React.PureComponent {
);
} else if (item.type === 'linkNotification') {
- notification = (
-
-
- {i18n('messageHistoryUnsynced')}
-
- );
+ notification = ;
} else if (item.type === 'timerNotification') {
notification = (
diff --git a/ts/components/conversation/TimerNotification.tsx b/ts/components/conversation/TimerNotification.tsx
index d946abaf7d..ddac4dd910 100644
--- a/ts/components/conversation/TimerNotification.tsx
+++ b/ts/components/conversation/TimerNotification.tsx
@@ -2,9 +2,9 @@
// SPDX-License-Identifier: AGPL-3.0-only
import React, { FunctionComponent, ReactNode } from 'react';
-import classNames from 'classnames';
import { ContactName } from './ContactName';
+import { SystemMessage } from './SystemMessage';
import { Intl } from '../Intl';
import { LocalizerType } from '../../types/Util';
import * as expirationTimer from '../../util/expirationTimer';
@@ -94,16 +94,7 @@ export const TimerNotification: FunctionComponent = props => {
break;
}
- return (
-
- );
+ const icon = disabled ? 'timer-disabled' : 'timer';
+
+ return ;
};
diff --git a/ts/components/conversation/UniversalTimerNotification.tsx b/ts/components/conversation/UniversalTimerNotification.tsx
index 9475245b02..97f3ae2793 100644
--- a/ts/components/conversation/UniversalTimerNotification.tsx
+++ b/ts/components/conversation/UniversalTimerNotification.tsx
@@ -3,6 +3,7 @@
import React from 'react';
+import { SystemMessage } from './SystemMessage';
import { LocalizerType } from '../../types/Util';
import * as expirationTimer from '../../util/expirationTimer';
@@ -21,15 +22,11 @@ export const UniversalTimerNotification: React.FC = props => {
const timeValue = expirationTimer.format(i18n, expireTimer);
return (
-
-
-
-
- {i18n('UniversalTimerNotification__text', {
- timeValue,
- })}
-
-
-
+
);
};
diff --git a/ts/components/conversation/UnsupportedMessage.tsx b/ts/components/conversation/UnsupportedMessage.tsx
index 4f65b97712..2910ac2ec9 100644
--- a/ts/components/conversation/UnsupportedMessage.tsx
+++ b/ts/components/conversation/UnsupportedMessage.tsx
@@ -1,9 +1,9 @@
-// Copyright 2019-2020 Signal Messenger, LLC
+// Copyright 2019-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
-import classNames from 'classnames';
+import { SystemMessage } from './SystemMessage';
import { Button, ButtonSize, ButtonVariant } from '../Button';
import { ContactName } from './ContactName';
import { Intl } from '../Intl';
@@ -48,54 +48,47 @@ export const UnsupportedMessage = ({
? 'Message--from-me-unsupported-message-ask-to-resend'
: 'Message--from-me-unsupported-message';
const stringId = isMe ? meStringId : otherStringId;
+ const icon = canProcessNow ? 'unsupported--can-process' : 'unsupported';
return (
-
-
-
+
+ ,
+ ]}
+ i18n={i18n}
/>
-
-
-
- ,
- ]}
- i18n={i18n}
- />
-
-
- {canProcessNow ? null : (
-
-
-
- )}
-
+ }
+ button={
+ canProcessNow ? undefined : (
+
+
+
+ )
+ }
+ />
);
};
diff --git a/ts/components/conversation/VerificationNotification.tsx b/ts/components/conversation/VerificationNotification.tsx
index e69ec5b418..b70d8169ac 100644
--- a/ts/components/conversation/VerificationNotification.tsx
+++ b/ts/components/conversation/VerificationNotification.tsx
@@ -1,9 +1,9 @@
-// Copyright 2018-2020 Signal Messenger, LLC
+// Copyright 2018-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
-// import classNames from 'classnames';
+import { SystemMessage } from './SystemMessage';
import { ContactName } from './ContactName';
import { Intl } from '../Intl';
import { LocalizerType } from '../../types/Util';
@@ -52,35 +52,28 @@ export class VerificationNotification extends React.Component
{
const id = this.getStringId();
return (
-
- ,
- ]}
- i18n={i18n}
- />
-
+ ,
+ ]}
+ i18n={i18n}
+ />
);
}
public render(): JSX.Element {
const { type } = this.props;
- const suffix = type === 'markVerified' ? 'verified' : 'verified-not';
+ const icon = type === 'markVerified' ? 'verified' : 'verified-not';
- return (
-
-
- {this.renderContents()}
-
- );
+ return ;
}
}