213 lines
6.2 KiB
TypeScript
213 lines
6.2 KiB
TypeScript
import type {
|
|
ApiChat, ApiGlobalMessageSearchType, ApiMessage, ApiTopic, ApiUser,
|
|
} from '../../../api/types';
|
|
import type { ActionReturnType, GlobalState, TabArgs } from '../../types';
|
|
|
|
import { GLOBAL_SEARCH_SLICE, GLOBAL_TOPIC_SEARCH_SLICE } from '../../../config';
|
|
import { timestampPlusDay } from '../../../util/dateFormat';
|
|
import { getCurrentTabId } from '../../../util/establishMultitabRole';
|
|
import { buildCollectionByKey } from '../../../util/iteratees';
|
|
import { throttle } from '../../../util/schedulers';
|
|
import { callApi } from '../../../api/gramjs';
|
|
import { addActionHandler, getGlobal, setGlobal } from '../../index';
|
|
import {
|
|
addChats,
|
|
addMessages,
|
|
addUsers,
|
|
updateGlobalSearch,
|
|
updateGlobalSearchFetchingStatus,
|
|
updateGlobalSearchResults,
|
|
updateTopics,
|
|
} from '../../reducers';
|
|
import { selectChat, selectCurrentGlobalSearchQuery, selectTabState } from '../../selectors';
|
|
|
|
const searchThrottled = throttle((cb) => cb(), 500, false);
|
|
|
|
addActionHandler('setGlobalSearchQuery', (global, actions, payload): ActionReturnType => {
|
|
const { query, tabId = getCurrentTabId() } = payload!;
|
|
const { chatId } = selectTabState(global, tabId).globalSearch;
|
|
|
|
if (query && !chatId) {
|
|
void searchThrottled(async () => {
|
|
const result = await callApi('searchChats', { query });
|
|
|
|
global = getGlobal();
|
|
const currentSearchQuery = selectCurrentGlobalSearchQuery(global, tabId);
|
|
if (!result || !currentSearchQuery || (query !== currentSearchQuery)) {
|
|
global = updateGlobalSearchFetchingStatus(global, { chats: false }, tabId);
|
|
setGlobal(global);
|
|
return;
|
|
}
|
|
|
|
const {
|
|
accountChats, accountUsers, globalChats, globalUsers,
|
|
} = result;
|
|
|
|
if (accountChats.length || globalChats.length) {
|
|
global = addChats(global, buildCollectionByKey([...accountChats, ...globalChats], 'id'));
|
|
}
|
|
|
|
if (accountUsers.length || globalUsers.length) {
|
|
global = addUsers(global, buildCollectionByKey([...accountUsers, ...globalUsers], 'id'));
|
|
}
|
|
|
|
global = updateGlobalSearchFetchingStatus(global, { chats: false }, tabId);
|
|
global = updateGlobalSearch(global, {
|
|
localResults: {
|
|
chatIds: accountChats.map(({ id }) => id),
|
|
userIds: accountChats.map(({ id }) => id),
|
|
},
|
|
globalResults: {
|
|
...selectTabState(global, tabId).globalSearch.globalResults,
|
|
chatIds: globalChats.map(({ id }) => id),
|
|
userIds: globalUsers.map(({ id }) => id),
|
|
},
|
|
}, tabId);
|
|
|
|
setGlobal(global);
|
|
});
|
|
}
|
|
});
|
|
|
|
addActionHandler('setGlobalSearchDate', (global, actions, payload): ActionReturnType => {
|
|
const { date, tabId = getCurrentTabId() } = payload!;
|
|
const maxDate = date ? timestampPlusDay(date) : date;
|
|
|
|
global = updateGlobalSearch(global, {
|
|
date,
|
|
query: '',
|
|
resultsByType: {
|
|
...selectTabState(global, tabId).globalSearch.resultsByType,
|
|
text: {
|
|
totalCount: undefined,
|
|
foundIds: [],
|
|
nextOffsetId: 0,
|
|
},
|
|
},
|
|
}, tabId);
|
|
setGlobal(global);
|
|
|
|
const { chatId } = selectTabState(global, tabId).globalSearch;
|
|
const chat = chatId ? selectChat(global, chatId) : undefined;
|
|
searchMessagesGlobal(global, '', 'text', undefined, chat, maxDate, date, tabId);
|
|
});
|
|
|
|
addActionHandler('searchMessagesGlobal', (global, actions, payload): ActionReturnType => {
|
|
const { type, tabId = getCurrentTabId() } = payload;
|
|
const {
|
|
query, resultsByType, chatId, date,
|
|
} = selectTabState(global, tabId).globalSearch;
|
|
const maxDate = date ? timestampPlusDay(date) : date;
|
|
const nextOffsetId = (resultsByType?.[type as ApiGlobalMessageSearchType])?.nextOffsetId;
|
|
|
|
const chat = chatId ? selectChat(global, chatId) : undefined;
|
|
|
|
searchMessagesGlobal(global, query, type, nextOffsetId, chat, maxDate, date, tabId);
|
|
});
|
|
|
|
async function searchMessagesGlobal<T extends GlobalState>(
|
|
global: T,
|
|
query = '', type: ApiGlobalMessageSearchType, offsetRate?: number, chat?: ApiChat, maxDate?: number, minDate?: number,
|
|
...[tabId = getCurrentTabId()]: TabArgs<T>
|
|
) {
|
|
let result: {
|
|
messages: ApiMessage[];
|
|
users: ApiUser[];
|
|
chats: ApiChat[];
|
|
topics?: ApiTopic[];
|
|
totalTopicsCount?: number;
|
|
totalCount: number;
|
|
nextRate: number | undefined;
|
|
} | undefined;
|
|
|
|
if (chat) {
|
|
const localResultRequest = callApi('searchMessagesLocal', {
|
|
chat,
|
|
query,
|
|
type,
|
|
limit: GLOBAL_SEARCH_SLICE,
|
|
offsetId: offsetRate,
|
|
minDate,
|
|
maxDate,
|
|
});
|
|
const topicsRequest = chat.isForum ? callApi('fetchTopics', {
|
|
chat,
|
|
query,
|
|
limit: GLOBAL_TOPIC_SEARCH_SLICE,
|
|
}) : undefined;
|
|
|
|
const [localResult, topics] = await Promise.all([localResultRequest, topicsRequest]);
|
|
|
|
if (localResult) {
|
|
const {
|
|
messages, users, totalCount, nextOffsetId,
|
|
} = localResult;
|
|
|
|
const { topics: localTopics, count } = topics || {};
|
|
|
|
result = {
|
|
topics: localTopics,
|
|
totalTopicsCount: count,
|
|
messages,
|
|
users,
|
|
chats: [],
|
|
totalCount,
|
|
nextRate: nextOffsetId,
|
|
};
|
|
}
|
|
} else {
|
|
result = await callApi('searchMessagesGlobal', {
|
|
query,
|
|
offsetRate,
|
|
limit: GLOBAL_SEARCH_SLICE,
|
|
type,
|
|
maxDate,
|
|
minDate,
|
|
});
|
|
}
|
|
|
|
global = getGlobal();
|
|
const currentSearchQuery = selectCurrentGlobalSearchQuery(global, tabId);
|
|
if (!result || (query !== '' && query !== currentSearchQuery)) {
|
|
global = updateGlobalSearchFetchingStatus(global, { messages: false }, tabId);
|
|
setGlobal(global);
|
|
return;
|
|
}
|
|
|
|
const {
|
|
messages, users, chats, totalCount, nextRate,
|
|
} = result;
|
|
|
|
if (chats.length) {
|
|
global = addChats(global, buildCollectionByKey(chats, 'id'));
|
|
}
|
|
|
|
if (users.length) {
|
|
global = addUsers(global, buildCollectionByKey(users, 'id'));
|
|
}
|
|
|
|
if (messages.length) {
|
|
global = addMessages(global, messages);
|
|
}
|
|
|
|
global = updateGlobalSearchResults(
|
|
global,
|
|
messages,
|
|
totalCount,
|
|
type,
|
|
nextRate,
|
|
tabId,
|
|
);
|
|
|
|
if (result.topics) {
|
|
global = updateTopics(global, chat!.id, result.totalTopicsCount!, result.topics);
|
|
}
|
|
|
|
const sortedTopics = result.topics?.map(({ id }) => id).sort((a, b) => b - a);
|
|
global = updateGlobalSearch(global, {
|
|
foundTopicIds: sortedTopics,
|
|
}, tabId);
|
|
|
|
setGlobal(global);
|
|
}
|