signal-desktop/ts/components/MyStories.tsx

180 lines
6 KiB
TypeScript
Raw Normal View History

2022-07-01 00:52:03 +00:00
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React, { useState } from 'react';
import type { MyStoryType, StoryViewType } from '../types/Stories';
import type { LocalizerType } from '../types/Util';
2022-07-06 19:06:20 +00:00
import type { ViewStoryActionCreatorType } from '../state/ducks/stories';
2022-07-01 00:52:03 +00:00
import { ConfirmationDialog } from './ConfirmationDialog';
import { ContextMenu } from './ContextMenu';
import { StoryViewModeType } from '../types/Stories';
2022-07-01 00:52:03 +00:00
import { MessageTimestamp } from './conversation/MessageTimestamp';
import { StoryDistributionListName } from './StoryDistributionListName';
2022-07-01 00:52:03 +00:00
import { StoryImage } from './StoryImage';
import { Theme } from '../util/theme';
export type PropsType = {
i18n: LocalizerType;
myStories: Array<MyStoryType>;
onBack: () => unknown;
onDelete: (story: StoryViewType) => unknown;
onForward: (storyId: string) => unknown;
onSave: (story: StoryViewType) => unknown;
queueStoryDownload: (storyId: string) => unknown;
2022-07-06 19:06:20 +00:00
viewStory: ViewStoryActionCreatorType;
2022-07-01 00:52:03 +00:00
};
export const MyStories = ({
i18n,
myStories,
onBack,
onDelete,
onForward,
onSave,
queueStoryDownload,
2022-07-06 19:06:20 +00:00
viewStory,
2022-07-01 00:52:03 +00:00
}: PropsType): JSX.Element => {
const [confirmDeleteStory, setConfirmDeleteStory] = useState<
StoryViewType | undefined
>();
return (
<>
{confirmDeleteStory && (
<ConfirmationDialog
actions={[
{
text: i18n('delete'),
action: () => onDelete(confirmDeleteStory),
style: 'negative',
},
]}
i18n={i18n}
onClose={() => setConfirmDeleteStory(undefined)}
>
{i18n('MyStories__delete')}
</ConfirmationDialog>
)}
<div className="Stories__pane__header Stories__pane__header--centered">
<button
aria-label={i18n('back')}
className="Stories__pane__header--back"
onClick={onBack}
type="button"
/>
<div className="Stories__pane__header--title">
{i18n('MyStories__title')}
</div>
</div>
<div className="Stories__pane__list">
{myStories.map(list => (
2022-08-05 01:13:26 +00:00
<div className="MyStories__distribution" key={list.id}>
2022-07-01 00:52:03 +00:00
<div className="MyStories__distribution__title">
<StoryDistributionListName
i18n={i18n}
2022-08-05 01:13:26 +00:00
id={list.id}
name={list.name}
/>
2022-07-01 00:52:03 +00:00
</div>
{list.stories.map(story => (
<div className="MyStories__story" key={story.timestamp}>
{story.attachment && (
<button
aria-label={i18n('MyStories__story')}
className="MyStories__story__preview"
2022-07-06 19:06:20 +00:00
onClick={() =>
2022-07-25 18:55:44 +00:00
viewStory({
storyId: story.messageId,
storyViewMode: StoryViewModeType.Single,
})
2022-07-06 19:06:20 +00:00
}
2022-07-01 00:52:03 +00:00
type="button"
>
<StoryImage
attachment={story.attachment}
2022-08-04 00:38:41 +00:00
firstName={i18n('you')}
2022-07-01 00:52:03 +00:00
i18n={i18n}
2022-08-04 00:38:41 +00:00
isMe
2022-07-01 00:52:03 +00:00
isThumbnail
label={i18n('MyStories__story')}
moduleClassName="MyStories__story__preview"
queueStoryDownload={queueStoryDownload}
storyId={story.messageId}
/>
</button>
)}
<div className="MyStories__story__details">
{story.views === 1
? i18n('MyStories__views--singular', [String(story.views)])
: i18n('MyStories__views--plural', [
String(story.views || 0),
])}
<MessageTimestamp
i18n={i18n}
isRelativeTime
2022-07-01 00:52:03 +00:00
module="MyStories__story__timestamp"
timestamp={story.timestamp}
/>
</div>
<button
aria-label={i18n('MyStories__download')}
className="MyStories__story__download"
onClick={() => {
onSave(story);
}}
type="button"
/>
<ContextMenu
i18n={i18n}
menuOptions={[
2022-07-25 18:55:44 +00:00
{
icon: 'MyStories__icon--forward',
label: i18n('forward'),
onClick: () => {
onForward(story.messageId);
},
},
2022-07-01 00:52:03 +00:00
{
icon: 'MyStories__icon--save',
label: i18n('save'),
onClick: () => {
onSave(story);
},
},
{
2022-07-25 18:55:44 +00:00
icon: 'StoryListItem__icon--info',
label: i18n('StoryListItem__info'),
2022-07-01 00:52:03 +00:00
onClick: () => {
2022-07-25 18:55:44 +00:00
viewStory({
storyId: story.messageId,
storyViewMode: StoryViewModeType.Single,
shouldShowDetailsModal: true,
});
2022-07-01 00:52:03 +00:00
},
},
{
icon: 'MyStories__icon--delete',
label: i18n('delete'),
onClick: () => {
setConfirmDeleteStory(story);
},
},
]}
2022-07-25 18:55:44 +00:00
moduleClassName="MyStories__story__more"
2022-07-01 00:52:03 +00:00
theme={Theme.Dark}
/>
</div>
))}
</div>
))}
</div>
{!myStories.length && (
<div className="Stories__pane__list--empty">
{i18n('Stories__list-empty')}
</div>
)}
</>
);
};