@defcomm/meetingsdk 0.4.4 → 0.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +40 -14
- package/dist/index.d.ts +40 -14
- package/dist/index.js +123 -81
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +135 -93
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -67,6 +67,26 @@ type PubSubMessage<T = unknown> = {
|
|
|
67
67
|
timestamp: number;
|
|
68
68
|
data: T;
|
|
69
69
|
};
|
|
70
|
+
type PubSubTopicConfig = {
|
|
71
|
+
SECURE_CHAT: {
|
|
72
|
+
publish: ChatInput;
|
|
73
|
+
message: ChatMessage;
|
|
74
|
+
};
|
|
75
|
+
REACTION: {
|
|
76
|
+
publish: {
|
|
77
|
+
emoji: string;
|
|
78
|
+
};
|
|
79
|
+
message: {
|
|
80
|
+
emoji: string;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
type PubSubTopic = keyof PubSubTopicConfig;
|
|
85
|
+
type PubSubHandle<TPublish = unknown, TMessage = TPublish> = {
|
|
86
|
+
messages: PubSubMessage<TMessage>[];
|
|
87
|
+
publish: (data: TPublish) => void;
|
|
88
|
+
};
|
|
89
|
+
type PubSubHandleForTopic<T extends PubSubTopic> = PubSubHandle<PubSubTopicConfig[T]["publish"], PubSubTopicConfig[T]["message"]>;
|
|
70
90
|
type Participant = {
|
|
71
91
|
id: string;
|
|
72
92
|
name?: string;
|
|
@@ -103,12 +123,7 @@ type MeetingConfig = {
|
|
|
103
123
|
name: string;
|
|
104
124
|
audioMuted?: boolean;
|
|
105
125
|
videoMuted?: boolean;
|
|
106
|
-
token
|
|
107
|
-
};
|
|
108
|
-
type PubSubTopic = "SECURE_CHAT" | "REACTION";
|
|
109
|
-
type PubSubHandle<T = unknown> = {
|
|
110
|
-
messages: PubSubMessage<T>[];
|
|
111
|
-
publish: (data: T) => void;
|
|
126
|
+
token: string;
|
|
112
127
|
};
|
|
113
128
|
type RecordingInfo = {
|
|
114
129
|
recording_id: string;
|
|
@@ -145,6 +160,7 @@ interface Recording {
|
|
|
145
160
|
}
|
|
146
161
|
interface VideoSDKCoreOptions {
|
|
147
162
|
participantId: string;
|
|
163
|
+
token: string;
|
|
148
164
|
onError?: (error: any) => void;
|
|
149
165
|
onEntryRequested?: (request: any) => void;
|
|
150
166
|
onEntryResponded?: (payload: any, decision?: any) => void;
|
|
@@ -234,6 +250,7 @@ declare class VideoSDKCore {
|
|
|
234
250
|
deleteRoom(roomCode: string): Promise<any>;
|
|
235
251
|
joinMeeting(config: Omit<MeetingConfig, "participantId">): Promise<void>;
|
|
236
252
|
private connect;
|
|
253
|
+
private createSFUClient;
|
|
237
254
|
private handleSFUState;
|
|
238
255
|
private handleRemoteTrack;
|
|
239
256
|
getMeeting(): {
|
|
@@ -253,6 +270,15 @@ declare class VideoSDKCore {
|
|
|
253
270
|
}>;
|
|
254
271
|
sendChatMessage(payload: ChatInput): void;
|
|
255
272
|
sendReaction(reaction: string): void;
|
|
273
|
+
/**
|
|
274
|
+
* Generic PubSub publishing entry point.
|
|
275
|
+
*
|
|
276
|
+
* The public SDK exposes one PubSub API for all topics. The current SFU
|
|
277
|
+
* protocol still has dedicated wire messages for chat and reactions, so
|
|
278
|
+
* this method is the compatibility bridge. The application does not need
|
|
279
|
+
* to know about those wire-level message types.
|
|
280
|
+
*/
|
|
281
|
+
publishPubSub<T extends PubSubTopic>(topic: T, data: PubSubTopicConfig[T]["publish"]): void;
|
|
256
282
|
private cleanupRemoteParticipant;
|
|
257
283
|
disconnect(): Promise<void>;
|
|
258
284
|
private performDisconnect;
|
|
@@ -304,8 +330,8 @@ type MeetingContextValue = {
|
|
|
304
330
|
presenterId: string | null;
|
|
305
331
|
activeSpeakerIds: string[];
|
|
306
332
|
recording: RecordingInfo | null;
|
|
307
|
-
usePubSub: <T
|
|
308
|
-
onPubSubMessage: <T
|
|
333
|
+
usePubSub: <T extends PubSubTopic>(topic: T) => PubSubHandleForTopic<T>;
|
|
334
|
+
onPubSubMessage: <T extends PubSubTopic>(topic: T, cb: (message: PubSubMessage<PubSubTopicConfig[T]["message"]>) => void) => () => void;
|
|
309
335
|
approveJoinRequest: (requestId: string) => void;
|
|
310
336
|
rejectJoinRequest: (requestId: string) => void;
|
|
311
337
|
startRecording: () => Promise<void>;
|
|
@@ -367,8 +393,8 @@ declare const useMeeting: (handlers?: {
|
|
|
367
393
|
presenterId: string | null;
|
|
368
394
|
activeSpeakerIds: string[];
|
|
369
395
|
recording: RecordingInfo | null;
|
|
370
|
-
usePubSub: <T
|
|
371
|
-
onPubSubMessage: <T
|
|
396
|
+
usePubSub: <T extends PubSubTopic>(topic: T) => PubSubHandleForTopic<T>;
|
|
397
|
+
onPubSubMessage: <T extends PubSubTopic>(topic: T, cb: (message: PubSubMessage<PubSubTopicConfig[T]["message"]>) => void) => () => void;
|
|
372
398
|
approveJoinRequest: (requestId: string) => void;
|
|
373
399
|
rejectJoinRequest: (requestId: string) => void;
|
|
374
400
|
startRecording: () => Promise<void>;
|
|
@@ -463,8 +489,8 @@ declare class ActiveSpeakerDetector {
|
|
|
463
489
|
destroy(): Promise<void>;
|
|
464
490
|
}
|
|
465
491
|
|
|
466
|
-
declare function usePubSub<T
|
|
467
|
-
onMessageReceived?: (message: PubSubMessage<T>) => void;
|
|
468
|
-
}):
|
|
492
|
+
declare function usePubSub<T extends PubSubTopic>(topic: T, options?: {
|
|
493
|
+
onMessageReceived?: (message: PubSubMessage<PubSubTopicConfig[T]["message"]>) => void;
|
|
494
|
+
}): PubSubHandleForTopic<T>;
|
|
469
495
|
|
|
470
|
-
export { ActiveSpeakerDetector, type ChatInput, type MeetingConfig, MeetingProvider, MeetingState, type Participant, type ParticipantInfo, type Reaction, type RecordingInfo, type SFUConnectionState, type TrackInfo, VideoSDKCore, useLocalParticipant, useMeeting, useMeetingContext, useMeetingPreview, useParticipants, usePubSub, useRemoteMedia };
|
|
496
|
+
export { ActiveSpeakerDetector, type ChatInput, type MeetingConfig, MeetingProvider, MeetingState, type Participant, type ParticipantInfo, type PubSubHandle, type PubSubHandleForTopic, type PubSubMessage, type PubSubTopic, type PubSubTopicConfig, type Reaction, type RecordingInfo, type SFUConnectionState, type TrackInfo, VideoSDKCore, useLocalParticipant, useMeeting, useMeetingContext, useMeetingPreview, useParticipants, usePubSub, useRemoteMedia };
|
package/dist/index.d.ts
CHANGED
|
@@ -67,6 +67,26 @@ type PubSubMessage<T = unknown> = {
|
|
|
67
67
|
timestamp: number;
|
|
68
68
|
data: T;
|
|
69
69
|
};
|
|
70
|
+
type PubSubTopicConfig = {
|
|
71
|
+
SECURE_CHAT: {
|
|
72
|
+
publish: ChatInput;
|
|
73
|
+
message: ChatMessage;
|
|
74
|
+
};
|
|
75
|
+
REACTION: {
|
|
76
|
+
publish: {
|
|
77
|
+
emoji: string;
|
|
78
|
+
};
|
|
79
|
+
message: {
|
|
80
|
+
emoji: string;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
type PubSubTopic = keyof PubSubTopicConfig;
|
|
85
|
+
type PubSubHandle<TPublish = unknown, TMessage = TPublish> = {
|
|
86
|
+
messages: PubSubMessage<TMessage>[];
|
|
87
|
+
publish: (data: TPublish) => void;
|
|
88
|
+
};
|
|
89
|
+
type PubSubHandleForTopic<T extends PubSubTopic> = PubSubHandle<PubSubTopicConfig[T]["publish"], PubSubTopicConfig[T]["message"]>;
|
|
70
90
|
type Participant = {
|
|
71
91
|
id: string;
|
|
72
92
|
name?: string;
|
|
@@ -103,12 +123,7 @@ type MeetingConfig = {
|
|
|
103
123
|
name: string;
|
|
104
124
|
audioMuted?: boolean;
|
|
105
125
|
videoMuted?: boolean;
|
|
106
|
-
token
|
|
107
|
-
};
|
|
108
|
-
type PubSubTopic = "SECURE_CHAT" | "REACTION";
|
|
109
|
-
type PubSubHandle<T = unknown> = {
|
|
110
|
-
messages: PubSubMessage<T>[];
|
|
111
|
-
publish: (data: T) => void;
|
|
126
|
+
token: string;
|
|
112
127
|
};
|
|
113
128
|
type RecordingInfo = {
|
|
114
129
|
recording_id: string;
|
|
@@ -145,6 +160,7 @@ interface Recording {
|
|
|
145
160
|
}
|
|
146
161
|
interface VideoSDKCoreOptions {
|
|
147
162
|
participantId: string;
|
|
163
|
+
token: string;
|
|
148
164
|
onError?: (error: any) => void;
|
|
149
165
|
onEntryRequested?: (request: any) => void;
|
|
150
166
|
onEntryResponded?: (payload: any, decision?: any) => void;
|
|
@@ -234,6 +250,7 @@ declare class VideoSDKCore {
|
|
|
234
250
|
deleteRoom(roomCode: string): Promise<any>;
|
|
235
251
|
joinMeeting(config: Omit<MeetingConfig, "participantId">): Promise<void>;
|
|
236
252
|
private connect;
|
|
253
|
+
private createSFUClient;
|
|
237
254
|
private handleSFUState;
|
|
238
255
|
private handleRemoteTrack;
|
|
239
256
|
getMeeting(): {
|
|
@@ -253,6 +270,15 @@ declare class VideoSDKCore {
|
|
|
253
270
|
}>;
|
|
254
271
|
sendChatMessage(payload: ChatInput): void;
|
|
255
272
|
sendReaction(reaction: string): void;
|
|
273
|
+
/**
|
|
274
|
+
* Generic PubSub publishing entry point.
|
|
275
|
+
*
|
|
276
|
+
* The public SDK exposes one PubSub API for all topics. The current SFU
|
|
277
|
+
* protocol still has dedicated wire messages for chat and reactions, so
|
|
278
|
+
* this method is the compatibility bridge. The application does not need
|
|
279
|
+
* to know about those wire-level message types.
|
|
280
|
+
*/
|
|
281
|
+
publishPubSub<T extends PubSubTopic>(topic: T, data: PubSubTopicConfig[T]["publish"]): void;
|
|
256
282
|
private cleanupRemoteParticipant;
|
|
257
283
|
disconnect(): Promise<void>;
|
|
258
284
|
private performDisconnect;
|
|
@@ -304,8 +330,8 @@ type MeetingContextValue = {
|
|
|
304
330
|
presenterId: string | null;
|
|
305
331
|
activeSpeakerIds: string[];
|
|
306
332
|
recording: RecordingInfo | null;
|
|
307
|
-
usePubSub: <T
|
|
308
|
-
onPubSubMessage: <T
|
|
333
|
+
usePubSub: <T extends PubSubTopic>(topic: T) => PubSubHandleForTopic<T>;
|
|
334
|
+
onPubSubMessage: <T extends PubSubTopic>(topic: T, cb: (message: PubSubMessage<PubSubTopicConfig[T]["message"]>) => void) => () => void;
|
|
309
335
|
approveJoinRequest: (requestId: string) => void;
|
|
310
336
|
rejectJoinRequest: (requestId: string) => void;
|
|
311
337
|
startRecording: () => Promise<void>;
|
|
@@ -367,8 +393,8 @@ declare const useMeeting: (handlers?: {
|
|
|
367
393
|
presenterId: string | null;
|
|
368
394
|
activeSpeakerIds: string[];
|
|
369
395
|
recording: RecordingInfo | null;
|
|
370
|
-
usePubSub: <T
|
|
371
|
-
onPubSubMessage: <T
|
|
396
|
+
usePubSub: <T extends PubSubTopic>(topic: T) => PubSubHandleForTopic<T>;
|
|
397
|
+
onPubSubMessage: <T extends PubSubTopic>(topic: T, cb: (message: PubSubMessage<PubSubTopicConfig[T]["message"]>) => void) => () => void;
|
|
372
398
|
approveJoinRequest: (requestId: string) => void;
|
|
373
399
|
rejectJoinRequest: (requestId: string) => void;
|
|
374
400
|
startRecording: () => Promise<void>;
|
|
@@ -463,8 +489,8 @@ declare class ActiveSpeakerDetector {
|
|
|
463
489
|
destroy(): Promise<void>;
|
|
464
490
|
}
|
|
465
491
|
|
|
466
|
-
declare function usePubSub<T
|
|
467
|
-
onMessageReceived?: (message: PubSubMessage<T>) => void;
|
|
468
|
-
}):
|
|
492
|
+
declare function usePubSub<T extends PubSubTopic>(topic: T, options?: {
|
|
493
|
+
onMessageReceived?: (message: PubSubMessage<PubSubTopicConfig[T]["message"]>) => void;
|
|
494
|
+
}): PubSubHandleForTopic<T>;
|
|
469
495
|
|
|
470
|
-
export { ActiveSpeakerDetector, type ChatInput, type MeetingConfig, MeetingProvider, MeetingState, type Participant, type ParticipantInfo, type Reaction, type RecordingInfo, type SFUConnectionState, type TrackInfo, VideoSDKCore, useLocalParticipant, useMeeting, useMeetingContext, useMeetingPreview, useParticipants, usePubSub, useRemoteMedia };
|
|
496
|
+
export { ActiveSpeakerDetector, type ChatInput, type MeetingConfig, MeetingProvider, MeetingState, type Participant, type ParticipantInfo, type PubSubHandle, type PubSubHandleForTopic, type PubSubMessage, type PubSubTopic, type PubSubTopicConfig, type Reaction, type RecordingInfo, type SFUConnectionState, type TrackInfo, VideoSDKCore, useLocalParticipant, useMeeting, useMeetingContext, useMeetingPreview, useParticipants, usePubSub, useRemoteMedia };
|
package/dist/index.js
CHANGED
|
@@ -404,6 +404,9 @@ var SFUClient = class {
|
|
|
404
404
|
this.publisherRevision = 0;
|
|
405
405
|
this.screenShareGeneration = 0;
|
|
406
406
|
this.currentParticipantId = null;
|
|
407
|
+
// Provider/application token used for authenticated REST calls.
|
|
408
|
+
this.authToken = null;
|
|
409
|
+
// Room/SFU token returned by /token and used for the WebSocket.
|
|
407
410
|
this.token = null;
|
|
408
411
|
this.room = null;
|
|
409
412
|
this.resumeToken = null;
|
|
@@ -444,6 +447,7 @@ var SFUClient = class {
|
|
|
444
447
|
this.apiBase = options.apiBase || "https://api.example.com/api";
|
|
445
448
|
this.wsBase = options.wsBase || "wss://api.example.com/ws";
|
|
446
449
|
this.participantId = options.participantId || this.createId();
|
|
450
|
+
this.authToken = options.token ?? null;
|
|
447
451
|
this.onStateChange = options.onStateChange || (() => {
|
|
448
452
|
});
|
|
449
453
|
this.onParticipantJoined = options.onParticipantJoined || (() => {
|
|
@@ -567,9 +571,14 @@ var SFUClient = class {
|
|
|
567
571
|
return (++this.requestId).toString();
|
|
568
572
|
}
|
|
569
573
|
async request(url, options = {}) {
|
|
574
|
+
const headers = new Headers(options.headers);
|
|
575
|
+
headers.set("Content-Type", "application/json");
|
|
576
|
+
if (this.authToken) {
|
|
577
|
+
headers.set("Authorization", `Bearer ${this.authToken}`);
|
|
578
|
+
}
|
|
570
579
|
const res = await fetch(url, {
|
|
571
|
-
|
|
572
|
-
|
|
580
|
+
...options,
|
|
581
|
+
headers
|
|
573
582
|
});
|
|
574
583
|
if (!res.ok) {
|
|
575
584
|
let body = {};
|
|
@@ -577,7 +586,9 @@ var SFUClient = class {
|
|
|
577
586
|
body = await res.json();
|
|
578
587
|
} catch {
|
|
579
588
|
}
|
|
580
|
-
throw new Error(
|
|
589
|
+
throw new Error(
|
|
590
|
+
body.message || `Request failed: ${res.status} ${res.statusText}`
|
|
591
|
+
);
|
|
581
592
|
}
|
|
582
593
|
return res.json();
|
|
583
594
|
}
|
|
@@ -1981,6 +1992,7 @@ var VideoSDKCore = class {
|
|
|
1981
1992
|
}
|
|
1982
1993
|
});
|
|
1983
1994
|
this.myId = options.participantId;
|
|
1995
|
+
this.sfuClient = this.createSFUClient(options.token);
|
|
1984
1996
|
}
|
|
1985
1997
|
emitError(code, message, raw, recoverable = true) {
|
|
1986
1998
|
const err = {
|
|
@@ -2045,36 +2057,16 @@ var VideoSDKCore = class {
|
|
|
2045
2057
|
}
|
|
2046
2058
|
// ROOM MANAGEMENT
|
|
2047
2059
|
async createRoom(input) {
|
|
2048
|
-
|
|
2049
|
-
apiBase: this.apiBase,
|
|
2050
|
-
wsBase: this.wsBase,
|
|
2051
|
-
participantId: this.myId
|
|
2052
|
-
});
|
|
2053
|
-
return client.createRoom(input);
|
|
2060
|
+
return this.sfuClient.createRoom(input);
|
|
2054
2061
|
}
|
|
2055
2062
|
async getRoom(roomCode) {
|
|
2056
|
-
|
|
2057
|
-
apiBase: this.apiBase,
|
|
2058
|
-
wsBase: this.wsBase,
|
|
2059
|
-
participantId: this.myId
|
|
2060
|
-
});
|
|
2061
|
-
return client.getRoom(roomCode);
|
|
2063
|
+
return this.sfuClient.getRoom(roomCode);
|
|
2062
2064
|
}
|
|
2063
2065
|
async getJoinState(roomCode) {
|
|
2064
|
-
|
|
2065
|
-
apiBase: this.apiBase,
|
|
2066
|
-
wsBase: this.wsBase,
|
|
2067
|
-
participantId: this.myId
|
|
2068
|
-
});
|
|
2069
|
-
return client.getJoinState(roomCode);
|
|
2066
|
+
return this.sfuClient.getJoinState(roomCode);
|
|
2070
2067
|
}
|
|
2071
2068
|
async deleteRoom(roomCode) {
|
|
2072
|
-
|
|
2073
|
-
apiBase: this.apiBase,
|
|
2074
|
-
wsBase: this.wsBase,
|
|
2075
|
-
participantId: this.myId
|
|
2076
|
-
});
|
|
2077
|
-
return client.deleteRoom(roomCode);
|
|
2069
|
+
return this.sfuClient.deleteRoom(roomCode);
|
|
2078
2070
|
}
|
|
2079
2071
|
// JOIN
|
|
2080
2072
|
async joinMeeting(config) {
|
|
@@ -2140,26 +2132,36 @@ var VideoSDKCore = class {
|
|
|
2140
2132
|
}
|
|
2141
2133
|
// SFU CONNECTION
|
|
2142
2134
|
async connect(roomId, name) {
|
|
2143
|
-
if (this.sfuClient) {
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2135
|
+
if (!this.sfuClient) {
|
|
2136
|
+
throw new Error("SFU client is not initialized");
|
|
2137
|
+
}
|
|
2138
|
+
const state = this.sfuClient.getConnectionState();
|
|
2139
|
+
if (this.room.id === roomId && (state === "connecting" || state === "joining" || state === "waiting_approval" || state === "connected" || state === "reconnecting")) {
|
|
2140
|
+
console.info("[SDK] Existing SFU connection is active; connect ignored", {
|
|
2141
|
+
roomId,
|
|
2142
|
+
state
|
|
2143
|
+
});
|
|
2144
|
+
return;
|
|
2145
|
+
}
|
|
2146
|
+
if (state !== "idle" && state !== "disconnected") {
|
|
2155
2147
|
throw new Error(
|
|
2156
|
-
`SFU client already
|
|
2148
|
+
`SFU client is already active in state "${state}". Leave the current meeting before joining another room.`
|
|
2157
2149
|
);
|
|
2158
2150
|
}
|
|
2159
|
-
|
|
2151
|
+
this.sfuClient.setLocalStream(this.localStream);
|
|
2152
|
+
await this.sfuClient.getToken(roomId, {
|
|
2153
|
+
displayName: name,
|
|
2154
|
+
participantId: this.myId,
|
|
2155
|
+
audioMuted: !(this.localStream?.getAudioTracks()[0]?.enabled ?? true),
|
|
2156
|
+
videoMuted: !(this.localStream?.getVideoTracks()[0]?.enabled ?? true)
|
|
2157
|
+
});
|
|
2158
|
+
}
|
|
2159
|
+
createSFUClient(token) {
|
|
2160
|
+
return new SFUClient({
|
|
2160
2161
|
apiBase: this.apiBase,
|
|
2161
2162
|
wsBase: this.wsBase,
|
|
2162
2163
|
participantId: this.myId,
|
|
2164
|
+
token,
|
|
2163
2165
|
autoSubscribe: true,
|
|
2164
2166
|
// CONNECTION STATE
|
|
2165
2167
|
onStateChange: (state) => {
|
|
@@ -2498,14 +2500,6 @@ var VideoSDKCore = class {
|
|
|
2498
2500
|
);
|
|
2499
2501
|
}
|
|
2500
2502
|
});
|
|
2501
|
-
this.sfuClient = client;
|
|
2502
|
-
client.setLocalStream(this.localStream);
|
|
2503
|
-
await client.getToken(roomId, {
|
|
2504
|
-
displayName: name,
|
|
2505
|
-
participantId: this.myId,
|
|
2506
|
-
audioMuted: !(this.localStream?.getAudioTracks()[0]?.enabled ?? true),
|
|
2507
|
-
videoMuted: !(this.localStream?.getVideoTracks()[0]?.enabled ?? true)
|
|
2508
|
-
});
|
|
2509
2503
|
}
|
|
2510
2504
|
// SFU STATE
|
|
2511
2505
|
handleSFUState(state) {
|
|
@@ -2739,6 +2733,28 @@ var VideoSDKCore = class {
|
|
|
2739
2733
|
}
|
|
2740
2734
|
this.sfuClient.sendReaction(reaction);
|
|
2741
2735
|
}
|
|
2736
|
+
/**
|
|
2737
|
+
* Generic PubSub publishing entry point.
|
|
2738
|
+
*
|
|
2739
|
+
* The public SDK exposes one PubSub API for all topics. The current SFU
|
|
2740
|
+
* protocol still has dedicated wire messages for chat and reactions, so
|
|
2741
|
+
* this method is the compatibility bridge. The application does not need
|
|
2742
|
+
* to know about those wire-level message types.
|
|
2743
|
+
*/
|
|
2744
|
+
publishPubSub(topic, data) {
|
|
2745
|
+
switch (topic) {
|
|
2746
|
+
case "SECURE_CHAT":
|
|
2747
|
+
this.sendChatMessage(data);
|
|
2748
|
+
return;
|
|
2749
|
+
case "REACTION":
|
|
2750
|
+
this.sendReaction(data.emoji);
|
|
2751
|
+
return;
|
|
2752
|
+
default: {
|
|
2753
|
+
const exhaustive = topic;
|
|
2754
|
+
throw new Error(`Unsupported PubSub topic: ${exhaustive}`);
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
2757
|
+
}
|
|
2742
2758
|
// CLEANUP
|
|
2743
2759
|
cleanupRemoteParticipant(participantId) {
|
|
2744
2760
|
this.activeSpeakerDetector.removeParticipant(participantId);
|
|
@@ -2764,10 +2780,8 @@ var VideoSDKCore = class {
|
|
|
2764
2780
|
async performDisconnect() {
|
|
2765
2781
|
this.intentionalDisconnect = true;
|
|
2766
2782
|
this.joinPromise = null;
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
if (client) {
|
|
2770
|
-
await client.leave();
|
|
2783
|
+
if (this.sfuClient) {
|
|
2784
|
+
await this.sfuClient.leave();
|
|
2771
2785
|
}
|
|
2772
2786
|
if (this.localStream) {
|
|
2773
2787
|
this.localStream.getTracks().forEach((track) => track.stop());
|
|
@@ -2829,6 +2843,7 @@ var MeetingProvider = ({
|
|
|
2829
2843
|
const pubSubListeners = (0, import_react2.useRef)(
|
|
2830
2844
|
/* @__PURE__ */ new Map()
|
|
2831
2845
|
);
|
|
2846
|
+
const [reactionPubSubMessages, setReactionPubSubMessages] = (0, import_react2.useState)([]);
|
|
2832
2847
|
const activeSpeakerListeners = (0, import_react2.useRef)(
|
|
2833
2848
|
/* @__PURE__ */ new Set()
|
|
2834
2849
|
);
|
|
@@ -2838,7 +2853,8 @@ var MeetingProvider = ({
|
|
|
2838
2853
|
if (!sdkRef.current) {
|
|
2839
2854
|
sdkRef.current = new VideoSDKCore(
|
|
2840
2855
|
{
|
|
2841
|
-
participantId: config.participantId
|
|
2856
|
+
participantId: config.participantId,
|
|
2857
|
+
token: config.token
|
|
2842
2858
|
},
|
|
2843
2859
|
{
|
|
2844
2860
|
onError: (err) => {
|
|
@@ -2862,21 +2878,43 @@ var MeetingProvider = ({
|
|
|
2862
2878
|
onRecordingStopped: (recording2) => {
|
|
2863
2879
|
recordingStoppedListeners.current.forEach((fn) => fn(recording2));
|
|
2864
2880
|
},
|
|
2881
|
+
onChatMessage: (message) => {
|
|
2882
|
+
const msg = {
|
|
2883
|
+
id: message.id,
|
|
2884
|
+
text: message.text,
|
|
2885
|
+
sender_id: message.sender_id,
|
|
2886
|
+
sender_name: message.sender_name,
|
|
2887
|
+
timestamp: Number(message.timestamp),
|
|
2888
|
+
reply_to: message.reply_to ?? null,
|
|
2889
|
+
target: message.target ?? null
|
|
2890
|
+
};
|
|
2891
|
+
const pubSubMessage = {
|
|
2892
|
+
id: msg.id,
|
|
2893
|
+
topic: "SECURE_CHAT",
|
|
2894
|
+
sender_id: msg.sender_id,
|
|
2895
|
+
sender_name: msg.sender_name,
|
|
2896
|
+
timestamp: msg.timestamp,
|
|
2897
|
+
data: msg
|
|
2898
|
+
};
|
|
2899
|
+
pubSubListeners.current.get("SECURE_CHAT")?.forEach((fn) => fn(pubSubMessage));
|
|
2900
|
+
},
|
|
2865
2901
|
onReaction: (reaction) => {
|
|
2866
2902
|
reactionListeners.current.forEach((fn) => fn(reaction));
|
|
2867
|
-
const
|
|
2868
|
-
if (!listeners) return;
|
|
2903
|
+
const timestamp = typeof reaction.timestamp === "number" ? reaction.timestamp : Date.parse(reaction.timestamp);
|
|
2869
2904
|
const message = {
|
|
2870
2905
|
id: reaction.id,
|
|
2871
2906
|
topic: "REACTION",
|
|
2872
2907
|
sender_id: reaction.participant_id,
|
|
2873
2908
|
sender_name: reaction.sender_name,
|
|
2874
|
-
timestamp
|
|
2909
|
+
timestamp,
|
|
2875
2910
|
data: {
|
|
2876
2911
|
emoji: reaction.emoji
|
|
2877
2912
|
}
|
|
2878
2913
|
};
|
|
2879
|
-
|
|
2914
|
+
setReactionPubSubMessages(
|
|
2915
|
+
(previous) => [...previous, message].slice(-50)
|
|
2916
|
+
);
|
|
2917
|
+
pubSubListeners.current.get("REACTION")?.forEach((fn) => fn(message));
|
|
2880
2918
|
},
|
|
2881
2919
|
onConnectionStateChanged: (state) => {
|
|
2882
2920
|
connectionStateListeners.current.forEach(
|
|
@@ -2939,32 +2977,32 @@ var MeetingProvider = ({
|
|
|
2939
2977
|
activeSpeakerIds,
|
|
2940
2978
|
recording,
|
|
2941
2979
|
usePubSub: (topic) => {
|
|
2980
|
+
if (topic === "SECURE_CHAT") {
|
|
2981
|
+
const chatMessages = messages.map((message) => ({
|
|
2982
|
+
id: message.id,
|
|
2983
|
+
topic: "SECURE_CHAT",
|
|
2984
|
+
sender_id: message.sender_id,
|
|
2985
|
+
sender_name: message.sender_name,
|
|
2986
|
+
timestamp: message.timestamp,
|
|
2987
|
+
data: message
|
|
2988
|
+
}));
|
|
2989
|
+
return {
|
|
2990
|
+
messages: chatMessages,
|
|
2991
|
+
publish: ((data) => {
|
|
2992
|
+
sdk.publishPubSub("SECURE_CHAT", data);
|
|
2993
|
+
})
|
|
2994
|
+
};
|
|
2995
|
+
}
|
|
2942
2996
|
if (topic === "REACTION") {
|
|
2943
2997
|
return {
|
|
2944
|
-
messages:
|
|
2945
|
-
publish: (data) => {
|
|
2946
|
-
|
|
2947
|
-
if (!reaction?.emoji) {
|
|
2998
|
+
messages: reactionPubSubMessages,
|
|
2999
|
+
publish: ((data) => {
|
|
3000
|
+
if (!data?.emoji) {
|
|
2948
3001
|
console.warn("[PubSub] REACTION requires an emoji");
|
|
2949
3002
|
return;
|
|
2950
3003
|
}
|
|
2951
|
-
sdk.
|
|
2952
|
-
}
|
|
2953
|
-
};
|
|
2954
|
-
}
|
|
2955
|
-
if (topic === "SECURE_CHAT") {
|
|
2956
|
-
return {
|
|
2957
|
-
messages: sdk.state.getChatMessages().map((message) => ({
|
|
2958
|
-
id: message.id,
|
|
2959
|
-
topic: "SECURE_CHAT",
|
|
2960
|
-
sender_id: message.sender_id,
|
|
2961
|
-
sender_name: message.sender_name,
|
|
2962
|
-
timestamp: message.timestamp,
|
|
2963
|
-
data: message
|
|
2964
|
-
})),
|
|
2965
|
-
publish: (data) => {
|
|
2966
|
-
sdk.sendChatMessage(data);
|
|
2967
|
-
}
|
|
3004
|
+
sdk.publishPubSub("REACTION", data);
|
|
3005
|
+
})
|
|
2968
3006
|
};
|
|
2969
3007
|
}
|
|
2970
3008
|
throw new Error(`Unsupported PubSub topic: "${topic}"`);
|
|
@@ -3049,7 +3087,8 @@ var MeetingProvider = ({
|
|
|
3049
3087
|
messages,
|
|
3050
3088
|
presenterId,
|
|
3051
3089
|
recording,
|
|
3052
|
-
activeSpeakerIds
|
|
3090
|
+
activeSpeakerIds,
|
|
3091
|
+
reactionPubSubMessages
|
|
3053
3092
|
]);
|
|
3054
3093
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MeetingContext.Provider, { value, children });
|
|
3055
3094
|
};
|
|
@@ -3286,7 +3325,10 @@ function usePubSub(topic, options) {
|
|
|
3286
3325
|
const ctx = useMeetingContext();
|
|
3287
3326
|
(0, import_react8.useEffect)(() => {
|
|
3288
3327
|
if (!options?.onMessageReceived) return;
|
|
3289
|
-
return ctx.onPubSubMessage(
|
|
3328
|
+
return ctx.onPubSubMessage(
|
|
3329
|
+
topic,
|
|
3330
|
+
options.onMessageReceived
|
|
3331
|
+
);
|
|
3290
3332
|
}, [ctx, topic, options?.onMessageReceived]);
|
|
3291
3333
|
return ctx.usePubSub(topic);
|
|
3292
3334
|
}
|