Automatic session reset

This commit is contained in:
Scott Nonnenberg 2021-02-18 08:40:26 -08:00 committed by Josh Perez
parent fe187226bb
commit 98e7e65d25
26 changed files with 803 additions and 225 deletions

View file

@ -0,0 +1,25 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { setup as setupI18n } from '../../../js/modules/i18n';
import enMessages from '../../../_locales/en/messages.json';
import { ChatSessionRefreshedDialog } from './ChatSessionRefreshedDialog';
const i18n = setupI18n('en', enMessages);
storiesOf('Components/Conversation/ChatSessionRefreshedDialog', module).add(
'Default',
() => {
return (
<ChatSessionRefreshedDialog
contactSupport={action('contactSupport')}
onClose={action('onClose')}
i18n={i18n}
/>
);
}
);

View file

@ -0,0 +1,57 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
import classNames from 'classnames';
import { LocalizerType } from '../../types/Util';
export type PropsType = {
i18n: LocalizerType;
contactSupport: () => unknown;
onClose: () => unknown;
};
export function ChatSessionRefreshedDialog(
props: PropsType
): React.ReactElement {
const { i18n, contactSupport, onClose } = props;
return (
<div className="module-chat-session-refreshed-dialog">
<div className="module-chat-session-refreshed-dialog__image">
<img
src="images/chat-session-refresh.svg"
height="110"
width="200"
alt=""
/>
</div>
<div className="module-chat-session-refreshed-dialog__title">
{i18n('ChatRefresh--notification')}
</div>
<div className="module-chat-session-refreshed-dialog__description">
{i18n('ChatRefresh--summary')}
</div>
<div className="module-chat-session-refreshed-dialog__buttons">
<button
type="button"
onClick={contactSupport}
className={classNames(
'module-chat-session-refreshed-dialog__button',
'module-chat-session-refreshed-dialog__button--secondary'
)}
>
{i18n('ChatRefresh--contactSupport')}
</button>
<button
type="button"
onClick={onClose}
className="module-chat-session-refreshed-dialog__button"
>
{i18n('Confirmation--confirm')}
</button>
</div>
</div>
);
}

View file

@ -0,0 +1,24 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { setup as setupI18n } from '../../../js/modules/i18n';
import enMessages from '../../../_locales/en/messages.json';
import { ChatSessionRefreshedNotification } from './ChatSessionRefreshedNotification';
const i18n = setupI18n('en', enMessages);
storiesOf(
'Components/Conversation/ChatSessionRefreshedNotification',
module
).add('Default', () => {
return (
<ChatSessionRefreshedNotification
contactSupport={action('contactSupport')}
i18n={i18n}
/>
);
});

View file

@ -0,0 +1,63 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React, { useCallback, useState, ReactElement } from 'react';
import { LocalizerType } from '../../types/Util';
import { ModalHost } from '../ModalHost';
import { ChatSessionRefreshedDialog } from './ChatSessionRefreshedDialog';
type PropsHousekeepingType = {
i18n: LocalizerType;
};
export type PropsActionsType = {
contactSupport: () => unknown;
};
export type PropsType = PropsHousekeepingType & PropsActionsType;
export function ChatSessionRefreshedNotification(
props: PropsType
): ReactElement {
const { contactSupport, i18n } = props;
const [isDialogOpen, setIsDialogOpen] = useState<boolean>(false);
const openDialog = useCallback(() => {
setIsDialogOpen(true);
}, [setIsDialogOpen]);
const closeDialog = useCallback(() => {
setIsDialogOpen(false);
}, [setIsDialogOpen]);
const wrappedContactSupport = useCallback(() => {
setIsDialogOpen(false);
contactSupport();
}, [contactSupport, setIsDialogOpen]);
return (
<div className="module-chat-session-refreshed-notification">
<div className="module-chat-session-refreshed-notification__first-line">
<span className="module-chat-session-refreshed-notification__icon" />
{i18n('ChatRefresh--notification')}
</div>
<button
type="button"
onClick={openDialog}
className="module-chat-session-refreshed-notification__button"
>
{i18n('ChatRefresh--learnMore')}
</button>
{isDialogOpen ? (
<ModalHost onClose={closeDialog}>
<ChatSessionRefreshedDialog
onClose={closeDialog}
contactSupport={wrappedContactSupport}
i18n={i18n}
/>
</ModalHost>
) : null}
</div>
);
}

View file

@ -252,6 +252,8 @@ const actions = () => ({
messageSizeChanged: action('messageSizeChanged'),
startCallingLobby: action('startCallingLobby'),
returnToActiveCall: action('returnToActiveCall'),
contactSupport: action('contactSupport'),
});
const renderItem = (id: string) => (

View file

@ -41,6 +41,7 @@ const getDefaultProps = () => ({
selectMessage: action('selectMessage'),
reactToMessage: action('reactToMessage'),
clearSelectedMessage: action('clearSelectedMessage'),
contactSupport: action('contactSupport'),
replyToMessage: action('replyToMessage'),
retrySend: action('retrySend'),
deleteMessage: action('deleteMessage'),

View file

@ -10,11 +10,14 @@ import {
PropsActions as MessageActionsType,
PropsData as MessageProps,
} from './Message';
import {
CallingNotification,
PropsActionsType as CallingNotificationActionsType,
} from './CallingNotification';
import {
ChatSessionRefreshedNotification,
PropsActionsType as PropsChatSessionRefreshedActionsType,
} from './ChatSessionRefreshedNotification';
import { CallingNotificationType } from '../../util/callingNotification';
import { InlineNotificationWrapper } from './InlineNotificationWrapper';
import {
@ -58,6 +61,10 @@ type CallHistoryType = {
type: 'callHistory';
data: CallingNotificationType;
};
type ChatSessionRefreshedType = {
type: 'chatSessionRefreshed';
data: null;
};
type LinkNotificationType = {
type: 'linkNotification';
data: null;
@ -105,6 +112,7 @@ type ProfileChangeNotificationType = {
export type TimelineItemType =
| CallHistoryType
| ChatSessionRefreshedType
| GroupNotificationType
| GroupV1MigrationType
| GroupV2ChangeType
@ -131,6 +139,7 @@ type PropsLocalType = {
type PropsActionsType = MessageActionsType &
CallingNotificationActionsType &
PropsChatSessionRefreshedActionsType &
UnsupportedMessageActionsType &
SafetyNumberActionsType;
@ -184,6 +193,14 @@ export class TimelineItem extends React.PureComponent<PropsType> {
{...item.data}
/>
);
} else if (item.type === 'chatSessionRefreshed') {
notification = (
<ChatSessionRefreshedNotification
{...this.props}
{...item.data}
i18n={i18n}
/>
);
} else if (item.type === 'linkNotification') {
notification = (
<div className="module-message-unsynced">