@defcomm/meetingsdk 0.6.2 → 0.6.4

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
@@ -30,6 +30,7 @@ type Events = {
30
30
  onMeetingLeft?: () => void;
31
31
  onChatMessage?: (msg: ChatMessage) => void;
32
32
  onReaction?: (reaction: Reaction) => void;
33
+ onHandRaised?: (participantId: string, raised: boolean) => void;
33
34
  onNetworkQuality?: (quality: NetworkQuality) => void;
34
35
  onScreenShareStarted?: (peerId: string, stream: MediaStream) => void;
35
36
  onScreenShareStopped?: (peerId: string) => void;
@@ -104,6 +105,7 @@ type Participant = {
104
105
  isLocal?: boolean;
105
106
  media?: ParticipantMedia;
106
107
  isPresenter?: boolean;
108
+ handRaised?: boolean;
107
109
  connectionState?: "connected" | "reconnecting" | "disconnected";
108
110
  };
109
111
  type ParticipantMedia = {
@@ -239,6 +241,7 @@ interface VideoSDKCoreOptions {
239
241
  onRoomUpdate?: (data: any) => void;
240
242
  onChatMessage?: (message: ChatMessage) => void;
241
243
  onReaction?: (reaction: Reaction) => void;
244
+ onHandRaised?: (participantId: string, raised: boolean) => void;
242
245
  onNetworkQuality?: (quality: NetworkQuality) => void;
243
246
  onMuteStateChanged?: (peerId: string, kind: "audio" | "video", muted: boolean) => void;
244
247
  }
@@ -260,6 +263,7 @@ type LocalParticipantPatch = {
260
263
  name?: string;
261
264
  isHost?: boolean;
262
265
  isModerator?: boolean;
266
+ handRaised?: boolean;
263
267
  permissions?: any;
264
268
  media?: Partial<ParticipantMedia>;
265
269
  };
@@ -284,6 +288,7 @@ declare class MeetingState {
284
288
  removeParticipant(id: string): void;
285
289
  updateParticipantMedia(id: string, patch: Partial<NonNullable<Participant["media"]>>): void;
286
290
  updateLocalParticipant(patch: LocalParticipantPatch): void;
291
+ setParticipantHandRaised(id: string, raised: boolean): void;
287
292
  addChatMessage(msg: ChatMessage): void;
288
293
  getChatMessages(): ChatMessage[];
289
294
  clearChat(): void;
@@ -359,6 +364,8 @@ declare class VideoSDKCore {
359
364
  }>;
360
365
  sendChatMessage(payload: ChatInput): void;
361
366
  sendReaction(reaction: string): void;
367
+ setHandRaised(raised: boolean): void;
368
+ toggleHandRaised(): void;
362
369
  /**
363
370
  * Generic PubSub publishing entry point.
364
371
  *
@@ -417,6 +424,8 @@ type MeetingContextValue = {
417
424
  stopScreenShare: () => void;
418
425
  sendMessage: (input: ChatInput) => void;
419
426
  sendReaction: (emoji: string) => void;
427
+ setHandRaised: (raised: boolean) => void;
428
+ toggleHandRaised: () => void;
420
429
  room: {
421
430
  id: string | null;
422
431
  name: string | null;
@@ -453,6 +462,7 @@ type MeetingContextValue = {
453
462
  onRecordingStarted: (cb: (recording: Recording) => void) => () => void;
454
463
  onRecordingStopped: (cb: (recording: any) => void) => () => void;
455
464
  onReaction: (cb: (reaction: Reaction) => void) => () => void;
465
+ onHandRaised: (cb: (participantId: string, raised: boolean) => void) => () => void;
456
466
  onConnectionStateChanged: (cb: (state: SFUConnectionState) => void) => () => void;
457
467
  onActiveSpeakersChanged: (cb: (participantIds: string[]) => void) => () => void;
458
468
  onNetworkQuality: (cb: (quality: NetworkQuality) => void) => () => void;
@@ -478,6 +488,7 @@ declare const useMeeting: (handlers?: {
478
488
  onRecordingStarted?: (recording: any) => void;
479
489
  onRecordingStopped?: (recording: any) => void;
480
490
  onReaction?: (reaction: any) => void;
491
+ onHandRaised?: (participantId: string, raised: boolean) => void;
481
492
  onActiveSpeakersChanged?: (participantIds: string[]) => void;
482
493
  onConnectionStateChanged?: (state: SFUConnectionState) => void;
483
494
  onNetworkQuality?: (quality: NetworkQuality) => void;
@@ -509,6 +520,8 @@ declare const useMeeting: (handlers?: {
509
520
  stopScreenShare: () => void;
510
521
  sendMessage: (input: ChatInput) => void;
511
522
  sendReaction: (emoji: string) => void;
523
+ setHandRaised: (raised: boolean) => void;
524
+ toggleHandRaised: () => void;
512
525
  room: {
513
526
  id: string | null;
514
527
  name: string | null;
@@ -545,6 +558,7 @@ declare const useMeeting: (handlers?: {
545
558
  onRecordingStarted: (cb: (recording: Recording) => void) => () => void;
546
559
  onRecordingStopped: (cb: (recording: any) => void) => () => void;
547
560
  onReaction: (cb: (reaction: Reaction) => void) => () => void;
561
+ onHandRaised: (cb: (participantId: string, raised: boolean) => void) => () => void;
548
562
  onConnectionStateChanged: (cb: (state: SFUConnectionState) => void) => () => void;
549
563
  onActiveSpeakersChanged: (cb: (participantIds: string[]) => void) => () => void;
550
564
  onNetworkQuality: (cb: (quality: NetworkQuality) => void) => () => void;
package/dist/index.d.ts CHANGED
@@ -30,6 +30,7 @@ type Events = {
30
30
  onMeetingLeft?: () => void;
31
31
  onChatMessage?: (msg: ChatMessage) => void;
32
32
  onReaction?: (reaction: Reaction) => void;
33
+ onHandRaised?: (participantId: string, raised: boolean) => void;
33
34
  onNetworkQuality?: (quality: NetworkQuality) => void;
34
35
  onScreenShareStarted?: (peerId: string, stream: MediaStream) => void;
35
36
  onScreenShareStopped?: (peerId: string) => void;
@@ -104,6 +105,7 @@ type Participant = {
104
105
  isLocal?: boolean;
105
106
  media?: ParticipantMedia;
106
107
  isPresenter?: boolean;
108
+ handRaised?: boolean;
107
109
  connectionState?: "connected" | "reconnecting" | "disconnected";
108
110
  };
109
111
  type ParticipantMedia = {
@@ -239,6 +241,7 @@ interface VideoSDKCoreOptions {
239
241
  onRoomUpdate?: (data: any) => void;
240
242
  onChatMessage?: (message: ChatMessage) => void;
241
243
  onReaction?: (reaction: Reaction) => void;
244
+ onHandRaised?: (participantId: string, raised: boolean) => void;
242
245
  onNetworkQuality?: (quality: NetworkQuality) => void;
243
246
  onMuteStateChanged?: (peerId: string, kind: "audio" | "video", muted: boolean) => void;
244
247
  }
@@ -260,6 +263,7 @@ type LocalParticipantPatch = {
260
263
  name?: string;
261
264
  isHost?: boolean;
262
265
  isModerator?: boolean;
266
+ handRaised?: boolean;
263
267
  permissions?: any;
264
268
  media?: Partial<ParticipantMedia>;
265
269
  };
@@ -284,6 +288,7 @@ declare class MeetingState {
284
288
  removeParticipant(id: string): void;
285
289
  updateParticipantMedia(id: string, patch: Partial<NonNullable<Participant["media"]>>): void;
286
290
  updateLocalParticipant(patch: LocalParticipantPatch): void;
291
+ setParticipantHandRaised(id: string, raised: boolean): void;
287
292
  addChatMessage(msg: ChatMessage): void;
288
293
  getChatMessages(): ChatMessage[];
289
294
  clearChat(): void;
@@ -359,6 +364,8 @@ declare class VideoSDKCore {
359
364
  }>;
360
365
  sendChatMessage(payload: ChatInput): void;
361
366
  sendReaction(reaction: string): void;
367
+ setHandRaised(raised: boolean): void;
368
+ toggleHandRaised(): void;
362
369
  /**
363
370
  * Generic PubSub publishing entry point.
364
371
  *
@@ -417,6 +424,8 @@ type MeetingContextValue = {
417
424
  stopScreenShare: () => void;
418
425
  sendMessage: (input: ChatInput) => void;
419
426
  sendReaction: (emoji: string) => void;
427
+ setHandRaised: (raised: boolean) => void;
428
+ toggleHandRaised: () => void;
420
429
  room: {
421
430
  id: string | null;
422
431
  name: string | null;
@@ -453,6 +462,7 @@ type MeetingContextValue = {
453
462
  onRecordingStarted: (cb: (recording: Recording) => void) => () => void;
454
463
  onRecordingStopped: (cb: (recording: any) => void) => () => void;
455
464
  onReaction: (cb: (reaction: Reaction) => void) => () => void;
465
+ onHandRaised: (cb: (participantId: string, raised: boolean) => void) => () => void;
456
466
  onConnectionStateChanged: (cb: (state: SFUConnectionState) => void) => () => void;
457
467
  onActiveSpeakersChanged: (cb: (participantIds: string[]) => void) => () => void;
458
468
  onNetworkQuality: (cb: (quality: NetworkQuality) => void) => () => void;
@@ -478,6 +488,7 @@ declare const useMeeting: (handlers?: {
478
488
  onRecordingStarted?: (recording: any) => void;
479
489
  onRecordingStopped?: (recording: any) => void;
480
490
  onReaction?: (reaction: any) => void;
491
+ onHandRaised?: (participantId: string, raised: boolean) => void;
481
492
  onActiveSpeakersChanged?: (participantIds: string[]) => void;
482
493
  onConnectionStateChanged?: (state: SFUConnectionState) => void;
483
494
  onNetworkQuality?: (quality: NetworkQuality) => void;
@@ -509,6 +520,8 @@ declare const useMeeting: (handlers?: {
509
520
  stopScreenShare: () => void;
510
521
  sendMessage: (input: ChatInput) => void;
511
522
  sendReaction: (emoji: string) => void;
523
+ setHandRaised: (raised: boolean) => void;
524
+ toggleHandRaised: () => void;
512
525
  room: {
513
526
  id: string | null;
514
527
  name: string | null;
@@ -545,6 +558,7 @@ declare const useMeeting: (handlers?: {
545
558
  onRecordingStarted: (cb: (recording: Recording) => void) => () => void;
546
559
  onRecordingStopped: (cb: (recording: any) => void) => () => void;
547
560
  onReaction: (cb: (reaction: Reaction) => void) => () => void;
561
+ onHandRaised: (cb: (participantId: string, raised: boolean) => void) => () => void;
548
562
  onConnectionStateChanged: (cb: (state: SFUConnectionState) => void) => () => void;
549
563
  onActiveSpeakersChanged: (cb: (participantIds: string[]) => void) => () => void;
550
564
  onNetworkQuality: (cb: (quality: NetworkQuality) => void) => () => void;
package/dist/index.js CHANGED
@@ -317,6 +317,7 @@ var MeetingState = class {
317
317
  name: patch.name ?? "",
318
318
  isHost: patch.isHost ?? false,
319
319
  isModerator: patch.isModerator ?? false,
320
+ handRaised: patch.handRaised ?? false,
320
321
  permissions: patch.permissions,
321
322
  media: {
322
323
  stream: patch.media?.stream ?? null,
@@ -364,6 +365,21 @@ var MeetingState = class {
364
365
  };
365
366
  this.notify("localParticipant");
366
367
  }
368
+ setParticipantHandRaised(id, raised) {
369
+ const p = id === this.localParticipant?.id ? this.localParticipant : this.participants.get(id);
370
+ if (!p || p.handRaised === raised) return;
371
+ const updated = { ...p, handRaised: raised };
372
+ if (id === this.localParticipant?.id) {
373
+ this.localParticipant = updated;
374
+ this.notify("localParticipant");
375
+ } else {
376
+ const next = new Map(this.participants);
377
+ next.set(id, updated);
378
+ this.participants = next;
379
+ this.notify(`participant:${id}`);
380
+ this.notify("participants");
381
+ }
382
+ }
367
383
  // ---- chat ----
368
384
  addChatMessage(msg) {
369
385
  this.chatMessages.set(msg.id, msg);
@@ -512,6 +528,8 @@ var SFUClient = class {
512
528
  });
513
529
  this.onReaction = options.onReaction || (() => {
514
530
  });
531
+ this.onHandRaised = options.onHandRaised || (() => {
532
+ });
515
533
  this.onRoomUpdate = options.onRoomUpdate || (() => {
516
534
  });
517
535
  this.onNetworkQuality = options.onNetworkQuality || (() => {
@@ -829,8 +847,9 @@ var SFUClient = class {
829
847
  case "join_approved": {
830
848
  const requestId = payload.request_id || message.request_id;
831
849
  if (!requestId) break;
850
+ const participantId = payload.user_id || payload.participant_id || payload.participantId || payload.request?.user_id || payload.request?.participant_id;
832
851
  this.pendingJoinRequestId = requestId;
833
- this.onJoinApproved(requestId);
852
+ this.onJoinApproved(requestId, participantId);
834
853
  if (this.ws?.readyState === WebSocket.OPEN) {
835
854
  this.setState("joining");
836
855
  this.send({
@@ -853,9 +872,10 @@ var SFUClient = class {
853
872
  break;
854
873
  }
855
874
  case "join_rejected": {
856
- const requestId = payload.request_id || message.request_id;
875
+ const requestId = payload.request_id;
857
876
  const reason = payload.reason;
858
- this.onJoinRejected(requestId, reason);
877
+ const participantId = payload.user_id || payload.participant_id;
878
+ this.onJoinRejected(requestId, reason, participantId);
859
879
  this.pendingJoinRequestId = null;
860
880
  this.intentionalClose = true;
861
881
  this.failJoin(new Error(reason || "Join request rejected"));
@@ -1110,10 +1130,20 @@ var SFUClient = class {
1110
1130
  if (reaction?.id && reaction?.emoji) this.onReaction(reaction);
1111
1131
  break;
1112
1132
  }
1133
+ case "hand_raised": {
1134
+ const participantId = String(
1135
+ payload.participant_id ?? payload.participantId ?? ""
1136
+ );
1137
+ const raised = Boolean(payload.raised);
1138
+ if (participantId) this.onHandRaised(participantId, raised);
1139
+ break;
1140
+ }
1113
1141
  case "network_quality": {
1114
1142
  const raw = payload.quality || payload;
1115
1143
  const quality = {
1116
- participant_id: String(raw.participant_id ?? this.currentParticipantId ?? this.participantId),
1144
+ participant_id: String(
1145
+ raw.participant_id ?? this.currentParticipantId ?? this.participantId
1146
+ ),
1117
1147
  quality: String(raw.quality ?? "unknown"),
1118
1148
  score: Number(raw.score ?? 0),
1119
1149
  recommended_action: String(raw.recommended_action ?? "maintain"),
@@ -1573,7 +1603,9 @@ var SFUClient = class {
1573
1603
  */
1574
1604
  async getMediaDevices() {
1575
1605
  if (!navigator.mediaDevices?.enumerateDevices) {
1576
- throw new Error("Media device enumeration is not supported on this device");
1606
+ throw new Error(
1607
+ "Media device enumeration is not supported on this device"
1608
+ );
1577
1609
  }
1578
1610
  return navigator.mediaDevices.enumerateDevices();
1579
1611
  }
@@ -1893,7 +1925,9 @@ var SFUClient = class {
1893
1925
  );
1894
1926
  const text = await response.text();
1895
1927
  if (!response.ok) {
1896
- throw new Error(`Meeting summary request failed: ${response.status} ${text}`);
1928
+ throw new Error(
1929
+ `Meeting summary request failed: ${response.status} ${text}`
1930
+ );
1897
1931
  }
1898
1932
  return JSON.parse(text);
1899
1933
  }
@@ -2035,6 +2069,14 @@ var SFUClient = class {
2035
2069
  }
2036
2070
  });
