Skip to content

Commit 18944f9

Browse files
committed
feat: allow to override query filters in search source instances
1 parent 04e03d6 commit 18944f9

File tree

1 file changed

+36
-12
lines changed

1 file changed

+36
-12
lines changed

src/components/Search/SearchController.ts

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import debounce from 'lodash.debounce';
2+
import { ChannelOptions, ChannelSort, StateStore, UserOptions } from 'stream-chat';
13
import type {
24
Channel,
35
ChannelFilters,
@@ -10,15 +12,15 @@ import type {
1012
UserResponse,
1113
UserSort,
1214
} from 'stream-chat';
13-
import { StateStore } from 'stream-chat';
1415
import type { DefaultStreamChatGenerics } from '../../types';
15-
import debounce from 'lodash.debounce';
1616
import type { DebouncedFunc } from 'lodash';
1717

1818
// eslint-disable-next-line @typescript-eslint/ban-types
1919
export type SearchSourceType = 'channels' | 'users' | 'messages' | (string & {});
2020
export type QueryReturnValue<T> = { items: T[]; next?: string };
21-
21+
export type DebounceOptions = {
22+
debounceMs: number;
23+
};
2224
type DebouncedExecQueryFunction = DebouncedFunc<(searchString?: string) => Promise<void>>;
2325

2426
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -28,14 +30,13 @@ export interface SearchSource<T = any> {
2830
readonly isLoading: boolean;
2931
readonly items: T[] | undefined;
3032
readonly lastQueryError: Error | undefined;
31-
// loadMore(): Promise<void>;
3233
readonly next: string | undefined;
3334
readonly offset: number | undefined;
3435
resetState(): void;
3536
search(text?: string): Promise<void>;
3637
searchDebounced: DebouncedExecQueryFunction;
3738
readonly searchQuery: string;
38-
setDebounceOptions(debounceMs: number): void;
39+
setDebounceOptions(options: DebounceOptions): void;
3940
readonly state: StateStore<SearchSourceState<T>>;
4041
readonly type: SearchSourceType;
4142
}
@@ -118,7 +119,7 @@ export abstract class BaseSearchSource<T> implements SearchSource<T> {
118119

119120
protected abstract filterQueryResults(items: T[]): T[] | Promise<T[]>;
120121

121-
setDebounceOptions = (debounceMs: number) => {
122+
setDebounceOptions = ({ debounceMs }: DebounceOptions) => {
122123
this.searchDebounced = debounce(this.executeQuery, debounceMs);
123124
};
124125

@@ -188,6 +189,9 @@ export class UserSearchSource<
188189
> extends BaseSearchSource<UserResponse<StreamChatGenerics>> {
189190
readonly type = 'users';
190191
private client: StreamChat<StreamChatGenerics>;
192+
filters: UserFilters<StreamChatGenerics> | undefined;
193+
sort: UserSort<StreamChatGenerics> | undefined;
194+
searchOptions: Omit<UserOptions, 'limit' | 'offset'> | undefined;
191195

192196
constructor(client: StreamChat<StreamChatGenerics>, options?: SearchSourceOptions) {
193197
super(options);
@@ -197,9 +201,10 @@ export class UserSearchSource<
197201
protected async query(searchQuery: string) {
198202
const filters = {
199203
$or: [{ id: { $autocomplete: searchQuery } }, { name: { $autocomplete: searchQuery } }],
204+
...this.filters,
200205
} as UserFilters<StreamChatGenerics>;
201-
const sort = { id: 1 } as UserSort<StreamChatGenerics>;
202-
const options = { limit: this.pageSize, offset: this.offset };
206+
const sort = { id: 1, ...this.sort } as UserSort<StreamChatGenerics>;
207+
const options = { ...this.searchOptions, limit: this.pageSize, offset: this.offset };
203208
const { users } = await this.client.queryUsers(filters, sort, options);
204209
return { items: users };
205210
}
@@ -214,6 +219,9 @@ export class ChannelSearchSource<
214219
> extends BaseSearchSource<Channel<StreamChatGenerics>> {
215220
readonly type = 'channels';
216221
private client: StreamChat<StreamChatGenerics>;
222+
filters: ChannelFilters<StreamChatGenerics> | undefined;
223+
sort: ChannelSort<StreamChatGenerics> | undefined;
224+
searchOptions: Omit<ChannelOptions, 'limit' | 'offset'> | undefined;
217225

218226
constructor(client: StreamChat<StreamChatGenerics>, options?: SearchSourceOptions) {
219227
super(options);
@@ -224,9 +232,10 @@ export class ChannelSearchSource<
224232
const filters = {
225233
members: { $in: [this.client.userID] },
226234
name: { $autocomplete: searchQuery },
235+
...this.filters,
227236
} as ChannelFilters<StreamChatGenerics>;
228-
const sort = {};
229-
const options = { limit: this.pageSize, offset: this.offset };
237+
const sort = this.sort ?? {};
238+
const options = { ...this.searchOptions, limit: this.pageSize, offset: this.offset };
230239
const items = await this.client.queryChannels(filters, sort, options);
231240
return { items };
232241
}
@@ -241,6 +250,12 @@ export class MessageSearchSource<
241250
> extends BaseSearchSource<MessageResponse<StreamChatGenerics>> {
242251
readonly type = 'messages';
243252
private client: StreamChat<StreamChatGenerics>;
253+
messageSearchChannelFilters: ChannelFilters<StreamChatGenerics> | undefined;
254+
messageSearchFilters: MessageFilters<StreamChatGenerics> | undefined;
255+
messageSearchSort: SearchMessageSort<StreamChatGenerics> | undefined;
256+
channelQueryFilters: ChannelFilters<StreamChatGenerics> | undefined;
257+
channelQuerySort: ChannelSort<StreamChatGenerics> | undefined;
258+
channelQueryOptions: Omit<ChannelOptions, 'limit' | 'offset'> | undefined;
244259

245260
constructor(client: StreamChat<StreamChatGenerics>, options?: SearchSourceOptions) {
246261
super(options);
@@ -252,14 +267,19 @@ export class MessageSearchSource<
252267

253268
const channelFilters: ChannelFilters<StreamChatGenerics> = {
254269
members: { $in: [this.client.userID] },
270+
...this.messageSearchChannelFilters,
255271
} as ChannelFilters<StreamChatGenerics>;
256272

257273
const messageFilters: MessageFilters<StreamChatGenerics> = {
258274
text: searchQuery,
259-
type: 'regular', // todo: type: 'reply'
275+
type: 'regular', // todo: type: 'reply' resp. do not filter by type and allow to jump to a message in a thread
276+
...this.messageSearchFilters,
260277
} as MessageFilters<StreamChatGenerics>;
261278

262-
const sort: SearchMessageSort<StreamChatGenerics> = { created_at: -1 };
279+
const sort: SearchMessageSort<StreamChatGenerics> = {
280+
created_at: -1,
281+
...this.messageSearchSort,
282+
};
263283

264284
const options = {
265285
limit: this.pageSize,
@@ -269,6 +289,7 @@ export class MessageSearchSource<
269289

270290
const { next, results } = await this.client.search(channelFilters, messageFilters, options);
271291
const items = results.map(({ message }) => message);
292+
272293
const cids = Array.from(
273294
items.reduce((acc, message) => {
274295
if (message.cid && !this.client.activeChannels[message.cid]) acc.add(message.cid);
@@ -280,10 +301,13 @@ export class MessageSearchSource<
280301
await this.client.queryChannels(
281302
{
282303
cid: { $in: cids },
304+
...this.channelQueryFilters,
283305
} as ChannelFilters<StreamChatGenerics>,
284306
{
285307
last_message_at: -1,
308+
...this.channelQuerySort,
286309
},
310+
this.channelQueryOptions,
287311
);
288312
}
289313

0 commit comments

Comments
 (0)