@defcomm/meetingsdk 0.4.4 → 0.4.5

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
@@ -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;
@@ -105,11 +125,6 @@ type MeetingConfig = {
105
125
  videoMuted?: boolean;
106
126
  token?: string;
107
127
  };
108
- type PubSubTopic = "SECURE_CHAT" | "REACTION";
109
- type PubSubHandle<T = unknown> = {
110
- messages: PubSubMessage<T>[];
111
- publish: (data: T) => void;
112
- };
113
128
  type RecordingInfo = {
114
129
  recording_id: string;
115
130
  started_at?: string;
@@ -253,6 +268,15 @@ declare class VideoSDKCore {
253
268
  }>;
254
269
  sendChatMessage(payload: ChatInput): void;
255
270
  sendReaction(reaction: string): void;
271
+ /**
272
+ * Generic PubSub publishing entry point.
273
+ *
274
+ * The public SDK exposes one PubSub API for all topics. The current SFU
275
+ * protocol still has dedicated wire messages for chat and reactions, so
276
+ * this method is the compatibility bridge. The application does not need
277
+ * to know about those wire-level message types.
278
+ */
279
+ publishPubSub<T extends PubSubTopic>(topic: T, data: PubSubTopicConfig[T]["publish"]): void;
256
280
  private cleanupRemoteParticipant;
257
281
  disconnect(): Promise<void>;
258
282
  private performDisconnect;
@@ -304,8 +328,8 @@ type MeetingContextValue = {
304
328
  presenterId: string | null;
305
329
  activeSpeakerIds: string[];
306
330
  recording: RecordingInfo | null;
307
- usePubSub: <T = unknown>(topic: PubSubTopic) => PubSubHandle<T>;
308
- onPubSubMessage: <T = unknown>(topic: PubSubTopic, cb: (message: PubSubMessage<T>) => void) => () => void;
331
+ usePubSub: <T extends PubSubTopic>(topic: T) => PubSubHandleForTopic<T>;
332
+ onPubSubMessage: <T extends PubSubTopic>(topic: T, cb: (message: PubSubMessage<PubSubTopicConfig[T]["message"]>) => void) => () => void;
309
333
  approveJoinRequest: (requestId: string) => void;
310
334
  rejectJoinRequest: (requestId: string) => void;
311
335
  startRecording: () => Promise<void>;
@@ -367,8 +391,8 @@ declare const useMeeting: (handlers?: {
367
391
  presenterId: string | null;
368
392
  activeSpeakerIds: string[];
369
393
  recording: RecordingInfo | null;
370
- usePubSub: <T = unknown>(topic: PubSubTopic) => PubSubHandle<T>;
371
- onPubSubMessage: <T = unknown>(topic: PubSubTopic, cb: (message: PubSubMessage<T>) => void) => () => void;
394
+ usePubSub: <T extends PubSubTopic>(topic: T) => PubSubHandleForTopic<T>;
395
+ onPubSubMessage: <T extends PubSubTopic>(topic: T, cb: (message: PubSubMessage<PubSubTopicConfig[T]["message"]>) => void) => () => void;
372
396
  approveJoinRequest: (requestId: string) => void;
373
397
  rejectJoinRequest: (requestId: string) => void;
374
398
  startRecording: () => Promise<void>;
@@ -463,8 +487,8 @@ declare class ActiveSpeakerDetector {
463
487
  destroy(): Promise<void>;
464
488
  }
465
489
 
466
- declare function usePubSub<T = unknown>(topic: PubSubTopic, options?: {
467
- onMessageReceived?: (message: PubSubMessage<T>) => void;
468
- }): PubSubHandle<T>;
490
+ declare function usePubSub<T extends PubSubTopic>(topic: T, options?: {
491
+ onMessageReceived?: (message: PubSubMessage<PubSubTopicConfig[T]["message"]>) => void;
492
+ }): PubSubHandleForTopic<T>;
469
493
 
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 };
494
+ 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;
@@ -105,11 +125,6 @@ type MeetingConfig = {
105
125
  videoMuted?: boolean;
106
126
  token?: string;
107
127
  };
108
- type PubSubTopic = "SECURE_CHAT" | "REACTION";
109
- type PubSubHandle<T = unknown> = {
110
- messages: PubSubMessage<T>[];
111
- publish: (data: T) => void;
112
- };
113
128
  type RecordingInfo = {
114
129
  recording_id: string;
115
130
  started_at?: string;
@@ -253,6 +268,15 @@ declare class VideoSDKCore {
253
268
  }>;
254
269
  sendChatMessage(payload: ChatInput): void;
255
270
  sendReaction(reaction: string): void;
271
+ /**
272
+ * Generic PubSub publishing entry point.
273
+ *
274
+ * The public SDK exposes one PubSub API for all topics. The current SFU
275
+ * protocol still has dedicated wire messages for chat and reactions, so
276
+ * this method is the compatibility bridge. The application does not need
277
+ * to know about those wire-level message types.
278
+ */
279
+ publishPubSub<T extends PubSubTopic>(topic: T, data: PubSubTopicConfig[T]["publish"]): void;
256
280
  private cleanupRemoteParticipant;
257
281
  disconnect(): Promise<void>;
258
282
  private performDisconnect;
@@ -304,8 +328,8 @@ type MeetingContextValue = {
304
328
  presenterId: string | null;
305
329
  activeSpeakerIds: string[];
306
330
  recording: RecordingInfo | null;
307
- usePubSub: <T = unknown>(topic: PubSubTopic) => PubSubHandle<T>;
308
- onPubSubMessage: <T = unknown>(topic: PubSubTopic, cb: (message: PubSubMessage<T>) => void) => () => void;
331
+ usePubSub: <T extends PubSubTopic>(topic: T) => PubSubHandleForTopic<T>;
332
+ onPubSubMessage: <T extends PubSubTopic>(topic: T, cb: (message: PubSubMessage<PubSubTopicConfig[T]["message"]>) => void) => () => void;
309
333
  approveJoinRequest: (requestId: string) => void;
310
334
  rejectJoinRequest: (requestId: string) => void;
311
335
  startRecording: () => Promise<void>;
@@ -367,8 +391,8 @@ declare const useMeeting: (handlers?: {
367
391
  presenterId: string | null;
368
392
  activeSpeakerIds: string[];
369
393
  recording: RecordingInfo | null;
370
- usePubSub: <T = unknown>(topic: PubSubTopic) => PubSubHandle<T>;
371
- onPubSubMessage: <T = unknown>(topic: PubSubTopic, cb: (message: PubSubMessage<T>) => void) => () => void;
394
+ usePubSub: <T extends PubSubTopic>(topic: T) => PubSubHandleForTopic<T>;
395
+ onPubSubMessage: <T extends PubSubTopic>(topic: T, cb: (message: PubSubMessage<PubSubTopicConfig[T]["message"]>) => void) => () => void;
372
396
  approveJoinRequest: (requestId: string) => void;
373
397
  rejectJoinRequest: (requestId: string) => void;
374
398
  startRecording: () => Promise<void>;
@@ -463,8 +487,8 @@ declare class ActiveSpeakerDetector {
463
487
  destroy(): Promise<void>;
464
488
  }
465
489
 
466
- declare function usePubSub<T = unknown>(topic: PubSubTopic, options?: {
467
- onMessageReceived?: (message: PubSubMessage<T>) => void;
468
- }): PubSubHandle<T>;
490
+ declare function usePubSub<T extends PubSubTopic>(topic: T, options?: {
491
+ onMessageReceived?: (message: PubSubMessage<PubSubTopicConfig[T]["message"]>) => void;
492
+ }): PubSubHandleForTopic<T>;
469
493
 
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 };
494
+ 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
@@ -2739,6 +2739,28 @@ var VideoSDKCore = class {
2739
2739
  }
2740
2740
  this.sfuClient.sendReaction(reaction);
2741
2741
  }
2742
+ /**
2743
+ * Generic PubSub publishing entry point.
2744
+ *
2745
+ * The public SDK exposes one PubSub API for all topics. The current SFU
2746
+ * protocol still has dedicated wire messages for chat and reactions, so
2747
+ * this method is the compatibility bridge. The application does not need
2748
+ * to know about those wire-level message types.
2749
+ */
2750
+ publishPubSub(topic, data) {
2751
+ switch (topic) {
2752
+ case "SECURE_CHAT":
2753
+ this.sendChatMessage(data);
2754
+ return;
2755
+ case "REACTION":
2756
+ this.sendReaction(data.emoji);
2757
+ return;
2758
+ default: {
2759
+ const exhaustive = topic;
2760
+ throw new Error(`Unsupported PubSub topic: ${exhaustive}`);
2761
+ }
2762
+ }
2763
+ }
2742
2764
  // CLEANUP
2743
2765
  cleanupRemoteParticipant(participantId) {
2744
2766
  this.activeSpeakerDetector.removeParticipant(participantId);
@@ -2829,6 +2851,7 @@ var MeetingProvider = ({
2829
2851
  const pubSubListeners = (0, import_react2.useRef)(
2830
2852
  /* @__PURE__ */ new Map()
2831
2853
  );
2854
+ const [reactionPubSubMessages, setReactionPubSubMessages] = (0, import_react2.useState)([]);
2832
2855
  const activeSpeakerListeners = (0, import_react2.useRef)(
2833
2856
  /* @__PURE__ */ new Set()
2834
2857
  );
@@ -2862,21 +2885,43 @@ var MeetingProvider = ({
2862
2885
  onRecordingStopped: (recording2) => {
2863
2886
  recordingStoppedListeners.current.forEach((fn) => fn(recording2));
2864
2887
  },
2888
+ onChatMessage: (message) => {
2889
+ const msg = {
2890
+ id: message.id,
2891
+ text: message.text,
2892
+ sender_id: message.sender_id,
2893
+ sender_name: message.sender_name,
2894
+ timestamp: Number(message.timestamp),
2895
+ reply_to: message.reply_to ?? null,
2896
+ target: message.target ?? null
2897
+ };
2898
+ const pubSubMessage = {
2899
+ id: msg.id,
2900
+ topic: "SECURE_CHAT",
2901
+ sender_id: msg.sender_id,
2902
+ sender_name: msg.sender_name,
2903
+ timestamp: msg.timestamp,
2904
+ data: msg
2905
+ };
2906
+ pubSubListeners.current.get("SECURE_CHAT")?.forEach((fn) => fn(pubSubMessage));
2907
+ },
2865
2908
  onReaction: (reaction) => {
2866
2909
  reactionListeners.current.forEach((fn) => fn(reaction));
2867
- const listeners = pubSubListeners.current.get("REACTION");
2868
- if (!listeners) return;
2910
+ const timestamp = typeof reaction.timestamp === "number" ? reaction.timestamp : Date.parse(reaction.timestamp);
2869
2911
  const message = {
2870
2912
  id: reaction.id,
2871
2913
  topic: "REACTION",
2872
2914
  sender_id: reaction.participant_id,
2873
2915
  sender_name: reaction.sender_name,
2874
- timestamp: typeof reaction.timestamp === "number" ? reaction.timestamp : Date.parse(reaction.timestamp),
2916
+ timestamp,
2875
2917
  data: {
2876
2918
  emoji: reaction.emoji
2877
2919
  }
2878
2920
  };
2879
- listeners.forEach((fn) => fn(message));
2921
+ setReactionPubSubMessages(
2922
+ (previous) => [...previous, message].slice(-50)
2923
+ );
2924
+ pubSubListeners.current.get("REACTION")?.forEach((fn) => fn(message));
2880
2925
  },
2881
2926
  onConnectionStateChanged: (state) => {
2882
2927
  connectionStateListeners.current.forEach(
@@ -2939,32 +2984,32 @@ var MeetingProvider = ({
2939
2984
  activeSpeakerIds,
2940
2985
  recording,
2941
2986
  usePubSub: (topic) => {
2987
+ if (topic === "SECURE_CHAT") {
2988
+ const chatMessages = messages.map((message) => ({
2989
+ id: message.id,
2990
+ topic: "SECURE_CHAT",
2991
+ sender_id: message.sender_id,
2992
+ sender_name: message.sender_name,
2993
+ timestamp: message.timestamp,
2994
+ data: message
2995
+ }));
2996
+ return {
2997
+ messages: chatMessages,
2998
+ publish: ((data) => {
2999
+ sdk.publishPubSub("SECURE_CHAT", data);
3000
+ })
3001
+ };
3002
+ }
2942
3003
  if (topic === "REACTION") {
2943
3004
  return {
2944
- messages: [],
2945
- publish: (data) => {
2946
- const reaction = data;
2947
- if (!reaction?.emoji) {
3005
+ messages: reactionPubSubMessages,
3006
+ publish: ((data) => {
3007
+ if (!data?.emoji) {
2948
3008
  console.warn("[PubSub] REACTION requires an emoji");
2949
3009
  return;
2950
3010
  }
2951
- sdk.sendReaction(reaction.emoji);
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
- }
3011
+ sdk.publishPubSub("REACTION", data);
3012
+ })
2968
3013
  };
2969
3014
  }
2970
3015
  throw new Error(`Unsupported PubSub topic: "${topic}"`);
@@ -3049,7 +3094,8 @@ var MeetingProvider = ({
3049
3094
  messages,
3050
3095
  presenterId,
3051
3096
  recording,
3052
- activeSpeakerIds
3097
+ activeSpeakerIds,
3098
+ reactionPubSubMessages
3053
3099
  ]);
3054
3100
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MeetingContext.Provider, { value, children });
3055
3101
  };
@@ -3286,7 +3332,10 @@ function usePubSub(topic, options) {
3286
3332
  const ctx = useMeetingContext();
3287
3333
  (0, import_react8.useEffect)(() => {
3288
3334
  if (!options?.onMessageReceived) return;
3289
- return ctx.onPubSubMessage(topic, options.onMessageReceived);
3335
+ return ctx.onPubSubMessage(
3336
+ topic,
3337
+ options.onMessageReceived
3338
+ );
3290
3339
  }, [ctx, topic, options?.onMessageReceived]);
3291
3340
  return ctx.usePubSub(topic);
3292
3341
  }