Skip to content

Commit 8efcb88

Browse files
Draft - target factories
1 parent 1c064e5 commit 8efcb88

File tree

2 files changed

+59
-5
lines changed

2 files changed

+59
-5
lines changed

src/client.ts

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ import {
8282
ErrorFromResponse,
8383
Event,
8484
EventHandler,
85+
EventTypes,
8586
ExportChannelOptions,
8687
ExportChannelRequest,
8788
ExportChannelResponse,
@@ -218,6 +219,11 @@ function isString(x: unknown): x is string {
218219
return typeof x === 'string' || x instanceof String;
219220
}
220221

222+
export type TargetFactory<
223+
SCG extends ExtendableGenerics = DefaultGenerics,
224+
T extends Exclude<EventTypes, 'all'> = Exclude<EventTypes, 'all'>
225+
> = (event: Event<SCG>) => `${T}${string}` | `${string}${T}` | `${string}${T}${string}` | null;
226+
221227
export class StreamChat<StreamChatGenerics extends ExtendableGenerics = DefaultGenerics> {
222228
private static _instance?: unknown | StreamChat; // type is undefined|StreamChat, unknown is due to TS limitations with statics
223229

@@ -269,6 +275,7 @@ export class StreamChat<StreamChatGenerics extends ExtendableGenerics = DefaultG
269275
defaultWSTimeoutWithFallback: number;
270276
defaultWSTimeout: number;
271277
private nextRequestAbortController: AbortController | null = null;
278+
private targetFactoriesByType = new Map<Exclude<EventTypes, 'all'>, Set<TargetFactory<StreamChatGenerics>>>();
272279

273280
/**
274281
* Initialize a client
@@ -909,6 +916,28 @@ export class StreamChat<StreamChatGenerics extends ExtendableGenerics = DefaultG
909916
return JWTUserToken(this.secret, userID, extra, {});
910917
}
911918

919+
public registerTargetFactory = <T extends Exclude<EventTypes, 'all'>>(
920+
eventType: T,
921+
factory: TargetFactory<StreamChatGenerics, T>,
922+
) => {
923+
let set = this.targetFactoriesByType.get(eventType);
924+
925+
if (!set) {
926+
set = new Set();
927+
this.targetFactoriesByType.set(eventType, set);
928+
}
929+
930+
set.add(factory);
931+
932+
return () => {
933+
set.delete(factory);
934+
935+
if (!set.size) {
936+
this.targetFactoriesByType.delete(eventType);
937+
}
938+
};
939+
};
940+
912941
/**
913942
* on - Listen to events on all channels and users your watching
914943
*
@@ -936,6 +965,7 @@ export class StreamChat<StreamChatGenerics extends ExtendableGenerics = DefaultG
936965
tags: ['event', 'client'],
937966
});
938967
this.listeners[key].push(callback);
968+
939969
return {
940970
unsubscribe: () => {
941971
this.logger('info', `Removing listener for ${key} event`, {
@@ -1364,8 +1394,21 @@ export class StreamChat<StreamChatGenerics extends ExtendableGenerics = DefaultG
13641394
if (client.listeners.all) {
13651395
listeners.push(...client.listeners.all);
13661396
}
1367-
if (client.listeners[event.type]) {
1368-
listeners.push(...client.listeners[event.type]);
1397+
1398+
const eventTypes: string[] = [event.type];
1399+
1400+
// factories
1401+
const factorySet = client.targetFactoriesByType.get(event.type as Exclude<EventTypes, 'all'>);
1402+
factorySet?.forEach((factory) => {
1403+
// a specific value could be missing from the event payload so factory can return "null" to be skipped
1404+
const targetedEventType = factory(event);
1405+
if (targetedEventType) eventTypes.push(targetedEventType);
1406+
});
1407+
1408+
for (const eventType of eventTypes) {
1409+
if (client.listeners[eventType]) {
1410+
listeners.push(...client.listeners[eventType]);
1411+
}
13691412
}
13701413

13711414
// call the event and send it to the listeners

src/thread.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { Channel } from './channel';
2-
import type { StreamChat } from './client';
2+
import type { StreamChat, TargetFactory } from './client';
33
import { StateStore } from './store';
44
import type {
55
AscDesc,
@@ -62,6 +62,14 @@ export type ThreadReadState<SCG extends ExtendableGenerics = DefaultGenerics> =
6262
ThreadUserReadState<SCG> | undefined
6363
>;
6464

65+
// TODO: figure out generics here
66+
const messageNewFactory: TargetFactory<DefaultGenerics, 'message.new'> = (event) => {
67+
return event.parent_id ? `message.new-${event.parent_id}` : null;
68+
};
69+
const threadMessageReadFactory: TargetFactory<DefaultGenerics, 'message.read'> = (event) => {
70+
return event.thread ? `message.read-${event.thread.parent_message_id}` : null;
71+
};
72+
6573
const DEFAULT_PAGE_LIMIT = 50;
6674
const DEFAULT_SORT: { created_at: AscDesc }[] = [{ created_at: -1 }];
6775
const MARK_AS_READ_THROTTLE_TIMEOUT = 1000;
@@ -186,6 +194,9 @@ export class Thread<SCG extends ExtendableGenerics = DefaultGenerics> {
186194
return;
187195
}
188196

197+
this.unsubscribeFunctions.add(this.client.registerTargetFactory('message.new', messageNewFactory));
198+
this.unsubscribeFunctions.add(this.client.registerTargetFactory('message.read', threadMessageReadFactory));
199+
189200
this.unsubscribeFunctions.add(this.subscribeMarkActiveThreadRead());
190201
this.unsubscribeFunctions.add(this.subscribeReloadActiveStaleThread());
191202
this.unsubscribeFunctions.add(this.subscribeMarkThreadStale());
@@ -230,7 +241,7 @@ export class Thread<SCG extends ExtendableGenerics = DefaultGenerics> {
230241
}).unsubscribe;
231242

232243
private subscribeNewReplies = () =>
233-
this.client.on('message.new', (event) => {
244+
this.client.on(`message.new-${this.id}`, (event) => {
234245
if (!this.client.userID || event.message?.parent_id !== this.id) {
235246
return;
236247
}
@@ -284,7 +295,7 @@ export class Thread<SCG extends ExtendableGenerics = DefaultGenerics> {
284295
}).unsubscribe;
285296

286297
private subscribeRepliesRead = () =>
287-
this.client.on('message.read', (event) => {
298+
this.client.on(`message.read-${this.id}`, (event) => {
288299
if (!event.user || !event.created_at || !event.thread) return;
289300
if (event.thread.parent_message_id !== this.id) return;
290301

0 commit comments

Comments
 (0)