signal-desktop/ts/state/smart/StoryViewer.tsx

176 lines
6.1 KiB
TypeScript
Raw Normal View History

2022-03-04 21:14:52 +00:00
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
import { useSelector } from 'react-redux';
2022-07-06 19:06:20 +00:00
import type { GetConversationByIdType } from '../selectors/conversations';
2022-03-04 21:14:52 +00:00
import type { LocalizerType } from '../../types/Util';
import type { StateType } from '../reducer';
2022-07-06 19:06:20 +00:00
import type { SelectedStoryDataType } from '../ducks/stories';
2022-03-04 21:14:52 +00:00
import { StoryViewer } from '../../components/StoryViewer';
import { ToastType } from '../../types/Toast';
import { useToastActions } from '../ducks/toast';
2022-07-06 19:06:20 +00:00
import { getConversationSelector } from '../selectors/conversations';
2022-03-04 21:14:52 +00:00
import {
getEmojiSkinTone,
2022-10-25 22:18:42 +00:00
getHasStoryViewReceiptSetting,
2022-03-04 21:14:52 +00:00
getPreferredReactionEmoji,
2023-04-18 01:16:41 +00:00
getTextFormattingEnabled,
2022-11-22 22:33:15 +00:00
isInternalUser,
2022-03-04 21:14:52 +00:00
} from '../selectors/items';
2023-04-03 20:16:27 +00:00
import { getIntl, getPlatform } from '../selectors/user';
2022-03-04 21:14:52 +00:00
import { getPreferredBadgeSelector } from '../selectors/badges';
2022-07-06 19:06:20 +00:00
import {
getSelectedStoryData,
getStoryReplies,
getStoryByIdSelector,
getHasAllStoriesUnmuted,
2022-07-06 19:06:20 +00:00
} from '../selectors/stories';
import { isInFullScreenCall } from '../selectors/calling';
2022-11-09 02:38:19 +00:00
import { isSignalConversation } from '../../util/isSignalConversation';
2022-03-04 21:14:52 +00:00
import { renderEmojiPicker } from './renderEmojiPicker';
2022-07-06 19:06:20 +00:00
import { strictAssert } from '../../util/assert';
2022-11-22 22:33:15 +00:00
import { asyncShouldNeverBeCalled } from '../../util/shouldNeverBeCalled';
2022-03-04 21:14:52 +00:00
import { useActions as useEmojisActions } from '../ducks/emojis';
import { useConversationsActions } from '../ducks/conversations';
2022-03-04 21:14:52 +00:00
import { useRecentEmojis } from '../selectors/emojis';
import { useActions as useItemsActions } from '../ducks/items';
2023-02-24 23:18:57 +00:00
import { useAudioPlayerActions } from '../ducks/audioPlayer';
2023-03-07 22:59:44 +00:00
import { useGlobalModalActions } from '../ducks/globalModals';
2022-03-04 21:14:52 +00:00
import { useStoriesActions } from '../ducks/stories';
import { useIsWindowActive } from '../../hooks/useIsWindowActive';
import {
2023-04-18 01:16:41 +00:00
getIsFormattingFlagEnabled,
getIsFormattingSpoilersFlagEnabled,
} from '../selectors/composer';
2022-03-04 21:14:52 +00:00
2022-07-06 19:06:20 +00:00
export function SmartStoryViewer(): JSX.Element | null {
2022-03-04 21:14:52 +00:00
const storiesActions = useStoriesActions();
const { onUseEmoji } = useEmojisActions();
const {
retryMessageSend,
saveAttachment,
showConversation,
toggleHideStories,
} = useConversationsActions();
const { onSetSkinTone } = useItemsActions();
const { showToast } = useToastActions();
2023-03-07 22:59:44 +00:00
const { showContactModal } = useGlobalModalActions();
2022-03-04 21:14:52 +00:00
const isWindowActive = useIsWindowActive();
2022-03-04 21:14:52 +00:00
const i18n = useSelector<StateType, LocalizerType>(getIntl);
2023-04-03 20:16:27 +00:00
const platform = useSelector(getPlatform);
2022-03-04 21:14:52 +00:00
const getPreferredBadge = useSelector(getPreferredBadgeSelector);
const preferredReactionEmoji = useSelector<StateType, ReadonlyArray<string>>(
2022-03-04 21:14:52 +00:00
getPreferredReactionEmoji
);
2022-07-06 19:06:20 +00:00
const selectedStoryData = useSelector<
2022-04-15 00:08:46 +00:00
StateType,
2022-07-06 19:06:20 +00:00
SelectedStoryDataType | undefined
>(getSelectedStoryData);
2022-04-15 00:08:46 +00:00
2022-11-22 22:33:15 +00:00
const internalUser = useSelector<StateType, boolean>(isInternalUser);
2022-07-06 19:06:20 +00:00
strictAssert(selectedStoryData, 'StoryViewer: !selectedStoryData');
const conversationSelector = useSelector<StateType, GetConversationByIdType>(
getConversationSelector
);
const getStoryById = useSelector(getStoryByIdSelector);
2022-03-04 21:14:52 +00:00
const recentEmojis = useRecentEmojis();
const skinTone = useSelector<StateType, number>(getEmojiSkinTone);
2022-04-15 00:08:46 +00:00
const replyState = useSelector(getStoryReplies);
const hasAllStoriesUnmuted = useSelector<StateType, boolean>(
getHasAllStoriesUnmuted
2022-05-06 19:02:44 +00:00
);
2022-03-04 21:14:52 +00:00
const hasActiveCall = useSelector(isInFullScreenCall);
2022-10-25 22:18:42 +00:00
const hasViewReceiptSetting = useSelector<StateType, boolean>(
getHasStoryViewReceiptSetting
);
const isFormattingEnabled = useSelector(getTextFormattingEnabled);
const isFormattingFlagEnabled = useSelector(getIsFormattingFlagEnabled);
const isFormattingSpoilersFlagEnabled = useSelector(
getIsFormattingSpoilersFlagEnabled
);
2023-02-24 23:18:57 +00:00
const { pauseVoiceNotePlayer } = useAudioPlayerActions();
const storyInfo = getStoryById(
conversationSelector,
selectedStoryData.messageId
);
if (!storyInfo) {
return null;
}
const { conversationStory, distributionList, storyView } = storyInfo;
2022-03-04 21:14:52 +00:00
return (
<StoryViewer
2022-07-06 19:06:20 +00:00
currentIndex={selectedStoryData.currentIndex}
distributionList={distributionList}
2022-03-04 21:14:52 +00:00
getPreferredBadge={getPreferredBadge}
2022-07-06 19:06:20 +00:00
group={conversationStory.group}
hasActiveCall={hasActiveCall}
hasAllStoriesUnmuted={hasAllStoriesUnmuted}
2022-10-25 22:18:42 +00:00
hasViewReceiptSetting={hasViewReceiptSetting}
2022-03-04 21:14:52 +00:00
i18n={i18n}
2023-04-03 20:16:27 +00:00
platform={platform}
2022-11-22 22:33:15 +00:00
isInternalUser={internalUser}
isFormattingEnabled={isFormattingEnabled}
isFormattingFlagEnabled={isFormattingFlagEnabled}
isFormattingSpoilersFlagEnabled={isFormattingSpoilersFlagEnabled}
2022-11-09 02:38:19 +00:00
isSignalConversation={isSignalConversation({
id: conversationStory.conversationId,
})}
2022-11-16 22:10:11 +00:00
isWindowActive={isWindowActive}
2022-07-06 19:06:20 +00:00
numStories={selectedStoryData.numStories}
onHideStory={toggleHideStories}
onGoToConversation={senderId => {
2022-06-16 19:12:50 +00:00
showConversation({ conversationId: senderId });
storiesActions.toggleStoriesView();
}}
2022-03-04 21:14:52 +00:00
onReactToStory={async (emoji, story) => {
2022-04-28 22:06:28 +00:00
const { messageId } = story;
storiesActions.reactToStory(emoji, messageId);
2022-03-04 21:14:52 +00:00
}}
onReplyToStory={(message, mentions, timestamp, story) => {
storiesActions.replyToStory(
2022-07-06 19:06:20 +00:00
conversationStory.conversationId,
2022-03-04 21:14:52 +00:00
message,
mentions,
timestamp,
story
);
}}
onSetSkinTone={onSetSkinTone}
onTextTooLong={() => {
showToast({ toastType: ToastType.MessageBodyTooLong });
}}
2022-03-04 21:14:52 +00:00
onUseEmoji={onUseEmoji}
2023-02-24 23:18:57 +00:00
onMediaPlaybackStart={pauseVoiceNotePlayer}
2022-03-04 21:14:52 +00:00
preferredReactionEmoji={preferredReactionEmoji}
recentEmojis={recentEmojis}
renderEmojiPicker={renderEmojiPicker}
2022-04-15 00:08:46 +00:00
replyState={replyState}
retryMessageSend={retryMessageSend}
saveAttachment={internalUser ? saveAttachment : asyncShouldNeverBeCalled}
2023-03-07 22:59:44 +00:00
showContactModal={showContactModal}
showToast={showToast}
2022-03-04 21:14:52 +00:00
skinTone={skinTone}
2022-07-06 19:06:20 +00:00
story={storyView}
2022-08-22 17:44:23 +00:00
storyViewMode={selectedStoryData.storyViewMode}
2022-11-16 22:10:11 +00:00
viewTarget={selectedStoryData.viewTarget}
2022-03-04 21:14:52 +00:00
{...storiesActions}
/>
);
}