116 lines
2.6 KiB
TypeScript
116 lines
2.6 KiB
TypeScript
|
|
import {
|
||
|
|
IEventWithRoomId,
|
||
|
|
IResultContext,
|
||
|
|
ISearchRequestBody,
|
||
|
|
ISearchResponse,
|
||
|
|
ISearchResult,
|
||
|
|
SearchOrderBy,
|
||
|
|
} from 'matrix-js-sdk';
|
||
|
|
import { useCallback } from 'react';
|
||
|
|
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
||
|
|
|
||
|
|
export type ResultItem = {
|
||
|
|
rank: number;
|
||
|
|
event: IEventWithRoomId;
|
||
|
|
context: IResultContext;
|
||
|
|
};
|
||
|
|
|
||
|
|
export type ResultGroup = {
|
||
|
|
roomId: string;
|
||
|
|
items: ResultItem[];
|
||
|
|
};
|
||
|
|
|
||
|
|
export type SearchResult = {
|
||
|
|
nextToken?: string;
|
||
|
|
highlights: string[];
|
||
|
|
groups: ResultGroup[];
|
||
|
|
};
|
||
|
|
|
||
|
|
const groupSearchResult = (results: ISearchResult[]): ResultGroup[] => {
|
||
|
|
const groups: ResultGroup[] = [];
|
||
|
|
|
||
|
|
results.forEach((item) => {
|
||
|
|
const roomId = item.result.room_id;
|
||
|
|
const resultItem: ResultItem = {
|
||
|
|
rank: item.rank,
|
||
|
|
event: item.result,
|
||
|
|
context: item.context,
|
||
|
|
};
|
||
|
|
|
||
|
|
const lastAddedGroup: ResultGroup | undefined = groups[groups.length - 1];
|
||
|
|
if (lastAddedGroup && roomId === lastAddedGroup.roomId) {
|
||
|
|
lastAddedGroup.items.push(resultItem);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
groups.push({
|
||
|
|
roomId,
|
||
|
|
items: [resultItem],
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
return groups;
|
||
|
|
};
|
||
|
|
|
||
|
|
const parseSearchResult = (result: ISearchResponse): SearchResult => {
|
||
|
|
const roomEvents = result.search_categories.room_events;
|
||
|
|
|
||
|
|
const searchResult: SearchResult = {
|
||
|
|
nextToken: roomEvents?.next_batch,
|
||
|
|
highlights: roomEvents?.highlights ?? [],
|
||
|
|
groups: groupSearchResult(roomEvents?.results ?? []),
|
||
|
|
};
|
||
|
|
|
||
|
|
return searchResult;
|
||
|
|
};
|
||
|
|
|
||
|
|
export type MessageSearchParams = {
|
||
|
|
term?: string;
|
||
|
|
order?: string;
|
||
|
|
rooms?: string[];
|
||
|
|
senders?: string[];
|
||
|
|
};
|
||
|
|
export const useMessageSearch = (params: MessageSearchParams) => {
|
||
|
|
const mx = useMatrixClient();
|
||
|
|
const { term, order, rooms, senders } = params;
|
||
|
|
|
||
|
|
const searchMessages = useCallback(
|
||
|
|
async (nextBatch?: string) => {
|
||
|
|
if (!term)
|
||
|
|
return {
|
||
|
|
highlights: [],
|
||
|
|
groups: [],
|
||
|
|
};
|
||
|
|
const limit = 20;
|
||
|
|
|
||
|
|
const requestBody: ISearchRequestBody = {
|
||
|
|
search_categories: {
|
||
|
|
room_events: {
|
||
|
|
event_context: {
|
||
|
|
before_limit: 0,
|
||
|
|
after_limit: 0,
|
||
|
|
include_profile: false,
|
||
|
|
},
|
||
|
|
filter: {
|
||
|
|
limit,
|
||
|
|
rooms,
|
||
|
|
senders,
|
||
|
|
},
|
||
|
|
include_state: false,
|
||
|
|
order_by: order as SearchOrderBy.Recent,
|
||
|
|
search_term: term,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
};
|
||
|
|
|
||
|
|
const r = await mx.search({
|
||
|
|
body: requestBody,
|
||
|
|
next_batch: nextBatch === '' ? undefined : nextBatch,
|
||
|
|
});
|
||
|
|
return parseSearchResult(r);
|
||
|
|
},
|
||
|
|
[mx, term, order, rooms, senders]
|
||
|
|
);
|
||
|
|
|
||
|
|
return searchMessages;
|
||
|
|
};
|