2037
2071
  }
2072
+ setHandRaised(raised) {
2073
+ this.send({
2074
+ type: "set_hand_raised",
2075
+ payload: {
2076
+ raised
2077
+ }
2078
+ });
2079
+ }
2038
2080
  removeRemoteParticipant(participantId) {
2039
2081
  const stream = this.remoteStreams.get(participantId);
2040
2082
  if (stream) {
@@ -2469,6 +2511,7 @@ var VideoSDKCore = class {
2469
2511
  isHost,
2470
2512
  isModerator,
2471
2513
  permissions,
2514
+ handRaised: Boolean(local?.hand_raised),
2472
2515
  media: {
2473
2516
  micEnabled: !Boolean(local?.audio_muted),
2474
2517
  camEnabled: !Boolean(local?.video_muted)
@@ -2496,6 +2539,7 @@ var VideoSDKCore = class {
2496
2539
  this.state.updateLocalParticipant({
2497
2540
  id: this.myId,
2498
2541
  name: this.participantName,
2542
+ handRaised: Boolean(local.hand_raised),
2499
2543
  media: {
2500
2544
  micEnabled: !Boolean(local.audio_muted),
2501
2545
  camEnabled: !Boolean(local.video_muted),
@@ -2527,23 +2571,32 @@ var VideoSDKCore = class {
2527
2571
  onJoinPending: (info) => {
2528
2572
  console.log("[SFU] Join request pending", info);
2529
2573
  },
2530
- onJoinApproved: (requestId) => {
2531
- console.log("[SFU] Join approved", requestId);
2574
+ onJoinApproved: (requestId, participantId) => {
2575
+ const targetParticipantId = participantId || this.myId;
2576
+ console.log("[SFU] Join approved", {
2577
+ requestId,
2578
+ participantId: targetParticipantId
2579
+ });
2532
2580
  this.events.onJoinApproved?.(requestId);
2533
2581
  this.events.onEntryResponded?.(
2534
2582
  {
2535
- participantId: this.myId,
2583
+ participantId: targetParticipantId,
2536
2584
  decision: "approved"
2537
2585
  },
2538
2586
  "approved"
2539
2587
  );
2540
2588
  },
2541
- onJoinRejected: (requestId, reason) => {
2542
- console.warn("[SFU] Join rejected", requestId, reason);
2589
+ onJoinRejected: (requestId, reason, participantId) => {
2590
+ const targetParticipantId = participantId || this.myId;
2591
+ console.warn("[SFU] Join rejected", {
2592
+ requestId,
2593
+ participantId: targetParticipantId,
2594
+ reason
2595
+ });
2543
2596
  this.events.onJoinRejected?.(requestId);
2544
2597
  this.events.onEntryResponded?.(
2545
2598
  {
2546
- participantId: this.myId,
2599
+ participantId: targetParticipantId,
2547
2600
  decision: "rejected"
2548
2601
  },
2549
2602
  "rejected"
@@ -2574,6 +2627,10 @@ var VideoSDKCore = class {
2574
2627
  onReaction: (reaction) => {
2575
2628
  this.events.onReaction?.(reaction);
2576
2629
  },
2630
+ onHandRaised: (participantId, raised) => {
2631
+ this.state.setParticipantHandRaised(participantId, raised);
2632
+ this.events.onHandRaised?.(participantId, raised);
2633
+ },
2577
2634
  onJoinRequestCanceled: (requestId) => {
2578
2635
  this.events.onJoinRequestCanceled?.(requestId);
2579
2636
  },
@@ -2599,6 +2656,7 @@ var VideoSDKCore = class {
2599
2656
  id: this.myId,
2600
2657
  name: this.participantName,
2601
2658
  isHost: current?.isHost,
2659
+ handRaised: current?.handRaised,
2602
2660
  isModerator: Boolean(permissions?.moderate),
2603
2661
  permissions
2604
2662
  });
@@ -2628,6 +2686,7 @@ var VideoSDKCore = class {
2628
2686
  id: pid,
2629
2687
  name: pname,
2630
2688
  isModerator: Boolean(participant?.permissions?.moderate),
2689
+ handRaised: Boolean(participant?.hand_raised),
2631
2690
  permissions: participant?.permissions,
2632
2691
  connectionState: "connected",
2633
2692
  media: {
@@ -3145,6 +3204,16 @@ var VideoSDKCore = class {
3145
3204
  }
3146
3205
  this.sfuClient.sendReaction(reaction);
3147
3206
  }
3207
+ setHandRaised(raised) {
3208
+ if (!this.sfuClient) {
3209
+ console.warn("SFU Client not connected");
3210
+ return;
3211
+ }
3212
+ this.sfuClient.setHandRaised(raised);
3213
+ }
3214
+ toggleHandRaised() {
3215
+ this.setHandRaised(!Boolean(this.state.localParticipant?.handRaised));
3216
+ }
3148
3217
  /**
3149
3218
  * Generic PubSub publishing entry point.
3150
3219
  *
@@ -3265,6 +3334,9 @@ var MeetingProvider = ({
3265
3334
  const recordingStartedListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
3266
3335
  const recordingStoppedListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
3267
3336
  const reactionListeners = (0, import_react2.useRef)(/* @__PURE__ */ new Set());
3337
+ const handRaisedListeners = (0, import_react2.useRef)(
3338
+ /* @__PURE__ */ new Set()
3339
+ );
3268
3340
  const pubSubListeners = (0, import_react2.useRef)(
3269
3341
  /* @__PURE__ */ new Map()
3270
3342
  );
@@ -3368,6 +3440,9 @@ var MeetingProvider = ({
3368
3440
  );
3369
3441
  pubSubListeners.current.get("REACTION")?.forEach((fn) => fn(message));
3370
3442
  },
3443
+ onHandRaised: (participantId, raised) => {
3444
+ handRaisedListeners.current.forEach((fn) => fn(participantId, raised));
3445
+ },
3371
3446
  onNetworkQuality: (quality) => {
3372
3447
  networkQualityListeners.current.forEach((fn) => fn(quality));
3373
3448
  },
@@ -3440,6 +3515,8 @@ var MeetingProvider = ({
3440
3515
  stopScreenShare: sdk.stopScreenShare.bind(sdk),
3441
3516
  sendMessage: sdk.sendChatMessage.bind(sdk),
3442
3517
  sendReaction: sdk.sendReaction.bind(sdk),
3518
+ setHandRaised: sdk.setHandRaised.bind(sdk),
3519
+ toggleHandRaised: sdk.toggleHandRaised.bind(sdk),
3443
3520
  room: sdk.getMeeting(),
3444
3521
  localParticipant,
3445
3522
  participants,
@@ -3565,6 +3642,10 @@ var MeetingProvider = ({
3565
3642
  reactionListeners.current.add(cb);
3566
3643
  return () => reactionListeners.current.delete(cb);
3567
3644
  },
3645
+ onHandRaised: (cb) => {
3646
+ handRaisedListeners.current.add(cb);
3647
+ return () => handRaisedListeners.current.delete(cb);
3648
+ },
3568
3649
  onNetworkQuality: (cb) => {
3569
3650
  networkQualityListeners.current.add(cb);
3570
3651
  return () => networkQualityListeners.current.delete(cb);
@@ -3732,6 +3813,10 @@ var useMeeting = (handlers) => {
3732
3813
  if (!handlers?.onReaction) return;
3733
3814
  return ctx.onReaction(handlers.onReaction);
3734
3815
  }, [handlers?.onReaction]);
3816
+ (0, import_react4.useEffect)(() => {
3817
+ if (!handlers?.onHandRaised) return;
3818
+ return ctx.onHandRaised(handlers.onHandRaised);
3819
+ }, [handlers?.onHandRaised]);
3735
3820
  const { sdk: _, ...publicApi } = ctx;
3736
3821
  return publicApi;
3737
3822
  };