217 lines
7 KiB
TypeScript
217 lines
7 KiB
TypeScript
// Copyright 2022 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
import React, { useState } from 'react';
|
|
import type {
|
|
ConversationType,
|
|
ShowConversationType,
|
|
} from '../state/ducks/conversations';
|
|
import type {
|
|
ConversationStoryType,
|
|
MyStoryType,
|
|
StoryViewType,
|
|
} from '../types/Stories';
|
|
import type { LocalizerType, ThemeType } from '../types/Util';
|
|
import type { PreferredBadgeSelectorType } from '../state/selectors/badges';
|
|
import type { ShowToastAction } from '../state/ducks/toast';
|
|
import type {
|
|
AddStoryData,
|
|
ViewUserStoriesActionCreatorType,
|
|
ViewStoryActionCreatorType,
|
|
} from '../state/ducks/stories';
|
|
import { MyStories } from './MyStories';
|
|
import { StoriesPane } from './StoriesPane';
|
|
import { NavSidebar, NavSidebarActionButton } from './NavSidebar';
|
|
import { StoriesAddStoryButton } from './StoriesAddStoryButton';
|
|
import { ContextMenu } from './ContextMenu';
|
|
import type { UnreadStats } from '../util/countUnreadStats';
|
|
|
|
export type PropsType = {
|
|
addStoryData: AddStoryData;
|
|
otherTabsUnreadStats: UnreadStats;
|
|
deleteStoryForEveryone: (story: StoryViewType) => unknown;
|
|
getPreferredBadge: PreferredBadgeSelectorType;
|
|
hasFailedStorySends: boolean;
|
|
hasPendingUpdate: boolean;
|
|
hasViewReceiptSetting: boolean;
|
|
hiddenStories: Array<ConversationStoryType>;
|
|
i18n: LocalizerType;
|
|
isStoriesSettingsVisible: boolean;
|
|
isViewingStory: boolean;
|
|
maxAttachmentSizeInKb: number;
|
|
me: ConversationType;
|
|
myStories: Array<MyStoryType>;
|
|
navTabsCollapsed: boolean;
|
|
onForwardStory: (storyId: string) => unknown;
|
|
onSaveStory: (story: StoryViewType) => unknown;
|
|
onToggleNavTabsCollapse: (navTabsCollapsed: boolean) => void;
|
|
onMediaPlaybackStart: () => void;
|
|
preferredLeftPaneWidth: number;
|
|
preferredWidthFromStorage: number;
|
|
queueStoryDownload: (storyId: string) => unknown;
|
|
renderStoryCreator: () => JSX.Element;
|
|
retryMessageSend: (messageId: string) => unknown;
|
|
savePreferredLeftPaneWidth: (preferredLeftPaneWidth: number) => void;
|
|
setAddStoryData: (data: AddStoryData) => unknown;
|
|
showConversation: ShowConversationType;
|
|
showStoriesSettings: () => unknown;
|
|
showToast: ShowToastAction;
|
|
stories: Array<ConversationStoryType>;
|
|
theme: ThemeType;
|
|
toggleHideStories: (conversationId: string) => unknown;
|
|
viewStory: ViewStoryActionCreatorType;
|
|
viewUserStories: ViewUserStoriesActionCreatorType;
|
|
};
|
|
|
|
export function StoriesTab({
|
|
addStoryData,
|
|
otherTabsUnreadStats,
|
|
deleteStoryForEveryone,
|
|
getPreferredBadge,
|
|
hasFailedStorySends,
|
|
hasPendingUpdate,
|
|
hasViewReceiptSetting,
|
|
hiddenStories,
|
|
i18n,
|
|
maxAttachmentSizeInKb,
|
|
me,
|
|
myStories,
|
|
navTabsCollapsed,
|
|
onForwardStory,
|
|
onSaveStory,
|
|
onToggleNavTabsCollapse,
|
|
onMediaPlaybackStart,
|
|
preferredLeftPaneWidth,
|
|
queueStoryDownload,
|
|
renderStoryCreator,
|
|
retryMessageSend,
|
|
savePreferredLeftPaneWidth,
|
|
setAddStoryData,
|
|
showConversation,
|
|
showStoriesSettings,
|
|
showToast,
|
|
stories,
|
|
theme,
|
|
toggleHideStories,
|
|
viewStory,
|
|
viewUserStories,
|
|
}: PropsType): JSX.Element {
|
|
const [isMyStories, setIsMyStories] = useState(false);
|
|
|
|
function onAddStory(file?: File) {
|
|
if (file) {
|
|
setAddStoryData({ type: 'Media', file });
|
|
} else {
|
|
setAddStoryData({ type: 'Text' });
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="Stories">
|
|
{addStoryData && renderStoryCreator()}
|
|
{isMyStories && myStories.length ? (
|
|
<MyStories
|
|
otherTabsUnreadStats={otherTabsUnreadStats}
|
|
hasFailedStorySends={hasFailedStorySends}
|
|
hasPendingUpdate={hasPendingUpdate}
|
|
hasViewReceiptSetting={hasViewReceiptSetting}
|
|
i18n={i18n}
|
|
myStories={myStories}
|
|
navTabsCollapsed={navTabsCollapsed}
|
|
onBack={() => setIsMyStories(false)}
|
|
onDelete={deleteStoryForEveryone}
|
|
onForward={onForwardStory}
|
|
onSave={onSaveStory}
|
|
onMediaPlaybackStart={onMediaPlaybackStart}
|
|
onToggleNavTabsCollapse={onToggleNavTabsCollapse}
|
|
preferredLeftPaneWidth={preferredLeftPaneWidth}
|
|
queueStoryDownload={queueStoryDownload}
|
|
retryMessageSend={retryMessageSend}
|
|
savePreferredLeftPaneWidth={savePreferredLeftPaneWidth}
|
|
theme={theme}
|
|
viewStory={viewStory}
|
|
/>
|
|
) : (
|
|
<NavSidebar
|
|
title="Stories"
|
|
i18n={i18n}
|
|
hasFailedStorySends={hasFailedStorySends}
|
|
hasPendingUpdate={hasPendingUpdate}
|
|
navTabsCollapsed={navTabsCollapsed}
|
|
onToggleNavTabsCollapse={onToggleNavTabsCollapse}
|
|
preferredLeftPaneWidth={preferredLeftPaneWidth}
|
|
requiresFullWidth
|
|
savePreferredLeftPaneWidth={savePreferredLeftPaneWidth}
|
|
otherTabsUnreadStats={otherTabsUnreadStats}
|
|
actions={
|
|
<>
|
|
<StoriesAddStoryButton
|
|
i18n={i18n}
|
|
maxAttachmentSizeInKb={maxAttachmentSizeInKb}
|
|
moduleClassName="Stories__pane__add-story"
|
|
onAddStory={onAddStory}
|
|
showToast={showToast}
|
|
/>
|
|
<ContextMenu
|
|
i18n={i18n}
|
|
menuOptions={[
|
|
{
|
|
label: i18n('icu:StoriesSettings__context-menu'),
|
|
onClick: showStoriesSettings,
|
|
},
|
|
]}
|
|
moduleClassName="Stories__pane__settings"
|
|
popperOptions={{
|
|
placement: 'bottom',
|
|
strategy: 'absolute',
|
|
}}
|
|
portalToRoot
|
|
>
|
|
{({ openMenu, onKeyDown }) => {
|
|
return (
|
|
<NavSidebarActionButton
|
|
onClick={openMenu}
|
|
onKeyDown={onKeyDown}
|
|
icon={<span className="StoriesTab__MoreActionsIcon" />}
|
|
label={i18n('icu:StoriesTab__MoreActionsLabel')}
|
|
/>
|
|
);
|
|
}}
|
|
</ContextMenu>
|
|
</>
|
|
}
|
|
>
|
|
<StoriesPane
|
|
getPreferredBadge={getPreferredBadge}
|
|
hiddenStories={hiddenStories}
|
|
i18n={i18n}
|
|
maxAttachmentSizeInKb={maxAttachmentSizeInKb}
|
|
me={me}
|
|
myStories={myStories}
|
|
onAddStory={onAddStory}
|
|
onMyStoriesClicked={() => {
|
|
if (myStories.length) {
|
|
setIsMyStories(true);
|
|
} else {
|
|
setAddStoryData({ type: 'Text' });
|
|
}
|
|
}}
|
|
onStoriesSettings={showStoriesSettings}
|
|
onMediaPlaybackStart={onMediaPlaybackStart}
|
|
queueStoryDownload={queueStoryDownload}
|
|
showConversation={showConversation}
|
|
showToast={showToast}
|
|
stories={stories}
|
|
theme={theme}
|
|
toggleHideStories={toggleHideStories}
|
|
viewUserStories={viewUserStories}
|
|
/>
|
|
</NavSidebar>
|
|
)}
|
|
<div className="Stories__placeholder">
|
|
<div className="Stories__placeholder__stories" />
|
|
{i18n('icu:Stories__placeholder--text')}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|