@defcomm/meetingsdk 0.6.6 → 0.6.8

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
@@ -11,6 +11,7 @@ type Events = {
11
11
  onUserJoined?: (p: Participant) => void;
12
12
  /** Fired when a remote participant permanently joins the meeting. */
13
13
  onParticipantJoined?: (p: Participant) => void;
14
+ onParticipantPresence?: (participantId: string, presence: string) => void;
14
15
  onEntryRequested?: (req: EntryRequest) => void;
15
16
  onEntryResponded?: (payload: {
16
17
  participantId: string;
@@ -285,6 +286,12 @@ declare class MeetingState {
285
286
  clearRecording(): void;
286
287
  setNetworkQuality(quality: NetworkQuality | null): void;
287
288
  addParticipant(p: Participant): boolean;
289
+ /**
290
+ * Reconcile a participant received from a room snapshot without emitting a
291
+ * lifecycle/join event. Snapshot data is authoritative for current room
292
+ * membership, including after a reconnect/resume.
293
+ */
294
+ upsertParticipantSnapshot(p: Participant): void;
288
295
  removeParticipant(id: string): void;
289
296
  updateParticipantMedia(id: string, patch: Partial<NonNullable<Participant["media"]>>): void;
290
297
  updateLocalParticipant(patch: LocalParticipantPatch): void;
@@ -468,6 +475,7 @@ type MeetingContextValue = {
468
475
  onNetworkQuality: (cb: (quality: NetworkQuality) => void) => () => void;
469
476
  onChatMessage: (cb: (message: ChatMessage) => void) => () => void;
470
477
  onParticipantJoined: (cb: (participant: Participant) => void) => () => void;
478
+ onParticipantPresence: (cb: (participantId: string, presence: string) => void) => () => void;
471
479
  onParticipantLeft: (cb: (participant: Participant) => void) => () => void;
472
480
  };
473
481
  declare const MeetingProvider: ({ config, children, }: {
@@ -564,6 +572,7 @@ declare const useMeeting: (handlers?: {
564
572
  onNetworkQuality: (cb: (quality: NetworkQuality) => void) => () => void;
565
573
  onChatMessage: (cb: (message: ChatMessage) => void) => () => void;
566
574
  onParticipantJoined: (cb: (participant: Participant) => void) => () => void;
575
+ onParticipantPresence: (cb: (participantId: string, presence: string) => void) => () => void;
567
576
  onParticipantLeft: (cb: (participant: Participant) => void) => () => void;
568
577
  };
569
578
 
package/dist/index.d.ts CHANGED
@@ -11,6 +11,7 @@ type Events = {
11
11
  onUserJoined?: (p: Participant) => void;
12
12
  /** Fired when a remote participant permanently joins the meeting. */
13
13
  onParticipantJoined?: (p: Participant) => void;
14
+ onParticipantPresence?: (participantId: string, presence: string) => void;
14
15
  onEntryRequested?: (req: EntryRequest) => void;
15
16
  onEntryResponded?: (payload: {
16
17
  participantId: string;
@@ -285,6 +286,12 @@ declare class MeetingState {
285
286
  clearRecording(): void;
286
287
  setNetworkQuality(quality: NetworkQuality | null): void;
287
288
  addParticipant(p: Participant): boolean;
289
+ /**
290
+ * Reconcile a participant received from a room snapshot without emitting a
291
+ * lifecycle/join event. Snapshot data is authoritative for current room
292
+ * membership, including after a reconnect/resume.
293
+ */
294
+ upsertParticipantSnapshot(p: Participant): void;
288
295
  removeParticipant(id: string): void;
289
296
  updateParticipantMedia(id: string, patch: Partial<NonNullable<Participant["media"]>>): void;
290
297
  updateLocalParticipant(patch: LocalParticipantPatch): void;
@@ -468,6 +475,7 @@ type MeetingContextValue = {
468
475
  onNetworkQuality: (cb: (quality: NetworkQuality) => void) => () => void;
469
476
  onChatMessage: (cb: (message: ChatMessage) => void) => () => void;
470
477
  onParticipantJoined: (cb: (participant: Participant) => void) => () => void;
478
+ onParticipantPresence: (cb: (participantId: string, presence: string) => void) => () => void;
471
479
  onParticipantLeft: (cb: (participant: Participant) => void) => () => void;
472
480
  };
473
481
  declare const MeetingProvider: ({ config, children, }: {
@@ -564,6 +572,7 @@ declare const useMeeting: (handlers?: {
564
572
  onNetworkQuality: (cb: (quality: NetworkQuality) => void) => () => void;
565
573
  onChatMessage: (cb: (message: ChatMessage) => void) => () => void;
566
574
  onParticipantJoined: (cb: (participant: Participant) => void) => () => void;
575
+ onParticipantPresence: (cb: (participantId: string, presence: string) => void) => () => void;
567
576
  onParticipantLeft: (cb: (participant: Participant) => void) => () => void;
568
577
  };
569
578
 
package/dist/index.js CHANGED
@@ -279,6 +279,36 @@ var MeetingState = class {
279
279
  this.notify("participants");
280
280
  return true;
281
281
  }
282
+ /**
283
+ * Reconcile a participant received from a room snapshot without emitting a
284
+ * lifecycle/join event. Snapshot data is authoritative for current room
285
+ * membership, including after a reconnect/resume.
286
+ */
287
+ upsertParticipantSnapshot(p) {
288
+ if (!p?.id) return;
289
+ const current = this.participants.get(p.id);
290
+ const updated = {
291
+ ...current ?? {},
292
+ ...p,
293
+ media: {
294
+ stream: current?.media?.stream ?? null,
295
+ screenStream: current?.media?.screenStream,
296
+ cameraTrack: current?.media?.cameraTrack,
297
+ screenTrack: current?.media?.screenTrack,
298
+ audioTrack: current?.media?.audioTrack,
299
+ micEnabled: current?.media?.micEnabled ?? !(p.media?.micEnabled === false),
300
+ camEnabled: current?.media?.camEnabled ?? !(p.media?.camEnabled === false),
301
+ isScreenSharing: current?.media?.isScreenSharing ?? false,
302
+ ...current?.media,
303
+ ...p.media
304
+ }
305
+ };
306
+ const next = new Map(this.participants);
307
+ next.set(p.id, updated);
308
+ this.participants = next;
309
+ this.notify(`participant:${p.id}`);
310
+ this.notify("participants");
311
+ }
282
312
  removeParticipant(id) {
283
313
  const next = new Map(this.participants);
284
314
  next.delete(id);
@@ -850,6 +880,22 @@ var SFUClient = class {
850
880
  const participantId = payload.user_id || payload.participant_id;
851
881
  this.pendingJoinRequestId = requestId;
852
882
  this.onJoinApproved(requestId, participantId);
883
+ if (this.ws?.readyState === WebSocket.OPEN) {
884
+ this.setState("joining");
885
+ this.send({
886
+ type: "join",
887
+ request_id: requestId,
888
+ payload: {
889
+ token: this.token,
890
+ room_code: this.room,
891
+ resume_token: this.resumeToken,
892
+ display_name: this.joinOptions.displayName,
893
+ avatar_url: this.joinOptions.avatarUrl,
894
+ audio_muted: this.desiredAudioMuted,
895
+ video_muted: this.desiredVideoMuted
896
+ }
897
+ });
898
+ }
853
899
  break;
854
900
  }
855
901
  case "join_rejected": {
@@ -1227,7 +1273,6 @@ var SFUClient = class {
1227
1273
  }
1228
1274
  for (const participant of this.participants.values()) {
1229
1275
  if (participant.participant_id !== this.currentParticipantId) {
1230
- this.onParticipantJoined(participant);
1231
1276
  this.onParticipantPresence(
1232
1277
  participant.participant_id,
1233
1278
  String(participant.presence || "connected")
@@ -2512,6 +2557,36 @@ var VideoSDKCore = class {
2512
2557
  },
2513
2558
  onRoomUpdate: (payload) => {
2514
2559
  const participants = payload?.participants || [];
2560
+ const snapshotParticipantIds = /* @__PURE__ */ new Set();
2561
+ for (const participant of participants) {
2562
+ const pid = participant?.participant_id;
2563
+ if (!pid || pid === this.myId) continue;
2564
+ snapshotParticipantIds.add(pid);
2565
+ const current = this.state.getParticipant(pid);
2566
+ const name = participant?.user_metadata?.name || participant?.display_name || current?.name || "Participant";
2567
+ this.state.upsertParticipantSnapshot({
2568
+ id: pid,
2569
+ name,
2570
+ isModerator: Boolean(participant?.permissions?.moderate),
2571
+ isHost: Boolean(
2572
+ participant?.is_host ?? participant?.isHost ?? participant?.permissions?.host
2573
+ ),
2574
+ handRaised: Boolean(participant?.hand_raised),
2575
+ permissions: participant?.permissions,
2576
+ connectionState: participant?.presence === "reconnecting" ? "reconnecting" : participant?.presence === "disconnected" ? "disconnected" : "connected",
2577
+ media: {
2578
+ ...current?.media || {},
2579
+ micEnabled: !Boolean(participant?.audio_muted),
2580
+ camEnabled: !Boolean(participant?.video_muted),
2581
+ isScreenSharing: Boolean(participant?.screen_sharing)
2582
+ }
2583
+ });
2584
+ }
2585
+ for (const [pid] of this.state.participants) {
2586
+ if (pid === this.myId || snapshotParticipantIds.has(pid)) continue;
2587
+ this.cleanupRemoteParticipant(pid);
2588
+ this.state.removeParticipant(pid);
2589
+ }
2515
2590
  const local = participants.find(
2516
2591
  (p) => p?.participant_id === this.myId
2517
2592
  );
@@ -3325,6 +3400,9 @@ var MeetingProvider = ({
3325
3400
  const participantJoinedListeners = (0, import_react2.useRef)(
3326
3401
  /* @__PURE__ */ new Set()
3327
3402
  );
3403
+ const participantPresenceListeners = (0, import_react2.useRef)(
3404
+ /* @__PURE__ */ new Set()
3405
+ );
3328
3406
  const participantLeftListeners = (0, import_react2.useRef)(
3329
3407
  /* @__PURE__ */ new Set()
3330
3408
  );
@@ -3413,7 +3491,9 @@ var MeetingProvider = ({
3413
3491
  pubSubListeners.current.get("REACTION")?.forEach((fn) => fn(message));
3414
3492
  },
3415
3493
  onHandRaised: (participantId, raised) => {
3416
- handRaisedListeners.current.forEach((fn) => fn(participantId, raised));
3494
+ handRaisedListeners.current.forEach(
3495
+ (fn) => fn(participantId, raised)
3496
+ );
3417
3497
  },
3418
3498
  onNetworkQuality: (quality) => {
3419
3499
  networkQualityListeners.current.forEach((fn) => fn(quality));
@@ -3426,6 +3506,11 @@ var MeetingProvider = ({
3426
3506
  onParticipantJoined: (participant) => {
3427
3507
  participantJoinedListeners.current.forEach((fn) => fn(participant));
3428
3508
  },
3509
+ onParticipantPresence: (participantId, presence) => {
3510
+ participantPresenceListeners.current.forEach(
3511
+ (fn) => fn(participantId, presence)
3512
+ );
3513
+ },
3429
3514
  onParticipantLeft: (participant) => {
3430
3515
  participantLeftListeners.current.forEach((fn) => fn(participant));
3431
3516
  }
@@ -3638,6 +3723,10 @@ var MeetingProvider = ({
3638
3723
  participantJoinedListeners.current.add(cb);
3639
3724
  return () => participantJoinedListeners.current.delete(cb);
3640
3725
  },
3726
+ onParticipantPresence: (cb) => {
3727
+ participantPresenceListeners.current.add(cb);
3728
+ return () => participantPresenceListeners.current.delete(cb);
3729
+ },
3641
3730
  onChatMessage: (cb) => {
3642
3731
  chatMessageListeners.current.add(cb);
3643
3732
  return () => chatMessageListeners.current.delete(cb);