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
|
@ -23,7 +23,7 @@
|
||||||
};
|
};
|
||||||
window.SignalContext = {
|
window.SignalContext = {
|
||||||
activeWindowService: {
|
activeWindowService: {
|
||||||
isActive: () => true;
|
isActive: () => true,
|
||||||
registerForActive: noop,
|
registerForActive: noop,
|
||||||
unregisterForActive: noop,
|
unregisterForActive: noop,
|
||||||
registerForChange: noop,
|
registerForChange: noop,
|
||||||
|
|
|
@ -7161,6 +7161,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Stories__toast--sending-reply": {
|
||||||
|
"message": "Sending reply...",
|
||||||
|
"description": "Toast message"
|
||||||
|
},
|
||||||
|
"Stories__toast--sending-reaction": {
|
||||||
|
"message": "Sending reaction...",
|
||||||
|
"description": "Toast message"
|
||||||
|
},
|
||||||
"StoryViewer__pause": {
|
"StoryViewer__pause": {
|
||||||
"message": "Pause",
|
"message": "Pause",
|
||||||
"description": "Aria label for pausing a story"
|
"description": "Aria label for pausing a story"
|
||||||
|
|
|
@ -1108,6 +1108,7 @@ export async function startApp(): Promise<void> {
|
||||||
actionCreators.storyDistributionLists,
|
actionCreators.storyDistributionLists,
|
||||||
store.dispatch
|
store.dispatch
|
||||||
),
|
),
|
||||||
|
toast: bindActionCreators(actionCreators.toast, store.dispatch),
|
||||||
updates: bindActionCreators(actionCreators.updates, store.dispatch),
|
updates: bindActionCreators(actionCreators.updates, store.dispatch),
|
||||||
user: bindActionCreators(actionCreators.user, store.dispatch),
|
user: bindActionCreators(actionCreators.user, store.dispatch),
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,18 +6,20 @@ import React, { useEffect } from 'react';
|
||||||
import { Globals } from '@react-spring/web';
|
import { Globals } from '@react-spring/web';
|
||||||
import classNames from 'classnames';
|
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 { AppViewType } from '../state/ducks/app';
|
||||||
import { Inbox } from './Inbox';
|
import { Inbox } from './Inbox';
|
||||||
import { SmartInstallScreen } from '../state/smart/InstallScreen';
|
import { SmartInstallScreen } from '../state/smart/InstallScreen';
|
||||||
import { StandaloneRegistration } from './StandaloneRegistration';
|
import { StandaloneRegistration } from './StandaloneRegistration';
|
||||||
import { ThemeType } from '../types/Util';
|
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 { usePageVisibility } from '../hooks/usePageVisibility';
|
||||||
import { useReducedMotion } from '../hooks/useReducedMotion';
|
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 = {
|
type PropsType = {
|
||||||
appView: AppViewType;
|
appView: AppViewType;
|
||||||
|
@ -45,6 +47,8 @@ type PropsType = {
|
||||||
executeMenuRole: ExecuteMenuRoleType;
|
executeMenuRole: ExecuteMenuRoleType;
|
||||||
executeMenuAction: (action: MenuActionType) => void;
|
executeMenuAction: (action: MenuActionType) => void;
|
||||||
titleBarDoubleClick: () => void;
|
titleBarDoubleClick: () => void;
|
||||||
|
toastType?: ToastType;
|
||||||
|
hideToast: () => unknown;
|
||||||
} & ComponentProps<typeof Inbox>;
|
} & ComponentProps<typeof Inbox>;
|
||||||
|
|
||||||
export const App = ({
|
export const App = ({
|
||||||
|
@ -56,6 +60,7 @@ export const App = ({
|
||||||
getPreferredBadge,
|
getPreferredBadge,
|
||||||
hasInitialLoadCompleted,
|
hasInitialLoadCompleted,
|
||||||
hideMenuBar,
|
hideMenuBar,
|
||||||
|
hideToast,
|
||||||
i18n,
|
i18n,
|
||||||
isCustomizingPreferredReactions,
|
isCustomizingPreferredReactions,
|
||||||
isFullScreen,
|
isFullScreen,
|
||||||
|
@ -81,6 +86,7 @@ export const App = ({
|
||||||
showWhatsNewModal,
|
showWhatsNewModal,
|
||||||
theme,
|
theme,
|
||||||
titleBarDoubleClick,
|
titleBarDoubleClick,
|
||||||
|
toastType,
|
||||||
verifyConversationsStoppingSend,
|
verifyConversationsStoppingSend,
|
||||||
}: PropsType): JSX.Element => {
|
}: PropsType): JSX.Element => {
|
||||||
let contents;
|
let contents;
|
||||||
|
@ -171,6 +177,7 @@ export const App = ({
|
||||||
'dark-theme': theme === ThemeType.dark,
|
'dark-theme': theme === ThemeType.dark,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
|
<ToastManager hideToast={hideToast} i18n={i18n} toastType={toastType} />
|
||||||
{renderGlobalModalContainer()}
|
{renderGlobalModalContainer()}
|
||||||
{renderCallManager()}
|
{renderCallManager()}
|
||||||
{isShowingStoriesView && renderStories()}
|
{isShowingStoriesView && renderStories()}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import type { EmojiPickDataType } from './emoji/EmojiPicker';
|
||||||
import type { PreferredBadgeSelectorType } from '../state/selectors/badges';
|
import type { PreferredBadgeSelectorType } from '../state/selectors/badges';
|
||||||
import type { RenderEmojiPickerProps } from './conversation/ReactionPicker';
|
import type { RenderEmojiPickerProps } from './conversation/ReactionPicker';
|
||||||
import type { ReplyStateType, StoryViewType } from '../types/Stories';
|
import type { ReplyStateType, StoryViewType } from '../types/Stories';
|
||||||
|
import type { ShowToastActionCreatorType } from '../state/ducks/toast';
|
||||||
import type { ViewStoryActionCreatorType } from '../state/ducks/stories';
|
import type { ViewStoryActionCreatorType } from '../state/ducks/stories';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
import { AnimatedEmojiGalore } from './AnimatedEmojiGalore';
|
import { AnimatedEmojiGalore } from './AnimatedEmojiGalore';
|
||||||
|
@ -24,6 +25,7 @@ import { StoryImage } from './StoryImage';
|
||||||
import { StoryViewDirectionType, StoryViewModeType } from '../types/Stories';
|
import { StoryViewDirectionType, StoryViewModeType } from '../types/Stories';
|
||||||
import { StoryViewsNRepliesModal } from './StoryViewsNRepliesModal';
|
import { StoryViewsNRepliesModal } from './StoryViewsNRepliesModal';
|
||||||
import { Theme } from '../util/theme';
|
import { Theme } from '../util/theme';
|
||||||
|
import { ToastType } from '../state/ducks/toast';
|
||||||
import { getAvatarColor } from '../types/Colors';
|
import { getAvatarColor } from '../types/Colors';
|
||||||
import { getStoryBackground } from '../util/getStoryBackground';
|
import { getStoryBackground } from '../util/getStoryBackground';
|
||||||
import { getStoryDuration } from '../util/getStoryDuration';
|
import { getStoryDuration } from '../util/getStoryDuration';
|
||||||
|
@ -66,6 +68,7 @@ export type PropsType = {
|
||||||
recentEmojis?: Array<string>;
|
recentEmojis?: Array<string>;
|
||||||
renderEmojiPicker: (props: RenderEmojiPickerProps) => JSX.Element;
|
renderEmojiPicker: (props: RenderEmojiPickerProps) => JSX.Element;
|
||||||
replyState?: ReplyStateType;
|
replyState?: ReplyStateType;
|
||||||
|
showToast: ShowToastActionCreatorType;
|
||||||
skinTone?: number;
|
skinTone?: number;
|
||||||
story: StoryViewType;
|
story: StoryViewType;
|
||||||
storyViewMode?: StoryViewModeType;
|
storyViewMode?: StoryViewModeType;
|
||||||
|
@ -105,6 +108,7 @@ export const StoryViewer = ({
|
||||||
recentEmojis,
|
recentEmojis,
|
||||||
renderEmojiPicker,
|
renderEmojiPicker,
|
||||||
replyState,
|
replyState,
|
||||||
|
showToast,
|
||||||
skinTone,
|
skinTone,
|
||||||
story,
|
story,
|
||||||
storyViewMode,
|
storyViewMode,
|
||||||
|
@ -650,12 +654,14 @@ export const StoryViewer = ({
|
||||||
onReactToStory(emoji, story);
|
onReactToStory(emoji, story);
|
||||||
setHasReplyModal(false);
|
setHasReplyModal(false);
|
||||||
setReactionEmoji(emoji);
|
setReactionEmoji(emoji);
|
||||||
|
showToast(ToastType.StoryReact);
|
||||||
}}
|
}}
|
||||||
onReply={(message, mentions, replyTimestamp) => {
|
onReply={(message, mentions, replyTimestamp) => {
|
||||||
if (!isGroupStory) {
|
if (!isGroupStory) {
|
||||||
setHasReplyModal(false);
|
setHasReplyModal(false);
|
||||||
}
|
}
|
||||||
onReplyToStory(message, mentions, replyTimestamp, story);
|
onReplyToStory(message, mentions, replyTimestamp, story);
|
||||||
|
showToast(ToastType.StoryReply);
|
||||||
}}
|
}}
|
||||||
onSetSkinTone={onSetSkinTone}
|
onSetSkinTone={onSetSkinTone}
|
||||||
onTextTooLong={onTextTooLong}
|
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;
|
||||||
|
};
|
|
@ -21,6 +21,7 @@ import { actions as search } from './ducks/search';
|
||||||
import { actions as stickers } from './ducks/stickers';
|
import { actions as stickers } from './ducks/stickers';
|
||||||
import { actions as stories } from './ducks/stories';
|
import { actions as stories } from './ducks/stories';
|
||||||
import { actions as storyDistributionLists } from './ducks/storyDistributionLists';
|
import { actions as storyDistributionLists } from './ducks/storyDistributionLists';
|
||||||
|
import { actions as toast } from './ducks/toast';
|
||||||
import { actions as updates } from './ducks/updates';
|
import { actions as updates } from './ducks/updates';
|
||||||
import { actions as user } from './ducks/user';
|
import { actions as user } from './ducks/user';
|
||||||
import type { ReduxActions } from './types';
|
import type { ReduxActions } from './types';
|
||||||
|
@ -46,6 +47,7 @@ export const actionCreators: ReduxActions = {
|
||||||
stickers,
|
stickers,
|
||||||
stories,
|
stories,
|
||||||
storyDistributionLists,
|
storyDistributionLists,
|
||||||
|
toast,
|
||||||
updates,
|
updates,
|
||||||
user,
|
user,
|
||||||
};
|
};
|
||||||
|
@ -71,6 +73,7 @@ export const mapDispatchToProps = {
|
||||||
...stickers,
|
...stickers,
|
||||||
...stories,
|
...stories,
|
||||||
...storyDistributionLists,
|
...storyDistributionLists,
|
||||||
|
...toast,
|
||||||
...updates,
|
...updates,
|
||||||
...user,
|
...user,
|
||||||
};
|
};
|
||||||
|
|
85
ts/state/ducks/toast.ts
Normal file
85
ts/state/ducks/toast.ts
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
// Copyright 2021 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import { useBoundActions } from '../../hooks/useBoundActions';
|
||||||
|
|
||||||
|
export enum ToastType {
|
||||||
|
MessageBodyTooLong = 'MessageBodyTooLong',
|
||||||
|
StoryReact = 'StoryReact',
|
||||||
|
StoryReply = 'StoryReply',
|
||||||
|
}
|
||||||
|
|
||||||
|
// State
|
||||||
|
|
||||||
|
export type ToastStateType = {
|
||||||
|
toastType?: ToastType;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
|
||||||
|
const HIDE_TOAST = 'toast/HIDE_TOAST';
|
||||||
|
const SHOW_TOAST = 'toast/SHOW_TOAST';
|
||||||
|
|
||||||
|
type HideToastActionType = {
|
||||||
|
type: typeof HIDE_TOAST;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ShowToastActionType = {
|
||||||
|
type: typeof SHOW_TOAST;
|
||||||
|
payload: ToastType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ToastActionType = HideToastActionType | ShowToastActionType;
|
||||||
|
|
||||||
|
// Action Creators
|
||||||
|
|
||||||
|
function hideToast(): HideToastActionType {
|
||||||
|
return {
|
||||||
|
type: HIDE_TOAST,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ShowToastActionCreatorType = (
|
||||||
|
toastType: ToastType
|
||||||
|
) => ShowToastActionType;
|
||||||
|
|
||||||
|
const showToast: ShowToastActionCreatorType = toastType => {
|
||||||
|
return {
|
||||||
|
type: SHOW_TOAST,
|
||||||
|
payload: toastType,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const actions = {
|
||||||
|
hideToast,
|
||||||
|
showToast,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useToastActions = (): typeof actions => useBoundActions(actions);
|
||||||
|
|
||||||
|
// Reducer
|
||||||
|
|
||||||
|
export function getEmptyState(): ToastStateType {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function reducer(
|
||||||
|
state: Readonly<ToastStateType> = getEmptyState(),
|
||||||
|
action: Readonly<ToastActionType>
|
||||||
|
): ToastStateType {
|
||||||
|
if (action.type === HIDE_TOAST) {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
toastType: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action.type === SHOW_TOAST) {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
toastType: action.payload,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ import { getEmptyState as safetyNumber } from './ducks/safetyNumber';
|
||||||
import { getEmptyState as search } from './ducks/search';
|
import { getEmptyState as search } from './ducks/search';
|
||||||
import { getEmptyState as getStoriesEmptyState } from './ducks/stories';
|
import { getEmptyState as getStoriesEmptyState } from './ducks/stories';
|
||||||
import { getEmptyState as getStoryDistributionListsEmptyState } from './ducks/storyDistributionLists';
|
import { getEmptyState as getStoryDistributionListsEmptyState } from './ducks/storyDistributionLists';
|
||||||
|
import { getEmptyState as getToastEmptyState } from './ducks/toast';
|
||||||
import { getEmptyState as updates } from './ducks/updates';
|
import { getEmptyState as updates } from './ducks/updates';
|
||||||
import { getEmptyState as user } from './ducks/user';
|
import { getEmptyState as user } from './ducks/user';
|
||||||
|
|
||||||
|
@ -115,6 +116,7 @@ export function getInitialState({
|
||||||
...getStoryDistributionListsEmptyState(),
|
...getStoryDistributionListsEmptyState(),
|
||||||
distributionLists: storyDistributionLists || [],
|
distributionLists: storyDistributionLists || [],
|
||||||
},
|
},
|
||||||
|
toast: getToastEmptyState(),
|
||||||
updates: updates(),
|
updates: updates(),
|
||||||
user: {
|
user: {
|
||||||
...user(),
|
...user(),
|
||||||
|
|
|
@ -24,6 +24,7 @@ import { reducer as search } from './ducks/search';
|
||||||
import { reducer as stickers } from './ducks/stickers';
|
import { reducer as stickers } from './ducks/stickers';
|
||||||
import { reducer as stories } from './ducks/stories';
|
import { reducer as stories } from './ducks/stories';
|
||||||
import { reducer as storyDistributionLists } from './ducks/storyDistributionLists';
|
import { reducer as storyDistributionLists } from './ducks/storyDistributionLists';
|
||||||
|
import { reducer as toast } from './ducks/toast';
|
||||||
import { reducer as updates } from './ducks/updates';
|
import { reducer as updates } from './ducks/updates';
|
||||||
import { reducer as user } from './ducks/user';
|
import { reducer as user } from './ducks/user';
|
||||||
|
|
||||||
|
@ -49,6 +50,7 @@ export const reducer = combineReducers({
|
||||||
stickers,
|
stickers,
|
||||||
stories,
|
stories,
|
||||||
storyDistributionLists,
|
storyDistributionLists,
|
||||||
|
toast,
|
||||||
updates,
|
updates,
|
||||||
user,
|
user,
|
||||||
});
|
});
|
||||||
|
|
|
@ -89,6 +89,7 @@ const mapStateToProps = (state: StateType) => {
|
||||||
titleBarDoubleClick: (): void => {
|
titleBarDoubleClick: (): void => {
|
||||||
window.titleBarDoubleClick();
|
window.titleBarDoubleClick();
|
||||||
},
|
},
|
||||||
|
toastType: state.toast.toastType,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ import type { StoryViewModeType } from '../../types/Stories';
|
||||||
import type { StateType } from '../reducer';
|
import type { StateType } from '../reducer';
|
||||||
import type { SelectedStoryDataType } from '../ducks/stories';
|
import type { SelectedStoryDataType } from '../ducks/stories';
|
||||||
import { StoryViewer } from '../../components/StoryViewer';
|
import { StoryViewer } from '../../components/StoryViewer';
|
||||||
import { ToastMessageBodyTooLong } from '../../components/ToastMessageBodyTooLong';
|
import { ToastType, useToastActions } from '../ducks/toast';
|
||||||
import { getConversationSelector } from '../selectors/conversations';
|
import { getConversationSelector } from '../selectors/conversations';
|
||||||
import {
|
import {
|
||||||
getEmojiSkinTone,
|
getEmojiSkinTone,
|
||||||
|
@ -26,7 +26,6 @@ import {
|
||||||
getStoryView,
|
getStoryView,
|
||||||
} from '../selectors/stories';
|
} from '../selectors/stories';
|
||||||
import { renderEmojiPicker } from './renderEmojiPicker';
|
import { renderEmojiPicker } from './renderEmojiPicker';
|
||||||
import { showToast } from '../../util/showToast';
|
|
||||||
import { strictAssert } from '../../util/assert';
|
import { strictAssert } from '../../util/assert';
|
||||||
import { useActions as useEmojisActions } from '../ducks/emojis';
|
import { useActions as useEmojisActions } from '../ducks/emojis';
|
||||||
import { useActions as useItemsActions } from '../ducks/items';
|
import { useActions as useItemsActions } from '../ducks/items';
|
||||||
|
@ -39,6 +38,7 @@ export function SmartStoryViewer(): JSX.Element | null {
|
||||||
const { onSetSkinTone, toggleHasAllStoriesMuted } = useItemsActions();
|
const { onSetSkinTone, toggleHasAllStoriesMuted } = useItemsActions();
|
||||||
const { onUseEmoji } = useEmojisActions();
|
const { onUseEmoji } = useEmojisActions();
|
||||||
const { showConversation, toggleHideStories } = useConversationsActions();
|
const { showConversation, toggleHideStories } = useConversationsActions();
|
||||||
|
const { showToast } = useToastActions();
|
||||||
|
|
||||||
const i18n = useSelector<StateType, LocalizerType>(getIntl);
|
const i18n = useSelector<StateType, LocalizerType>(getIntl);
|
||||||
const getPreferredBadge = useSelector(getPreferredBadgeSelector);
|
const getPreferredBadge = useSelector(getPreferredBadgeSelector);
|
||||||
|
@ -100,12 +100,13 @@ export function SmartStoryViewer(): JSX.Element | null {
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
onSetSkinTone={onSetSkinTone}
|
onSetSkinTone={onSetSkinTone}
|
||||||
onTextTooLong={() => showToast(ToastMessageBodyTooLong)}
|
onTextTooLong={() => showToast(ToastType.MessageBodyTooLong)}
|
||||||
onUseEmoji={onUseEmoji}
|
onUseEmoji={onUseEmoji}
|
||||||
preferredReactionEmoji={preferredReactionEmoji}
|
preferredReactionEmoji={preferredReactionEmoji}
|
||||||
recentEmojis={recentEmojis}
|
recentEmojis={recentEmojis}
|
||||||
renderEmojiPicker={renderEmojiPicker}
|
renderEmojiPicker={renderEmojiPicker}
|
||||||
replyState={replyState}
|
replyState={replyState}
|
||||||
|
showToast={showToast}
|
||||||
skinTone={skinTone}
|
skinTone={skinTone}
|
||||||
story={storyView}
|
story={storyView}
|
||||||
storyViewMode={storyViewMode}
|
storyViewMode={storyViewMode}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import type { actions as search } from './ducks/search';
|
||||||
import type { actions as stickers } from './ducks/stickers';
|
import type { actions as stickers } from './ducks/stickers';
|
||||||
import type { actions as stories } from './ducks/stories';
|
import type { actions as stories } from './ducks/stories';
|
||||||
import type { actions as storyDistributionLists } from './ducks/storyDistributionLists';
|
import type { actions as storyDistributionLists } from './ducks/storyDistributionLists';
|
||||||
|
import type { actions as toast } from './ducks/toast';
|
||||||
import type { actions as updates } from './ducks/updates';
|
import type { actions as updates } from './ducks/updates';
|
||||||
import type { actions as user } from './ducks/user';
|
import type { actions as user } from './ducks/user';
|
||||||
|
|
||||||
|
@ -45,6 +46,7 @@ export type ReduxActions = {
|
||||||
stickers: typeof stickers;
|
stickers: typeof stickers;
|
||||||
stories: typeof stories;
|
stories: typeof stories;
|
||||||
storyDistributionLists: typeof storyDistributionLists;
|
storyDistributionLists: typeof storyDistributionLists;
|
||||||
|
toast: typeof toast;
|
||||||
updates: typeof updates;
|
updates: typeof updates;
|
||||||
user: typeof user;
|
user: typeof user;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue