Show toast when reacting/replying to a Story
This commit is contained in:
parent
fc98d54326
commit
9ce4b8977d
14 changed files with 228 additions and 9 deletions
|
@ -6,18 +6,20 @@ import React, { useEffect } from 'react';
|
|||
import { Globals } from '@react-spring/web';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import type { ExecuteMenuRoleType } from './TitleBarContainer';
|
||||
import type { LocaleMessagesType } from '../types/I18N';
|
||||
import type { MenuOptionsType, MenuActionType } from '../types/menu';
|
||||
import type { SelectedStoryDataType } from '../state/ducks/stories';
|
||||
import type { ToastType } from '../state/ducks/toast';
|
||||
import { AppViewType } from '../state/ducks/app';
|
||||
import { Inbox } from './Inbox';
|
||||
import { SmartInstallScreen } from '../state/smart/InstallScreen';
|
||||
import { StandaloneRegistration } from './StandaloneRegistration';
|
||||
import { ThemeType } from '../types/Util';
|
||||
import type { LocaleMessagesType } from '../types/I18N';
|
||||
import { TitleBarContainer } from './TitleBarContainer';
|
||||
import { ToastManager } from './ToastManager';
|
||||
import { usePageVisibility } from '../hooks/usePageVisibility';
|
||||
import { useReducedMotion } from '../hooks/useReducedMotion';
|
||||
import type { MenuOptionsType, MenuActionType } from '../types/menu';
|
||||
import { TitleBarContainer } from './TitleBarContainer';
|
||||
import type { ExecuteMenuRoleType } from './TitleBarContainer';
|
||||
import type { SelectedStoryDataType } from '../state/ducks/stories';
|
||||
|
||||
type PropsType = {
|
||||
appView: AppViewType;
|
||||
|
@ -45,6 +47,8 @@ type PropsType = {
|
|||
executeMenuRole: ExecuteMenuRoleType;
|
||||
executeMenuAction: (action: MenuActionType) => void;
|
||||
titleBarDoubleClick: () => void;
|
||||
toastType?: ToastType;
|
||||
hideToast: () => unknown;
|
||||
} & ComponentProps<typeof Inbox>;
|
||||
|
||||
export const App = ({
|
||||
|
@ -56,6 +60,7 @@ export const App = ({
|
|||
getPreferredBadge,
|
||||
hasInitialLoadCompleted,
|
||||
hideMenuBar,
|
||||
hideToast,
|
||||
i18n,
|
||||
isCustomizingPreferredReactions,
|
||||
isFullScreen,
|
||||
|
@ -81,6 +86,7 @@ export const App = ({
|
|||
showWhatsNewModal,
|
||||
theme,
|
||||
titleBarDoubleClick,
|
||||
toastType,
|
||||
verifyConversationsStoppingSend,
|
||||
}: PropsType): JSX.Element => {
|
||||
let contents;
|
||||
|
@ -171,6 +177,7 @@ export const App = ({
|
|||
'dark-theme': theme === ThemeType.dark,
|
||||
})}
|
||||
>
|
||||
<ToastManager hideToast={hideToast} i18n={i18n} toastType={toastType} />
|
||||
{renderGlobalModalContainer()}
|
||||
{renderCallManager()}
|
||||
{isShowingStoriesView && renderStories()}
|
||||
|
|
|
@ -11,6 +11,7 @@ import type { EmojiPickDataType } from './emoji/EmojiPicker';
|
|||
import type { PreferredBadgeSelectorType } from '../state/selectors/badges';
|
||||
import type { RenderEmojiPickerProps } from './conversation/ReactionPicker';
|
||||
import type { ReplyStateType, StoryViewType } from '../types/Stories';
|
||||
import type { ShowToastActionCreatorType } from '../state/ducks/toast';
|
||||
import type { ViewStoryActionCreatorType } from '../state/ducks/stories';
|
||||
import * as log from '../logging/log';
|
||||
import { AnimatedEmojiGalore } from './AnimatedEmojiGalore';
|
||||
|
@ -24,6 +25,7 @@ import { StoryImage } from './StoryImage';
|
|||
import { StoryViewDirectionType, StoryViewModeType } from '../types/Stories';
|
||||
import { StoryViewsNRepliesModal } from './StoryViewsNRepliesModal';
|
||||
import { Theme } from '../util/theme';
|
||||
import { ToastType } from '../state/ducks/toast';
|
||||
import { getAvatarColor } from '../types/Colors';
|
||||
import { getStoryBackground } from '../util/getStoryBackground';
|
||||
import { getStoryDuration } from '../util/getStoryDuration';
|
||||
|
@ -66,6 +68,7 @@ export type PropsType = {
|
|||
recentEmojis?: Array<string>;
|
||||
renderEmojiPicker: (props: RenderEmojiPickerProps) => JSX.Element;
|
||||
replyState?: ReplyStateType;
|
||||
showToast: ShowToastActionCreatorType;
|
||||
skinTone?: number;
|
||||
story: StoryViewType;
|
||||
storyViewMode?: StoryViewModeType;
|
||||
|
@ -105,6 +108,7 @@ export const StoryViewer = ({
|
|||
recentEmojis,
|
||||
renderEmojiPicker,
|
||||
replyState,
|
||||
showToast,
|
||||
skinTone,
|
||||
story,
|
||||
storyViewMode,
|
||||
|
@ -650,12 +654,14 @@ export const StoryViewer = ({
|
|||
onReactToStory(emoji, story);
|
||||
setHasReplyModal(false);
|
||||
setReactionEmoji(emoji);
|
||||
showToast(ToastType.StoryReact);
|
||||
}}
|
||||
onReply={(message, mentions, replyTimestamp) => {
|
||||
if (!isGroupStory) {
|
||||
setHasReplyModal(false);
|
||||
}
|
||||
onReplyToStory(message, mentions, replyTimestamp, story);
|
||||
showToast(ToastType.StoryReply);
|
||||
}}
|
||||
onSetSkinTone={onSetSkinTone}
|
||||
onTextTooLong={onTextTooLong}
|
||||
|
|
52
ts/components/ToastManager.stories.tsx
Normal file
52
ts/components/ToastManager.stories.tsx
Normal file
|
@ -0,0 +1,52 @@
|
|||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import type { Meta, Story } from '@storybook/react';
|
||||
import React from 'react';
|
||||
|
||||
import type { PropsType } from './ToastManager';
|
||||
import enMessages from '../../_locales/en/messages.json';
|
||||
import { ToastManager } from './ToastManager';
|
||||
import { ToastType } from '../state/ducks/toast';
|
||||
import { setupI18n } from '../util/setupI18n';
|
||||
|
||||
const i18n = setupI18n('en', enMessages);
|
||||
|
||||
export default {
|
||||
title: 'Components/ToastManager',
|
||||
component: ToastManager,
|
||||
argTypes: {
|
||||
hideToast: { action: true },
|
||||
i18n: {
|
||||
defaultValue: i18n,
|
||||
},
|
||||
toastType: {
|
||||
defaultValue: undefined,
|
||||
},
|
||||
},
|
||||
} as Meta;
|
||||
|
||||
const Template: Story<PropsType> = args => <ToastManager {...args} />;
|
||||
|
||||
export const UndefinedToast = Template.bind({});
|
||||
UndefinedToast.args = {};
|
||||
|
||||
export const InvalidToast = Template.bind({});
|
||||
InvalidToast.args = {
|
||||
toastType: 'this is a toast that does not exist' as ToastType,
|
||||
};
|
||||
|
||||
export const StoryReact = Template.bind({});
|
||||
StoryReact.args = {
|
||||
toastType: ToastType.StoryReact,
|
||||
};
|
||||
|
||||
export const StoryReply = Template.bind({});
|
||||
StoryReply.args = {
|
||||
toastType: ToastType.StoryReply,
|
||||
};
|
||||
|
||||
export const MessageBodyTooLong = Template.bind({});
|
||||
MessageBodyTooLong.args = {
|
||||
toastType: ToastType.MessageBodyTooLong,
|
||||
};
|
49
ts/components/ToastManager.tsx
Normal file
49
ts/components/ToastManager.tsx
Normal file
|
@ -0,0 +1,49 @@
|
|||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import React from 'react';
|
||||
import type { LocalizerType } from '../types/Util';
|
||||
import { SECOND } from '../util/durations';
|
||||
import { Toast } from './Toast';
|
||||
import { ToastMessageBodyTooLong } from './ToastMessageBodyTooLong';
|
||||
import { ToastType } from '../state/ducks/toast';
|
||||
import { strictAssert } from '../util/assert';
|
||||
|
||||
export type PropsType = {
|
||||
hideToast: () => unknown;
|
||||
i18n: LocalizerType;
|
||||
toastType?: ToastType;
|
||||
};
|
||||
|
||||
export const ToastManager = ({
|
||||
hideToast,
|
||||
i18n,
|
||||
toastType,
|
||||
}: PropsType): JSX.Element | null => {
|
||||
if (toastType === ToastType.MessageBodyTooLong) {
|
||||
return <ToastMessageBodyTooLong i18n={i18n} onClose={hideToast} />;
|
||||
}
|
||||
|
||||
if (toastType === ToastType.StoryReact) {
|
||||
return (
|
||||
<Toast onClose={hideToast} timeout={3 * SECOND}>
|
||||
{i18n('Stories__toast--sending-reaction')}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
if (toastType === ToastType.StoryReply) {
|
||||
return (
|
||||
<Toast onClose={hideToast} timeout={3 * SECOND}>
|
||||
{i18n('Stories__toast--sending-reply')}
|
||||
</Toast>
|
||||
);
|
||||
}
|
||||
|
||||
strictAssert(
|
||||
toastType === undefined,
|
||||
`Unhandled toast of type: ${toastType}`
|
||||
);
|
||||
|
||||
return null;
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue