Page MenuHomePhabricator

D8293.id28330.diff
No OneTemporary

D8293.id28330.diff

diff --git a/lib/shared/search-utils.js b/lib/shared/search-utils.js
--- a/lib/shared/search-utils.js
+++ b/lib/shared/search-utils.js
@@ -229,6 +229,7 @@
onResultsReceived: (
messages: $ReadOnlyArray<RawMessageInfo>,
endReached: boolean,
+ threadID: string,
) => mixed,
cursor?: string,
) => void {
@@ -239,7 +240,7 @@
(query, threadID, onResultsReceived, cursor) => {
const searchMessagesPromise = (async () => {
if (query === '') {
- onResultsReceived([], true);
+ onResultsReceived([], true, threadID);
return;
}
const { messages, endReached } = await callSearchMessages({
@@ -247,7 +248,7 @@
threadID,
cursor,
});
- onResultsReceived(messages, endReached);
+ onResultsReceived(messages, endReached, threadID);
})();
dispatchActionPromise(searchMessagesActionTypes, searchMessagesPromise);
diff --git a/web/search/message-search-state-provider.react.js b/web/search/message-search-state-provider.react.js
--- a/web/search/message-search-state-provider.react.js
+++ b/web/search/message-search-state-provider.react.js
@@ -3,10 +3,22 @@
import invariant from 'invariant';
import * as React from 'react';
+import { useSearchMessages } from 'lib/shared/search-utils.js';
+import { messageTypes } from 'lib/types/message-types-enum.js';
+import type { RawMessageInfo } from 'lib/types/message-types.js';
+
type MessageSearchState = {
+getQuery: (threadID: string) => string,
+setQuery: (query: string, threadID: string) => void,
+clearQuery: (threadID: string) => void,
+ +getSearchResults: (threadID: string) => $ReadOnlyArray<RawMessageInfo>,
+ +appendSearchResult: (
+ $ReadOnlyArray<RawMessageInfo>,
+ threadID: string,
+ ) => void,
+ +getEndReached: (threadID: string) => boolean,
+ +setEndReached: (threadID: string) => void,
+ +searchMessages: (threadID: string) => void,
};
const MessageSearchContext: React.Context<?MessageSearchState> =
@@ -17,28 +29,121 @@
};
function MessageSearchStateProvider(props: Props): React.Node {
- const [queries, setQueries] = React.useState<{
+ const queries = React.useRef<{
[threadID: string]: string,
}>({});
- const setQuery = React.useCallback(
- (query: string, threadID: string) =>
- setQueries(prevQueries => ({ ...prevQueries, [threadID]: query })),
+ const [results, setResults] = React.useState<{
+ [threadID: string]: $ReadOnlyArray<RawMessageInfo>,
+ }>({});
+
+ const endsReached = React.useRef(new Set());
+
+ const lastIDs = React.useRef<{
+ [threadID: string]: string,
+ }>({});
+
+ const setEndReached = React.useCallback((threadID: string) => {
+ endsReached.current.add(threadID);
+ }, []);
+
+ const removeEndReached = React.useCallback(
+ (threadID: string) => endsReached.current.delete(threadID),
[],
);
- const clearQuery = React.useCallback(
- (threadID: string) =>
- setQueries(prevQueries => {
- const { [threadID]: deleted, ...newState } = prevQueries;
- return newState;
- }),
+ const getEndReached = React.useCallback(
+ (threadID: string) => endsReached.current.has(threadID),
[],
);
+ const appendResult = React.useCallback(
+ (result: $ReadOnlyArray<RawMessageInfo>, threadID: string) => {
+ const lastMessageID = oldestMessageID(result);
+ if (lastMessageID) {
+ lastIDs.current[threadID] = lastMessageID;
+ }
+ setResults(prevResults => {
+ const prevThreadResults = prevResults[threadID] ?? [];
+ const newThreadResults = [...prevThreadResults, ...result];
+ return { ...prevResults, [threadID]: newThreadResults };
+ });
+ },
+ [],
+ );
+
+ const clearResults = React.useCallback(
+ (threadID: string) => {
+ loading.current = false;
+ delete lastIDs.current[threadID];
+ removeEndReached(threadID);
+ setResults(prevResults => {
+ const { [threadID]: deleted, ...newState } = prevResults;
+ return newState;
+ });
+ },
+ [removeEndReached],
+ );
+
+ const getResults = React.useCallback(
+ (threadID: string) => results[threadID] ?? [],
+ [results],
+ );
+
const getQuery = React.useCallback(
- (threadID: string) => queries[threadID] ?? '',
- [queries],
+ (threadID: string) => queries.current[threadID] ?? '',
+ [],
+ );
+
+ const setQuery = React.useCallback(
+ (query: string, threadID: string) => {
+ clearResults(threadID);
+ queries.current[threadID] = query;
+ },
+ [clearResults],
+ );
+
+ const clearQuery = React.useCallback(
+ (threadID: string) => {
+ clearResults(threadID);
+ delete queries.current[threadID];
+ },
+ [clearResults],
+ );
+
+ const searchMessagesCall = useSearchMessages();
+
+ const loading = React.useRef(false);
+
+ const appendResults = React.useCallback(
+ (
+ newMessages: $ReadOnlyArray<RawMessageInfo>,
+ end: boolean,
+ threadID: string,
+ ) => {
+ appendResult(newMessages, threadID);
+ if (end) {
+ setEndReached(threadID);
+ }
+ loading.current = false;
+ },
+ [appendResult, setEndReached],
+ );
+
+ const searchMessages = React.useCallback(
+ (threadID: string) => {
+ if (loading.current || endsReached.current.has(threadID)) {
+ return;
+ }
+ loading.current = true;
+ searchMessagesCall(
+ queries.current[threadID],
+ threadID,
+ appendResults,
+ lastIDs.current[threadID],
+ );
+ },
+ [appendResults, endsReached, searchMessagesCall],
);
const state = React.useMemo(
@@ -46,8 +151,22 @@
getQuery,
setQuery,
clearQuery,
+ getSearchResults: getResults,
+ appendSearchResult: appendResult,
+ getEndReached,
+ setEndReached,
+ searchMessages,
}),
- [getQuery, setQuery, clearQuery],
+ [
+ getQuery,
+ setQuery,
+ clearQuery,
+ getResults,
+ appendResult,
+ getEndReached,
+ setEndReached,
+ searchMessages,
+ ],
);
return (
@@ -57,6 +176,18 @@
);
}
+function oldestMessageID(data: $ReadOnlyArray<RawMessageInfo>) {
+ if (!data) {
+ return undefined;
+ }
+ for (let i = data.length - 1; i >= 0; i--) {
+ if (data[i].type === messageTypes.TEXT) {
+ return data[i].id;
+ }
+ }
+ return undefined;
+}
+
function useMessageSearchContext(): MessageSearchState {
const context = React.useContext(MessageSearchContext);
invariant(context, 'MessageSearchContext not found');

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 15, 8:27 PM (21 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2495354
Default Alt Text
D8293.id28330.diff (6 KB)

Event Timeline