// Copyright 2022 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import Fuse from 'fuse.js'; import React, { useEffect, useState } from 'react'; import classNames from 'classnames'; import type { ConversationType, ShowConversationType, } from '../state/ducks/conversations'; import type { ConversationStoryType, MyStoryType } 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 { ViewUserStoriesActionCreatorType } from '../state/ducks/stories'; import { MyStoryButton } from './MyStoryButton'; import { SearchInput } from './SearchInput'; import { StoryListItem } from './StoryListItem'; import { isNotNil } from '../util/isNotNil'; import { NavSidebarSearchHeader } from './NavSidebar'; const FUSE_OPTIONS: Fuse.IFuseOptions = { getFn: (story, path) => { if (path[0] === 'searchNames' || path === 'searchNames') { return [story.storyView.sender.title, story.storyView.sender.name].filter( isNotNil ); } return story.group?.title ?? ''; }, keys: [ { name: 'searchNames', weight: 1, }, { name: 'group', weight: 1, }, ], threshold: 0.1, }; function search( stories: ReadonlyArray, searchTerm: string ): Array { return new Fuse(stories, FUSE_OPTIONS) .search(searchTerm) .map(result => result.item); } export type PropsType = { getPreferredBadge: PreferredBadgeSelectorType; hiddenStories: Array; i18n: LocalizerType; maxAttachmentSizeInKb: number; me: ConversationType; myStories: Array; onAddStory: (file?: File) => unknown; onMyStoriesClicked: () => unknown; onStoriesSettings: () => unknown; onMediaPlaybackStart: () => void; queueStoryDownload: (storyId: string) => unknown; showConversation: ShowConversationType; showToast: ShowToastAction; stories: Array; theme: ThemeType; toggleHideStories: (conversationId: string) => unknown; viewUserStories: ViewUserStoriesActionCreatorType; }; export function StoriesPane({ getPreferredBadge, hiddenStories, i18n, maxAttachmentSizeInKb, me, myStories, onAddStory, onMyStoriesClicked, onMediaPlaybackStart, queueStoryDownload, showConversation, showToast, stories, theme, toggleHideStories, viewUserStories, }: PropsType): JSX.Element { const [searchTerm, setSearchTerm] = useState(''); const [isShowingHiddenStories, setIsShowingHiddenStories] = useState(false); const [renderedStories, setRenderedStories] = useState>(stories); useEffect(() => { if (searchTerm) { setRenderedStories(search(stories, searchTerm)); } else { setRenderedStories(stories); } }, [searchTerm, stories]); return ( <> { setSearchTerm(event.target.value); }} placeholder={i18n('icu:search')} value={searchTerm} />
{renderedStories.map(story => ( { showConversation({ conversationId }); }} onHideStory={toggleHideStories} onMediaPlaybackStart={onMediaPlaybackStart} queueStoryDownload={queueStoryDownload} story={story.storyView} theme={theme} viewUserStories={viewUserStories} /> ))} {Boolean(hiddenStories.length) && ( <> {isShowingHiddenStories && hiddenStories.map(story => ( { showConversation({ conversationId }); }} onHideStory={toggleHideStories} onMediaPlaybackStart={onMediaPlaybackStart} queueStoryDownload={queueStoryDownload} story={story.storyView} theme={theme} viewUserStories={viewUserStories} /> ))} )} {!stories.length && (
{i18n('icu:Stories__list-empty')}
)}
); }