diff --git a/lib/hooks/search-sidebars.js b/lib/hooks/search-sidebars.js new file mode 100644 --- /dev/null +++ b/lib/hooks/search-sidebars.js @@ -0,0 +1,51 @@ +// @flow + +import * as React from 'react'; + +import { sidebarInfoSelector } from '../selectors/thread-selectors'; +import type { SidebarInfo, ThreadInfo } from '../types/thread-types'; +import { useSelector } from '../utils/redux-utils'; + +function useSearchSidebars( + threadInfo: ThreadInfo, +): { + listData: $ReadOnlyArray, + searchState: { text: string, results: Set }, + setSearchState: ( + searchState: + | { + text: string, + results: Set, + } + | ((state: { text: string, results: Set }) => { + text: string, + results: Set, + }), + ) => void, +} { + const [searchState, setSearchState] = React.useState({ + text: '', + results: new Set(), + }); + + const sidebarInfos = useSelector( + state => sidebarInfoSelector(state)[threadInfo.id] ?? [], + ); + + const listData = React.useMemo(() => { + if (!searchState.text) { + return sidebarInfos; + } + return sidebarInfos.filter(sidebarInfo => + searchState.results.has(sidebarInfo.threadInfo.id), + ); + }, [sidebarInfos, searchState]); + + return React.useMemo(() => ({ listData, searchState, setSearchState }), [ + listData, + setSearchState, + searchState, + ]); +} + +export { useSearchSidebars }; diff --git a/native/chat/sidebar-list-modal.react.js b/native/chat/sidebar-list-modal.react.js --- a/native/chat/sidebar-list-modal.react.js +++ b/native/chat/sidebar-list-modal.react.js @@ -3,6 +3,7 @@ import * as React from 'react'; import { TextInput, FlatList, StyleSheet } from 'react-native'; +import { useSearchSidebars } from 'lib/hooks/search-sidebars'; import { sidebarInfoSelector } from 'lib/selectors/thread-selectors'; import SearchIndex from 'lib/shared/search-index'; import { threadSearchText } from 'lib/shared/thread-utils'; @@ -35,24 +36,13 @@ }; function SidebarListModal(props: Props): React.Node { const threadID = props.route.params.threadInfo.id; + const { listData, searchState, setSearchState } = useSearchSidebars( + props.route.params.threadInfo, + ); const sidebarInfos = useSelector( state => sidebarInfoSelector(state)[threadID] ?? [], ); - const [searchState, setSearchState] = React.useState({ - text: '', - results: new Set(), - }); - - const listData = React.useMemo(() => { - if (!searchState.text) { - return sidebarInfos; - } - return sidebarInfos.filter(({ threadInfo }) => - searchState.results.has(threadInfo.id), - ); - }, [sidebarInfos, searchState]); - const userInfos = useSelector(state => state.userStore.userInfos); const viewerID = useSelector( state => state.currentUserInfo && state.currentUserInfo.id, @@ -73,7 +63,7 @@ ...curState, results: new Set(searchIndex.getSearchResults(curState.text)), })); - }, [searchIndex]); + }, [searchIndex, setSearchState]); const onChangeSearchText = React.useCallback( (searchText: string) => @@ -81,7 +71,7 @@ text: searchText, results: new Set(searchIndex.getSearchResults(searchText)), }), - [searchIndex], + [searchIndex, setSearchState], ); const searchTextInputRef = React.useRef(); @@ -111,7 +101,7 @@ } navigateToThread({ threadInfo }); }, - [navigateToThread], + [navigateToThread, setSearchState], ); const renderItem = React.useCallback( diff --git a/web/modals/chat/sidebar-list-modal.react.js b/web/modals/chat/sidebar-list-modal.react.js --- a/web/modals/chat/sidebar-list-modal.react.js +++ b/web/modals/chat/sidebar-list-modal.react.js @@ -5,6 +5,7 @@ import classNames from 'classnames'; import * as React from 'react'; +import { useSearchSidebars } from 'lib/hooks/search-sidebars'; import { sidebarInfoSelector } from 'lib/selectors/thread-selectors'; import SearchIndex from 'lib/shared/search-index'; import { threadSearchText } from 'lib/shared/thread-utils'; @@ -24,10 +25,9 @@ function SidebarListModal(props: Props): React.Node { const { threadInfo } = props; - const [searchState, setSearchState] = React.useState({ - text: '', - results: new Set(), - }); + const { listData, searchState, setSearchState } = useSearchSidebars( + threadInfo, + ); const { popModal } = useModalContext(); const sidebarInfos = useSelector( @@ -35,15 +35,6 @@ ); const userInfos = useSelector(state => state.userStore.userInfos); - const listData = React.useMemo(() => { - if (!searchState.text) { - return sidebarInfos; - } - return sidebarInfos.filter(sidebarInfo => - searchState.results.has(sidebarInfo.threadInfo.id), - ); - }, [sidebarInfos, searchState]); - const sidebars = React.useMemo( () => listData.map(item => ( @@ -81,7 +72,7 @@ ...curState, results: new Set(searchIndex.getSearchResults(curState.text)), })); - }, [searchIndex]); + }, [searchIndex, setSearchState]); const onChangeSearchText = React.useCallback( (event: SyntheticEvent) => { @@ -91,15 +82,15 @@ results: new Set(searchIndex.getSearchResults(searchText)), }); }, - [searchIndex], + [searchIndex, setSearchState], ); const clearQuery = React.useCallback( (event: SyntheticEvent) => { event.preventDefault(); - setSearchState({ text: '', results: [] }); + setSearchState({ text: '', results: new Set() }); }, - [], + [setSearchState], ); let clearQueryButton = null;