Changeset View
Changeset View
Standalone View
Standalone View
web/modals/search/message-search-modal.react.js
Show All 14 Lines | |||||
import Button from '../../components/button.react.js'; | import Button from '../../components/button.react.js'; | ||||
import MessageResult from '../../components/message-result.react.js'; | import MessageResult from '../../components/message-result.react.js'; | ||||
import Search from '../../components/search.react.js'; | import Search from '../../components/search.react.js'; | ||||
import LoadingIndicator from '../../loading-indicator.react.js'; | import LoadingIndicator from '../../loading-indicator.react.js'; | ||||
import { useMessageSearchContext } from '../../search/message-search-state-provider.react.js'; | import { useMessageSearchContext } from '../../search/message-search-state-provider.react.js'; | ||||
import Modal from '../modal.react.js'; | import Modal from '../modal.react.js'; | ||||
type ContentProps = { | type ContentProps = { | ||||
+query: string, | |||||
+threadInfo: ThreadInfo, | +threadInfo: ThreadInfo, | ||||
}; | }; | ||||
function MessageSearchModalContent(props: ContentProps): React.Node { | function MessageSearchModal(props: ContentProps): React.Node { | ||||
const { query, threadInfo } = props; | const { threadInfo } = props; | ||||
const [lastID, setLastID] = React.useState(); | const [lastID, setLastID] = React.useState(); | ||||
const [searchResults, setSearchResults] = React.useState([]); | const [searchResults, setSearchResults] = React.useState([]); | ||||
const [endReached, setEndReached] = React.useState(false); | const [endReached, setEndReached] = React.useState(false); | ||||
const { getQuery, setQuery, clearQuery } = useMessageSearchContext(); | |||||
const query = React.useMemo( | |||||
() => getQuery(threadInfo.id), | |||||
[getQuery, threadInfo.id], | |||||
); | |||||
const appendSearchResults = React.useCallback( | const appendSearchResults = React.useCallback( | ||||
(newMessages: $ReadOnlyArray<RawMessageInfo>, end: boolean) => { | (newMessages: $ReadOnlyArray<RawMessageInfo>, end: boolean) => { | ||||
setSearchResults(oldMessages => [...oldMessages, ...newMessages]); | setSearchResults(oldMessages => [...oldMessages, ...newMessages]); | ||||
setEndReached(end); | setEndReached(end); | ||||
}, | }, | ||||
[], | [], | ||||
); | ); | ||||
▲ Show 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | const footer = React.useMemo(() => { | ||||
} | } | ||||
return ( | return ( | ||||
<div className={css.footer}> | <div className={css.footer}> | ||||
No results. Please try using different keywords to refine your search | No results. Please try using different keywords to refine your search | ||||
</div> | </div> | ||||
); | ); | ||||
}, [query, endReached, modifiedItems.length]); | }, [query, endReached, modifiedItems.length]); | ||||
return ( | |||||
<div className={css.content} ref={messageContainerRef}> | |||||
{messages} | |||||
{footer} | |||||
</div> | |||||
); | |||||
} | |||||
function oldestMessageID(data: $ReadOnlyArray<ChatMessageItem>) { | |||||
for (let i = data.length - 1; i >= 0; i--) { | |||||
if (data[i].itemType === 'message' && data[i].messageInfo.id) { | |||||
return data[i].messageInfo.id; | |||||
} | |||||
} | |||||
return undefined; | |||||
} | |||||
type Props = { | |||||
+threadInfo: ThreadInfo, | |||||
}; | |||||
function MessageSearchModal(props: Props): React.Node { | |||||
const { threadInfo } = props; | |||||
const { popModal } = useModalContext(); | |||||
const { getQuery, setQuery, clearQuery } = useMessageSearchContext(); | |||||
const query = React.useMemo( | |||||
() => getQuery(threadInfo.id), | |||||
[getQuery, threadInfo.id], | |||||
); | |||||
const [input, setInput] = React.useState(query); | const [input, setInput] = React.useState(query); | ||||
const onPressSearch = React.useCallback( | const onPressSearch = React.useCallback( | ||||
() => setQuery(input, threadInfo.id), | () => setQuery(input, threadInfo.id), | ||||
[setQuery, input, threadInfo.id], | [setQuery, input, threadInfo.id], | ||||
); | ); | ||||
const { uiName } = useResolvedThreadInfo(threadInfo); | |||||
const searchPlaceholder = `Searching in ${uiName}`; | |||||
const clearQueryWrapper = React.useCallback( | const clearQueryWrapper = React.useCallback( | ||||
() => clearQuery(threadInfo.id), | () => clearQuery(threadInfo.id), | ||||
[clearQuery, threadInfo.id], | [clearQuery, threadInfo.id], | ||||
); | ); | ||||
const onKeyDown = React.useCallback( | const onKeyDown = React.useCallback( | ||||
event => { | event => { | ||||
if (event.key === 'Enter') { | if (event.key === 'Enter') { | ||||
onPressSearch(); | onPressSearch(); | ||||
} | } | ||||
}, | }, | ||||
[onPressSearch], | [onPressSearch], | ||||
); | ); | ||||
const { uiName } = useResolvedThreadInfo(threadInfo); | |||||
const searchPlaceholder = `Searching in ${uiName}`; | |||||
const { popModal } = useModalContext(); | |||||
return ( | return ( | ||||
<Modal name="Search Message" onClose={popModal} size="large"> | <Modal name="Search Message" onClose={popModal} size="large"> | ||||
<div className={css.container}> | <div className={css.container}> | ||||
<div className={css.header}> | <div className={css.header}> | ||||
<Search | <Search | ||||
onChangeText={setInput} | onChangeText={setInput} | ||||
searchText={input} | searchText={input} | ||||
placeholder={searchPlaceholder} | placeholder={searchPlaceholder} | ||||
onClearText={clearQueryWrapper} | onClearText={clearQueryWrapper} | ||||
onKeyDown={onKeyDown} | onKeyDown={onKeyDown} | ||||
/> | /> | ||||
<Button | <Button | ||||
onClick={onPressSearch} | onClick={onPressSearch} | ||||
variant="filled" | variant="filled" | ||||
className={css.button} | className={css.button} | ||||
> | > | ||||
Search | Search | ||||
</Button> | </Button> | ||||
</div> | </div> | ||||
<MessageSearchModalContent threadInfo={threadInfo} query={query} /> | <div className={css.content} ref={messageContainerRef}> | ||||
{messages} | |||||
{footer} | |||||
</div> | |||||
</div> | </div> | ||||
</Modal> | </Modal> | ||||
); | ); | ||||
} | } | ||||
function oldestMessageID(data: $ReadOnlyArray<ChatMessageItem>) { | |||||
for (let i = data.length - 1; i >= 0; i--) { | |||||
if (data[i].itemType === 'message' && data[i].messageInfo.id) { | |||||
return data[i].messageInfo.id; | |||||
} | |||||
} | |||||
return undefined; | |||||
} | |||||
export default MessageSearchModal; | export default MessageSearchModal; |