signal-desktop/ts/components/conversation/TimelineItem.stories.tsx

600 lines
15 KiB
TypeScript
Raw Normal View History

2023-01-03 19:55:46 +00:00
// Copyright 2020 Signal Messenger, LLC
2020-10-30 20:34:04 +00:00
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
import { action } from '@storybook/addon-actions';
import type { Meta } from '@storybook/react';
2020-09-14 19:51:27 +00:00
import { EmojiPicker } from '../emoji/EmojiPicker';
2021-09-18 00:30:08 +00:00
import { setupI18n } from '../../util/setupI18n';
2022-11-16 20:18:02 +00:00
import { DurationInSeconds } from '../../util/durations';
import enMessages from '../../../_locales/en/messages.json';
import type { PropsType as TimelineItemProps } from './TimelineItem';
import { TimelineItem } from './TimelineItem';
2021-06-01 20:45:43 +00:00
import { UniversalTimerNotification } from './UniversalTimerNotification';
import { CallMode } from '../../types/Calling';
2021-08-06 00:17:05 +00:00
import { AvatarColors } from '../../types/Colors';
2021-05-28 19:11:19 +00:00
import { getDefaultConversation } from '../../test-both/helpers/getDefaultConversation';
import { WidthBreakpoint } from '../_util';
import { ThemeType } from '../../types/Util';
2022-11-30 21:47:54 +00:00
import { PaymentEventKind } from '../../types/Payment';
import { ErrorBoundary } from './ErrorBoundary';
const i18n = setupI18n('en', enMessages);
const renderEmojiPicker: TimelineItemProps['renderEmojiPicker'] = ({
onClose,
onPickEmoji,
ref,
}) => (
<EmojiPicker
i18n={setupI18n('en', enMessages)}
skinTone={0}
onSetSkinTone={action('EmojiPicker::onSetSkinTone')}
ref={ref}
onClose={onClose}
onPickEmoji={onPickEmoji}
/>
);
const renderReactionPicker: TimelineItemProps['renderReactionPicker'] = () => (
<div />
);
2020-09-09 02:25:05 +00:00
const renderContact = (conversationId: string) => (
<React.Fragment key={conversationId}>{conversationId}</React.Fragment>
);
2021-06-01 20:45:43 +00:00
const renderUniversalTimerNotification = () => (
2022-11-16 20:18:02 +00:00
<UniversalTimerNotification
i18n={i18n}
expireTimer={DurationInSeconds.HOUR}
/>
2021-06-01 20:45:43 +00:00
);
const getDefaultProps = () => ({
containerElementRef: React.createRef<HTMLElement>(),
containerWidthBreakpoint: WidthBreakpoint.Wide,
conversationId: 'conversation-id',
2021-11-17 21:11:46 +00:00
getPreferredBadge: () => undefined,
id: 'asdf',
isNextItemCallingNotification: false,
2023-03-20 22:23:53 +00:00
isTargeted: false,
interactionMode: 'keyboard' as const,
theme: ThemeType.light,
2023-04-03 20:16:27 +00:00
platform: 'darwin',
2023-03-20 22:23:53 +00:00
targetMessage: action('targetMessage'),
toggleSelectMessage: action('toggleSelectMessage'),
reactToMessage: action('reactToMessage'),
checkForAccount: action('checkForAccount'),
2023-03-20 22:23:53 +00:00
clearTargetedMessage: action('clearTargetedMessage'),
setMessageToEdit: action('setMessageToEdit'),
setQuoteByMessageId: action('setQuoteByMessageId'),
copyMessageText: action('copyMessageText'),
retryDeleteForEveryone: action('retryDeleteForEveryone'),
retryMessageSend: action('retryMessageSend'),
blockGroupLinkRequests: action('blockGroupLinkRequests'),
2021-01-29 22:58:28 +00:00
kickOffAttachmentDownload: action('kickOffAttachmentDownload'),
markAttachmentAsCorrupted: action('markAttachmentAsCorrupted'),
messageExpanded: action('messageExpanded'),
showConversation: action('showConversation'),
2022-05-11 20:59:58 +00:00
openGiftBadge: action('openGiftBadge'),
2022-12-14 18:12:04 +00:00
saveAttachment: action('saveAttachment'),
onOutgoingAudioCallInConversation: action(
'onOutgoingAudioCallInConversation'
),
onOutgoingVideoCallInConversation: action(
'onOutgoingVideoCallInConversation'
),
pushPanelForConversation: action('pushPanelForConversation'),
showContactModal: action('showContactModal'),
2022-12-10 02:02:22 +00:00
showLightbox: action('showLightbox'),
toggleDeleteMessagesModal: action('toggleDeleteMessagesModal'),
2023-03-20 22:23:53 +00:00
toggleForwardMessagesModal: action('toggleForwardMessagesModal'),
2022-12-10 02:02:22 +00:00
showLightboxForViewOnceMedia: action('showLightboxForViewOnceMedia'),
doubleCheckMissingQuoteReference: action('doubleCheckMissingQuoteReference'),
showExpiredIncomingTapToViewToast: action(
'showExpiredIncomingTapToViewToast'
),
showExpiredOutgoingTapToViewToast: action(
'showExpiredIncomingTapToViewToast'
),
scrollToQuotedMessage: action('scrollToQuotedMessage'),
showSpoiler: action('showSpoiler'),
startConversation: action('startConversation'),
returnToActiveCall: action('returnToActiveCall'),
shouldCollapseAbove: false,
shouldCollapseBelow: false,
shouldHideMetadata: false,
shouldRenderDateHeader: false,
toggleSafetyNumberModal: action('toggleSafetyNumberModal'),
now: Date.now(),
2020-09-09 02:25:05 +00:00
renderContact,
2021-06-01 20:45:43 +00:00
renderUniversalTimerNotification,
renderEmojiPicker,
renderReactionPicker,
renderAudioAttachment: () => <div>*AudioAttachment*</div>,
2022-07-06 19:06:20 +00:00
viewStory: action('viewStory'),
2023-03-20 22:23:53 +00:00
onReplyToMessage: action('onReplyToMessage'),
});
2022-06-07 00:48:02 +00:00
export default {
title: 'Components/Conversation/TimelineItem',
} satisfies Meta<TimelineItemProps>;
2022-11-18 00:45:19 +00:00
export function PlainMessage(): JSX.Element {
2022-06-07 00:48:02 +00:00
const item = {
type: 'message',
data: {
id: 'id-1',
direction: 'incoming',
timestamp: Date.now(),
author: {
phoneNumber: '(202) 555-2001',
color: AvatarColors[0],
},
text: '🔥',
},
} as TimelineItemProps['item'];
return <TimelineItem {...getDefaultProps()} item={item} i18n={i18n} />;
2022-11-18 00:45:19 +00:00
}
2022-06-07 00:48:02 +00:00
2022-11-18 00:45:19 +00:00
export function Notification(): JSX.Element {
2022-06-07 00:48:02 +00:00
const items = [
{
type: 'timerNotification',
data: {
phoneNumber: '(202) 555-0000',
2022-11-16 20:18:02 +00:00
expireTimer: DurationInSeconds.MINUTE,
2022-06-07 00:48:02 +00:00
...getDefaultConversation(),
type: 'fromOther',
},
},
2023-05-04 18:04:22 +00:00
{
type: 'timerNotification',
data: {
phoneNumber: '(202) 555-0000',
disabled: true,
...getDefaultConversation(),
type: 'fromOther',
},
},
2022-06-07 00:48:02 +00:00
{
type: 'universalTimerNotification',
data: null,
},
{
type: 'chatSessionRefreshed',
},
2023-04-05 20:48:00 +00:00
{
type: 'contactRemovedNotification',
data: null,
},
2022-06-07 00:48:02 +00:00
{
type: 'safetyNumberNotification',
data: {
isGroup: false,
contact: getDefaultConversation(),
2020-06-04 18:16:19 +00:00
},
2022-06-07 00:48:02 +00:00
},
{
type: 'deliveryIssue',
data: {
sender: getDefaultConversation(),
},
2022-06-07 00:48:02 +00:00
},
{
type: 'changeNumberNotification',
data: {
sender: getDefaultConversation(),
timestamp: Date.now(),
2020-06-04 18:16:19 +00:00
},
2022-06-07 00:48:02 +00:00
},
{
type: 'callHistory',
data: {
// declined incoming audio
callMode: CallMode.Direct,
wasDeclined: true,
wasIncoming: true,
wasVideoCall: false,
endedTime: Date.now(),
},
},
{
type: 'callHistory',
data: {
// declined incoming video
callMode: CallMode.Direct,
wasDeclined: true,
wasIncoming: true,
wasVideoCall: true,
endedTime: Date.now(),
},
},
{
type: 'callHistory',
data: {
// accepted incoming audio
callMode: CallMode.Direct,
acceptedTime: Date.now() - 300,
wasDeclined: false,
wasIncoming: true,
wasVideoCall: false,
endedTime: Date.now(),
},
},
{
type: 'callHistory',
data: {
// accepted incoming video
callMode: CallMode.Direct,
acceptedTime: Date.now() - 400,
wasDeclined: false,
wasIncoming: true,
wasVideoCall: true,
endedTime: Date.now(),
},
},
{
type: 'callHistory',
data: {
// missed (neither accepted nor declined) incoming audio
callMode: CallMode.Direct,
wasDeclined: false,
wasIncoming: true,
wasVideoCall: false,
endedTime: Date.now(),
},
},
{
type: 'callHistory',
data: {
// missed (neither accepted nor declined) incoming video
callMode: CallMode.Direct,
wasDeclined: false,
wasIncoming: true,
wasVideoCall: true,
endedTime: Date.now(),
},
},
{
type: 'callHistory',
data: {
// accepted outgoing audio
callMode: CallMode.Direct,
acceptedTime: Date.now() - 200,
wasDeclined: false,
wasIncoming: false,
wasVideoCall: false,
endedTime: Date.now(),
},
},
{
type: 'callHistory',
data: {
// accepted outgoing video
callMode: CallMode.Direct,
acceptedTime: Date.now() - 200,
wasDeclined: false,
wasIncoming: false,
wasVideoCall: true,
endedTime: Date.now(),
},
},
{
type: 'callHistory',
data: {
// declined outgoing audio
callMode: CallMode.Direct,
wasDeclined: true,
wasIncoming: false,
wasVideoCall: false,
endedTime: Date.now(),
},
},
{
type: 'callHistory',
data: {
// declined outgoing video
callMode: CallMode.Direct,
wasDeclined: true,
wasIncoming: false,
wasVideoCall: true,
endedTime: Date.now(),
},
},
{
type: 'callHistory',
data: {
// unanswered (neither accepted nor declined) outgoing audio
callMode: CallMode.Direct,
wasDeclined: false,
wasIncoming: false,
wasVideoCall: false,
endedTime: Date.now(),
},
},
{
type: 'callHistory',
data: {
// unanswered (neither accepted nor declined) outgoing video
callMode: CallMode.Direct,
wasDeclined: false,
wasIncoming: false,
wasVideoCall: true,
endedTime: Date.now(),
},
},
{
type: 'callHistory',
data: {
// ongoing group call
callMode: CallMode.Group,
conversationId: 'abc123',
creator: {
firstName: 'Luigi',
isMe: false,
title: 'Luigi Mario',
2020-06-04 18:16:19 +00:00
},
2022-06-07 00:48:02 +00:00
ended: false,
deviceCount: 1,
maxDevices: 16,
startedTime: Date.now(),
},
},
{
type: 'callHistory',
data: {
// ongoing group call started by you
callMode: CallMode.Group,
conversationId: 'abc123',
creator: {
firstName: 'Peach',
isMe: true,
title: 'Princess Peach',
2020-06-04 18:16:19 +00:00
},
2022-06-07 00:48:02 +00:00
ended: false,
deviceCount: 1,
maxDevices: 16,
startedTime: Date.now(),
},
},
{
type: 'callHistory',
data: {
// ongoing group call, creator unknown
callMode: CallMode.Group,
conversationId: 'abc123',
ended: false,
deviceCount: 1,
maxDevices: 16,
startedTime: Date.now(),
},
},
{
type: 'callHistory',
data: {
// ongoing and active group call
callMode: CallMode.Group,
activeCallConversationId: 'abc123',
conversationId: 'abc123',
creator: {
firstName: 'Luigi',
isMe: false,
title: 'Luigi Mario',
2020-06-04 18:16:19 +00:00
},
2022-06-07 00:48:02 +00:00
ended: false,
deviceCount: 1,
maxDevices: 16,
startedTime: Date.now(),
},
},
{
type: 'callHistory',
data: {
// ongoing group call, but you're in another one
callMode: CallMode.Group,
activeCallConversationId: 'abc123',
conversationId: 'xyz987',
creator: {
firstName: 'Luigi',
isMe: false,
title: 'Luigi Mario',
2020-06-04 18:16:19 +00:00
},
2022-06-07 00:48:02 +00:00
ended: false,
deviceCount: 1,
maxDevices: 16,
startedTime: Date.now(),
},
},
{
type: 'callHistory',
data: {
// ongoing full group call
callMode: CallMode.Group,
conversationId: 'abc123',
creator: {
firstName: 'Luigi',
isMe: false,
title: 'Luigi Mario',
2021-08-26 20:51:55 +00:00
},
2022-06-07 00:48:02 +00:00
ended: false,
deviceCount: 16,
maxDevices: 16,
startedTime: Date.now(),
},
},
{
type: 'callHistory',
data: {
// finished call
callMode: CallMode.Group,
conversationId: 'abc123',
creator: {
firstName: 'Luigi',
isMe: false,
title: 'Luigi Mario',
2021-08-26 20:51:55 +00:00
},
2022-06-07 00:48:02 +00:00
ended: true,
deviceCount: 0,
maxDevices: 16,
startedTime: Date.now(),
},
},
{
type: 'profileChange',
data: {
change: {
type: 'name',
oldName: 'Fred',
newName: 'John',
2021-08-26 20:51:55 +00:00
},
2022-06-07 00:48:02 +00:00
changedContact: getDefaultConversation(),
},
},
2022-11-30 21:47:54 +00:00
{
type: 'paymentEvent',
data: {
event: {
kind: PaymentEventKind.ActivationRequest,
},
sender: getDefaultConversation(),
conversation: getDefaultConversation(),
},
},
{
type: 'paymentEvent',
data: {
event: {
kind: PaymentEventKind.Activation,
},
sender: getDefaultConversation(),
conversation: getDefaultConversation(),
},
},
{
type: 'paymentEvent',
data: {
event: {
kind: PaymentEventKind.ActivationRequest,
},
sender: getDefaultConversation({
isMe: true,
}),
conversation: getDefaultConversation(),
},
},
{
type: 'paymentEvent',
data: {
event: {
kind: PaymentEventKind.Activation,
},
sender: getDefaultConversation({
isMe: true,
}),
conversation: getDefaultConversation(),
},
},
2022-06-07 00:48:02 +00:00
{
type: 'resetSessionNotification',
data: null,
},
{
type: 'unsupportedMessage',
data: {
canProcessNow: true,
contact: getDefaultConversation(),
2021-08-26 20:51:55 +00:00
},
2022-06-07 00:48:02 +00:00
},
{
type: 'unsupportedMessage',
data: {
canProcessNow: false,
contact: getDefaultConversation(),
2021-08-26 20:51:55 +00:00
},
2022-06-07 00:48:02 +00:00
},
{
type: 'verificationNotification',
data: {
type: 'markVerified',
isLocal: false,
contact: getDefaultConversation(),
2021-08-26 20:51:55 +00:00
},
2022-06-07 00:48:02 +00:00
},
{
type: 'verificationNotification',
data: {
type: 'markVerified',
isLocal: true,
contact: getDefaultConversation(),
2021-08-26 20:51:55 +00:00
},
2022-06-07 00:48:02 +00:00
},
{
type: 'verificationNotification',
data: {
type: 'markNotVerified',
isLocal: false,
contact: getDefaultConversation(),
2021-08-26 20:51:55 +00:00
},
2022-06-07 00:48:02 +00:00
},
{
type: 'verificationNotification',
data: {
2022-06-07 00:48:02 +00:00
type: 'markNotVerified',
isLocal: true,
contact: getDefaultConversation(),
},
2022-06-07 00:48:02 +00:00
},
2023-05-23 21:14:47 +00:00
{
type: 'conversationMerge',
data: {
conversationTitle: 'Alice',
obsoleteConversationTitle: 'Nancy',
obsoleteConversationNumber: '+121255501234',
},
},
2022-06-07 00:48:02 +00:00
];
return (
<>
{items.map((item, index) => (
<React.Fragment key={index}>
<TimelineItem
{...getDefaultProps()}
item={item as TimelineItemProps['item']}
i18n={i18n}
/>
</React.Fragment>
))}
</>
);
2022-11-18 00:45:19 +00:00
}
2022-11-18 00:45:19 +00:00
export function UnknownType(): JSX.Element {
2022-06-07 00:48:02 +00:00
const item = {
type: 'random',
data: {
somethin: 'somethin',
},
2021-12-17 01:14:21 +00:00
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2022-06-07 00:48:02 +00:00
} as any as TimelineItemProps['item'];
return (
<ErrorBoundary i18n={i18n} showDebugLog={action('showDebugLog')}>
<TimelineItem {...getDefaultProps()} item={item} i18n={i18n} />
</ErrorBoundary>
);
2022-11-18 00:45:19 +00:00
}
2022-06-07 00:48:02 +00:00
2022-11-18 00:45:19 +00:00
export function MissingItem(): JSX.Element {
2022-06-07 00:48:02 +00:00
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const item = null as any as TimelineItemProps['item'];
2022-06-07 00:48:02 +00:00
return <TimelineItem {...getDefaultProps()} item={item} i18n={i18n} />;
2022-11-18 00:45:19 +00:00
}