@defcomm/meetingsdk 0.4.8 → 0.5.0

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 CHANGED
@@ -17,6 +17,9 @@ type Events = {
17
17
  onActiveSpeakersChanged?: (participantIds: string[]) => void;
18
18
  onJoinApproved?: (requestId: string) => void;
19
19
  onJoinRejected?: (requestId: string) => void;
20
+ onJoinRequestCanceled?: (requestId: string) => void;
21
+ onParticipantRemoved?: (participantId: string, removedBy: string) => void;
22
+ onParticipantPermissionsChanged?: (participantId: string, permissions: any) => void;
20
23
  onConnectionStateChanged?: (state: string) => void;
21
24
  onRoomUpdate?: (data: any) => void;
22
25
  onUserLeft?: (id: string) => void;
@@ -91,6 +94,8 @@ type Participant = {
91
94
  id: string;
92
95
  name?: string;
93
96
  isHost?: boolean;
97
+ isModerator?: boolean;
98
+ permissions?: any;
94
99
  isLocal?: boolean;
95
100
  media?: ParticipantMedia;
96
101
  isPresenter?: boolean;
@@ -170,6 +175,7 @@ interface VideoSDKCoreOptions {
170
175
  onRecordingStopped?: (recording: any) => void;
171
176
  onRoomUpdate?: (data: any) => void;
172
177
  onChatMessage?: (message: ChatMessage) => void;
178
+ onReaction?: (reaction: Reaction) => void;
173
179
  onMuteStateChanged?: (peerId: string, kind: "audio" | "video", muted: boolean) => void;
174
180
  }
175
181
  type SFUConnectionState = "idle" | "connecting" | "joining" | "waiting_approval" | "connected" | "reconnecting" | "leaving" | "disconnected";
@@ -188,6 +194,9 @@ declare const useLocalParticipant: () => {
188
194
  type LocalParticipantPatch = {
189
195
  id?: string;
190
196
  name?: string;
197
+ isHost?: boolean;
198
+ isModerator?: boolean;
199
+ permissions?: any;
191
200
  media?: Partial<ParticipantMedia>;
192
201
  };
193
202
  declare class MeetingState {
@@ -259,6 +268,13 @@ declare class VideoSDKCore {
259
268
  };
260
269
  approveJoinRequest(requestId: string): Promise<void>;
261
270
  rejectJoinRequest(requestId: string, reason?: string): Promise<void>;
271
+ cancelJoinRequest(requestId: string): Promise<void | undefined>;
272
+ muteAllAudio(): Promise<void>;
273
+ unmuteAllAudio(): Promise<void>;
274
+ removeParticipant(participantId: string): Promise<void>;
275
+ getModerators(roomCode: string): Promise<any>;
276
+ addModerator(roomCode: string, userId: string): Promise<any>;
277
+ removeModerator(roomCode: string, userId: string): Promise<any>;
262
278
  toggleMic(): void;
263
279
  toggleCam(): void;
264
280
  startScreenShare(): Promise<MediaStream | null>;
@@ -334,6 +350,13 @@ type MeetingContextValue = {
334
350
  onPubSubMessage: <T extends PubSubTopic>(topic: T, cb: (message: PubSubMessage<PubSubTopicConfig[T]["message"]>) => void) => () => void;
335
351
  approveJoinRequest: (requestId: string) => void;
336
352
  rejectJoinRequest: (requestId: string) => void;
353
+ cancelJoinRequest: (requestId: string) => Promise<void> | undefined;
354
+ muteAllAudio: () => Promise<void>;
355
+ unmuteAllAudio: () => Promise<void>;
356
+ removeParticipant: (participantId: string) => Promise<void>;
357
+ getModerators: (roomCode: string) => Promise<any> | undefined;
358
+ addModerator: (roomCode: string, userId: string) => Promise<any> | undefined;
359
+ removeModerator: (roomCode: string, userId: string) => Promise<any> | undefined;
337
360
  startRecording: () => Promise<void>;
338
361
  stopRecording: () => Promise<void>;
339
362
  getRecordingStatus: () => Promise<any>;
@@ -397,6 +420,13 @@ declare const useMeeting: (handlers?: {
397
420
  onPubSubMessage: <T extends PubSubTopic>(topic: T, cb: (message: PubSubMessage<PubSubTopicConfig[T]["message"]>) => void) => () => void;
398
421
  approveJoinRequest: (requestId: string) => void;
399
422
  rejectJoinRequest: (requestId: string) => void;
423
+ cancelJoinRequest: (requestId: string) => Promise<void> | undefined;
424
+ muteAllAudio: () => Promise<void>;
425
+ unmuteAllAudio: () => Promise<void>;
426
+ removeParticipant: (participantId: string) => Promise<void>;
427
+ getModerators: (roomCode: string) => Promise<any> | undefined;
428
+ addModerator: (roomCode: string, userId: string) => Promise<any> | undefined;
429
+ removeModerator: (roomCode: string, userId: string) => Promise<any> | undefined;
400
430
  startRecording: () => Promise<void>;
401
431
  stopRecording: () => Promise<void>;
402
432
  getRecordingStatus: () => Promise<any>;
package/dist/index.d.ts CHANGED
@@ -17,6 +17,9 @@ type Events = {
17
17
  onActiveSpeakersChanged?: (participantIds: string[]) => void;
18
18
  onJoinApproved?: (requestId: string) => void;
19
19
  onJoinRejected?: (requestId: string) => void;
20
+ onJoinRequestCanceled?: (requestId: string) => void;
21
+ onParticipantRemoved?: (participantId: string, removedBy: string) => void;
22
+ onParticipantPermissionsChanged?: (participantId: string, permissions: any) => void;
20
23
  onConnectionStateChanged?: (state: string) => void;
21
24
  onRoomUpdate?: (data: any) => void;
22
25
  onUserLeft?: (id: string) => void;
@@ -91,6 +94,8 @@ type Participant = {
91
94
  id: string;
92
95
  name?: string;
93
96
  isHost?: boolean;
97
+ isModerator?: boolean;
98
+ permissions?: any;
94
99
  isLocal?: boolean;
95
100
  media?: ParticipantMedia;
96
101
  isPresenter?: boolean;
@@ -170,6 +175,7 @@ interface VideoSDKCoreOptions {
170
175
  onRecordingStopped?: (recording: any) => void;
171
176
  onRoomUpdate?: (data: any) => void;
172
177
  onChatMessage?: (message: ChatMessage) => void;
178
+ onReaction?: (reaction: Reaction) => void;
173
179
  onMuteStateChanged?: (peerId: string, kind: "audio" | "video", muted: boolean) => void;
174
180
  }
175
181
  type SFUConnectionState = "idle" | "connecting" | "joining" | "waiting_approval" | "connected" | "reconnecting" | "leaving" | "disconnected";
@@ -188,6 +194,9 @@ declare const useLocalParticipant: () => {
188
194
  type LocalParticipantPatch = {
189
195
  id?: string;
190
196
  name?: string;
197
+ isHost?: boolean;
198
+ isModerator?: boolean;
199
+ permissions?: any;
191
200
  media?: Partial<ParticipantMedia>;
192
201
  };
193
202
  declare class MeetingState {
@@ -259,6 +268,13 @@ declare class VideoSDKCore {
259
268
  };
260
269
  approveJoinRequest(requestId: string): Promise<void>;
261
270
  rejectJoinRequest(requestId: string, reason?: string): Promise<void>;
271
+ cancelJoinRequest(requestId: string): Promise<void | undefined>;
272
+ muteAllAudio(): Promise<void>;
273
+ unmuteAllAudio(): Promise<void>;
274
+ removeParticipant(participantId: string): Promise<void>;
275
+ getModerators(roomCode: string): Promise<any>;
276
+ addModerator(roomCode: string, userId: string): Promise<any>;
277
+ removeModerator(roomCode: string, userId: string): Promise<any>;
262
278
  toggleMic(): void;
263
279
  toggleCam(): void;
264
280
  startScreenShare(): Promise<MediaStream | null>;
@@ -334,6 +350,13 @@ type MeetingContextValue = {
334
350
  onPubSubMessage: <T extends PubSubTopic>(topic: T, cb: (message: PubSubMessage<PubSubTopicConfig[T]["message"]>) => void) => () => void;
335
351
  approveJoinRequest: (requestId: string) => void;
336
352
  rejectJoinRequest: (requestId: string) => void;
353
+ cancelJoinRequest: (requestId: string) => Promise<void> | undefined;
354
+ muteAllAudio: () => Promise<void>;
355
+ unmuteAllAudio: () => Promise<void>;
356
+ removeParticipant: (participantId: string) => Promise<void>;
357
+ getModerators: (roomCode: string) => Promise<any> | undefined;
358
+ addModerator: (roomCode: string, userId: string) => Promise<any> | undefined;
359
+ removeModerator: (roomCode: string, userId: string) => Promise<any> | undefined;
337
360
  startRecording: () => Promise<void>;
338
361
  stopRecording: () => Promise<void>;
339
362
  getRecordingStatus: () => Promise<any>;
@@ -397,6 +420,13 @@ declare const useMeeting: (handlers?: {
397
420
  onPubSubMessage: <T extends PubSubTopic>(topic: T, cb: (message: PubSubMessage<PubSubTopicConfig[T]["message"]>) => void) => () => void;
398
421
  approveJoinRequest: (requestId: string) => void;
399
422
  rejectJoinRequest: (requestId: string) => void;
423
+ cancelJoinRequest: (requestId: string) => Promise<void> | undefined;
424
+ muteAllAudio: () => Promise<void>;
425
+ unmuteAllAudio: () => Promise<void>;
426
+ removeParticipant: (participantId: string) => Promise<void>;
427
+ getModerators: (roomCode: string) => Promise<any> | undefined;
428
+ addModerator: (roomCode: string, userId: string) => Promise<any> | undefined;
429
+ removeModerator: (roomCode: string, userId: string) => Promise<any> | undefined;
400
430
  startRecording: () => Promise<void>;
401
431
  stopRecording: () => Promise<void>;
402
432
  getRecordingStatus: () => Promise<any>;
package/dist/index.js CHANGED
@@ -476,6 +476,12 @@ var SFUClient = class {
476
476
  });
477
477
  this.onJoinRequested = options.onJoinRequested || (() => {
478
478
  });
479
+ this.onJoinRequestCanceled = options.onJoinRequestCanceled || (() => {
480
+ });
481
+ this.onParticipantRemoved = options.onParticipantRemoved || (() => {
482
+ });
483
+ this.onParticipantPermissionsChanged = options.onParticipantPermissionsChanged || (() => {
484
+ });
479
485
  this.onScreenShareStarted = options.onScreenShareStarted || (() => {
480
486
  });
481
487
  this.onScreenShareStopped = options.onScreenShareStopped || (() => {
@@ -843,6 +849,38 @@ var SFUClient = class {
843
849
  this.onJoinRequested(payload.request || payload);
844
850
  break;
845
851
  }
852
+ case "join_request_canceled": {
853
+ this.onJoinRequestCanceled(payload.request_id || message.request_id);
854
+ break;
855
+ }
856
+ case "participant_removed": {
857
+ const participantId = payload.participant_id;
858
+ if (!participantId) break;
859
+ const removedBy = payload.removed_by || "";
860
+ this.participants.delete(participantId);
861
+ this.removeRemoteParticipant(participantId);
862
+ if (participantId === this.currentParticipantId) {
863
+ this.intentionalClose = true;
864
+ this.pendingJoinRequestId = null;
865
+ this.setState("disconnected");
866
+ try {
867
+ this.ws?.close();
868
+ } catch {
869
+ }
870
+ }
871
+ this.onParticipantRemoved(participantId, removedBy);
872
+ break;
873
+ }
874
+ case "participant_permissions_changed": {
875
+ const participantId = payload.participant_id;
876
+ if (!participantId) break;
877
+ const participant = this.participants.get(participantId);
878
+ if (participant) {
879
+ this.participants.set(participantId, { ...participant, permissions: payload.permissions });
880
+ }
881
+ this.onParticipantPermissionsChanged(participantId, payload.permissions);
882
+ break;
883
+ }
846
884
  case "publish_answer": {
847
885
  if (!this.publisher) break;
848
886
  await this.publisher.setRemoteDescription({
@@ -1746,6 +1784,39 @@ var SFUClient = class {
1746
1784
  throw new Error("SFU signaling is not connected");
1747
1785
  }
1748
1786
  }
1787
+ async cancelJoinRequest(requestId) {
1788
+ if (!requestId) throw new Error("requestId is required");
1789
+ if (!this.send({ type: "cancel_join_request", payload: { request_id: requestId } })) {
1790
+ throw new Error("SFU signaling is not connected");
1791
+ }
1792
+ this.pendingJoinRequestId = null;
1793
+ }
1794
+ async muteAllAudio() {
1795
+ if (!this.send({ type: "mute_all_audio" })) throw new Error("SFU signaling is not connected");
1796
+ }
1797
+ async unmuteAllAudio() {
1798
+ if (!this.send({ type: "unmute_all_audio" })) throw new Error("SFU signaling is not connected");
1799
+ }
1800
+ async removeParticipant(participantId) {
1801
+ if (!participantId) throw new Error("participantId is required");
1802
+ if (!this.send({ type: "remove_participant", payload: { participant_id: participantId } })) {
1803
+ throw new Error("SFU signaling is not connected");
1804
+ }
1805
+ }
1806
+ async getModerators(roomCode) {
1807
+ return this.request(`${this.apiBase}/rooms/${encodeURIComponent(roomCode)}/moderators`);
1808
+ }
1809
+ async addModerator(roomCode, userId) {
1810
+ return this.request(`${this.apiBase}/rooms/${encodeURIComponent(roomCode)}/moderators`, {
1811
+ method: "POST",
1812
+ body: JSON.stringify({ user_id: userId })
1813
+ });
1814
+ }
1815
+ async removeModerator(roomCode, userId) {
1816
+ return this.request(`${this.apiBase}/rooms/${encodeURIComponent(roomCode)}/moderators/${encodeURIComponent(userId)}`, {
1817
+ method: "DELETE"
1818
+ });
1819
+ }
1749
1820
  isSocketOpen() {
1750
1821
  return this.ws?.readyState === WebSocket.OPEN;
1751
1822
  }
@@ -2267,6 +2338,33 @@ var VideoSDKCore = class {
2267
2338
  this.state.addChatMessage(msg);
2268
2339
  this.events.onChatMessage?.(msg);
2269
2340
  },
2341
+ onReaction: (reaction) => {
2342
+ this.events.onReaction?.(reaction);
2343
+ },
2344
+ onJoinRequestCanceled: (requestId) => {
2345
+ this.events.onJoinRequestCanceled?.(requestId);
2346
+ },
2347
+ onParticipantRemoved: (participantId, removedBy) => {
2348
+ if (participantId === this.myId) {
2349
+ this.intentionalDisconnect = true;
2350
+ this.events.onUserLeft?.(participantId);
2351
+ try {
2352
+ this.localStream?.getTracks().forEach((track) => track.enabled = false);
2353
+ } catch {
2354
+ }
2355
+ } else {
2356
+ this.cleanupRemoteParticipant(participantId);
2357
+ this.state.removeParticipant(participantId);
2358
+ this.events.onUserLeft?.(participantId);
2359
+ }
2360
+ this.events.onParticipantRemoved?.(participantId, removedBy);
2361
+ },
2362
+ onParticipantPermissionsChanged: (participantId, permissions) => {
2363
+ if (participantId === this.myId) {
2364
+ const current = this.state.localParticipant;
2365
+ this.state.updateLocalParticipant({ id: this.myId, name: this.participantName, isHost: Boolean(permissions?.moderate) && current?.isHost, isModerator: Boolean(permissions?.moderate), permissions });
2366
+ }
2367
+ },
2270
2368
  onJoinRequested: (request) => {
2271
2369
  const requestId = request?.request_id || request?.requestId;
2272
2370
  const participantId = request?.user_id || request?.participantId;
@@ -2290,6 +2388,8 @@ var VideoSDKCore = class {
2290
2388
  this.state.addParticipant({
2291
2389
  id: pid,
2292
2390
  name: pname,
2391
+ isModerator: Boolean(participant?.permissions?.moderate),
2392
+ permissions: participant?.permissions,
2293
2393
  connectionState: "connected",
2294
2394
  media: {
2295
2395
  micEnabled: true,
@@ -2336,7 +2436,18 @@ var VideoSDKCore = class {
2336
2436
  },
2337
2437
  // TRACKS
2338
2438
  onParticipantMediaState: (participantId, audioMuted, videoMuted) => {
2339
- if (participantId === this.myId) return;
2439
+ if (participantId === this.myId) {
2440
+ this.localStream?.getAudioTracks().forEach((track) => track.enabled = !audioMuted);
2441
+ this.localStream?.getVideoTracks().forEach((track) => track.enabled = !videoMuted);
2442
+ this.state.updateLocalParticipant({
2443
+ id: this.myId,
2444
+ name: this.participantName,
2445
+ media: { micEnabled: !audioMuted, camEnabled: !videoMuted }
2446
+ });
2447
+ this.events.onMuteStateChanged?.(participantId, "audio", audioMuted);
2448
+ this.events.onMuteStateChanged?.(participantId, "video", videoMuted);
2449
+ return;
2450
+ }
2340
2451
  const participant = this.state.getParticipant(participantId);
2341
2452
  if (!participant) return;
2342
2453
  this.state.updateParticipantMedia(participantId, {
@@ -2606,6 +2717,30 @@ var VideoSDKCore = class {
2606
2717
  }
2607
2718
  return this.sfuClient.rejectJoinRequest(requestId, reason);
2608
2719
  }
2720
+ async cancelJoinRequest(requestId) {
2721
+ return this.sfuClient?.cancelJoinRequest(requestId);
2722
+ }
2723
+ async muteAllAudio() {
2724
+ if (!this.sfuClient) throw new Error("SFU client is not connected");
2725
+ return this.sfuClient.muteAllAudio();
2726
+ }
2727
+ async unmuteAllAudio() {
2728
+ if (!this.sfuClient) throw new Error("SFU client is not connected");
2729
+ return this.sfuClient.unmuteAllAudio();
2730
+ }
2731
+ async removeParticipant(participantId) {
2732
+ if (!this.sfuClient) throw new Error("SFU client is not connected");
2733
+ return this.sfuClient.removeParticipant(participantId);
2734
+ }
2735
+ async getModerators(roomCode) {
2736
+ return this.sfuClient?.getModerators(roomCode);
2737
+ }
2738
+ async addModerator(roomCode, userId) {
2739
+ return this.sfuClient?.addModerator(roomCode, userId);
2740
+ }
2741
+ async removeModerator(roomCode, userId) {
2742
+ return this.sfuClient?.removeModerator(roomCode, userId);
2743
+ }
2609
2744
  // MEDIA CONTROL
2610
2745
  toggleMic() {
2611
2746
  const mediaState = this.state.localParticipant?.media;
@@ -2913,10 +3048,6 @@ var MeetingProvider = ({
2913
3048
  }
2914
3049
  };
2915
3050
  console.log("[MeetingProvider] PUBSUB REACTION", message);
2916
- pubSubListeners.current.get("REACTION")?.forEach((fn) => {
2917
- console.log("[MeetingProvider] DELIVERING REACTION");
2918
- fn(message);
2919
- });
2920
3051
  setReactionPubSubMessages(
2921
3052
  (previous) => [...previous, message].slice(-50)
2922
3053
  );
@@ -3031,6 +3162,13 @@ var MeetingProvider = ({
3031
3162
  },
3032
3163
  approveJoinRequest: sdk.approveJoinRequest.bind(sdk),
3033
3164
  rejectJoinRequest: sdk.rejectJoinRequest.bind(sdk),
3165
+ cancelJoinRequest: sdk.cancelJoinRequest.bind(sdk),
3166
+ muteAllAudio: sdk.muteAllAudio.bind(sdk),
3167
+ unmuteAllAudio: sdk.unmuteAllAudio.bind(sdk),
3168
+ removeParticipant: sdk.removeParticipant.bind(sdk),
3169
+ getModerators: sdk.getModerators.bind(sdk),
3170
+ addModerator: sdk.addModerator.bind(sdk),
3171
+ removeModerator: sdk.removeModerator.bind(sdk),
3034
3172
  startRecording: sdk.startRecording.bind(sdk),
3035
3173
  stopRecording: sdk.stopRecording.bind(sdk),
3036
3174
  getRecordingStatus: sdk.getRecordingStatus.bind(sdk),