@defcomm/meetingsdk 0.4.3 → 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.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  // src/react/useLocalParticipant.tsx
2
- import { useCallback, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
2
+ import { useCallback, useEffect as useEffect2, useRef as useRef2, useState as useState3 } from "react";
3
3
 
4
4
  // src/react/MeetingProvider.tsx
5
- import { createContext, useContext, useMemo, useRef } from "react";
5
+ import { createContext, useContext, useMemo, useRef, useState as useState2 } from "react";
6
6
 
7
7
  // src/config/ws.ts
8
8
  var SDK_CONFIG = {
@@ -2703,6 +2703,28 @@ var VideoSDKCore = class {
2703
2703
  }
2704
2704
  this.sfuClient.sendReaction(reaction);
2705
2705
  }
2706
+ /**
2707
+ * Generic PubSub publishing entry point.
2708
+ *
2709
+ * The public SDK exposes one PubSub API for all topics. The current SFU
2710
+ * protocol still has dedicated wire messages for chat and reactions, so
2711
+ * this method is the compatibility bridge. The application does not need
2712
+ * to know about those wire-level message types.
2713
+ */
2714
+ publishPubSub(topic, data) {
2715
+ switch (topic) {
2716
+ case "SECURE_CHAT":
2717
+ this.sendChatMessage(data);
2718
+ return;
2719
+ case "REACTION":
2720
+ this.sendReaction(data.emoji);
2721
+ return;
2722
+ default: {
2723
+ const exhaustive = topic;
2724
+ throw new Error(`Unsupported PubSub topic: ${exhaustive}`);
2725
+ }
2726
+ }
2727
+ }
2706
2728
  // CLEANUP
2707
2729
  cleanupRemoteParticipant(participantId) {
2708
2730
  this.activeSpeakerDetector.removeParticipant(participantId);
@@ -2790,6 +2812,10 @@ var MeetingProvider = ({
2790
2812
  const recordingStartedListeners = useRef(/* @__PURE__ */ new Set());
2791
2813
  const recordingStoppedListeners = useRef(/* @__PURE__ */ new Set());
2792
2814
  const reactionListeners = useRef(/* @__PURE__ */ new Set());
2815
+ const pubSubListeners = useRef(
2816
+ /* @__PURE__ */ new Map()
2817
+ );
2818
+ const [reactionPubSubMessages, setReactionPubSubMessages] = useState2([]);
2793
2819
  const activeSpeakerListeners = useRef(
2794
2820
  /* @__PURE__ */ new Set()
2795
2821
  );
@@ -2823,8 +2849,43 @@ var MeetingProvider = ({
2823
2849
  onRecordingStopped: (recording2) => {
2824
2850
  recordingStoppedListeners.current.forEach((fn) => fn(recording2));
2825
2851
  },
2852
+ onChatMessage: (message) => {
2853
+ const msg = {
2854
+ id: message.id,
2855
+ text: message.text,
2856
+ sender_id: message.sender_id,
2857
+ sender_name: message.sender_name,
2858
+ timestamp: Number(message.timestamp),
2859
+ reply_to: message.reply_to ?? null,
2860
+ target: message.target ?? null
2861
+ };
2862
+ const pubSubMessage = {
2863
+ id: msg.id,
2864
+ topic: "SECURE_CHAT",
2865
+ sender_id: msg.sender_id,
2866
+ sender_name: msg.sender_name,
2867
+ timestamp: msg.timestamp,
2868
+ data: msg
2869
+ };
2870
+ pubSubListeners.current.get("SECURE_CHAT")?.forEach((fn) => fn(pubSubMessage));
2871
+ },
2826
2872
  onReaction: (reaction) => {
2827
2873
  reactionListeners.current.forEach((fn) => fn(reaction));
2874
+ const timestamp = typeof reaction.timestamp === "number" ? reaction.timestamp : Date.parse(reaction.timestamp);
2875
+ const message = {
2876
+ id: reaction.id,
2877
+ topic: "REACTION",
2878
+ sender_id: reaction.participant_id,
2879
+ sender_name: reaction.sender_name,
2880
+ timestamp,
2881
+ data: {
2882
+ emoji: reaction.emoji
2883
+ }
2884
+ };
2885
+ setReactionPubSubMessages(
2886
+ (previous) => [...previous, message].slice(-50)
2887
+ );
2888
+ pubSubListeners.current.get("REACTION")?.forEach((fn) => fn(message));
2828
2889
  },
2829
2890
  onConnectionStateChanged: (state) => {
2830
2891
  connectionStateListeners.current.forEach(
@@ -2887,12 +2948,48 @@ var MeetingProvider = ({
2887
2948
  activeSpeakerIds,
2888
2949
  recording,
2889
2950
  usePubSub: (topic) => {
2890
- if (topic !== "SECURE_CHAT") {
2891
- throw new Error(`Unsupported PubSub argument: "${topic}"`);
2951
+ if (topic === "SECURE_CHAT") {
2952
+ const chatMessages = messages.map((message) => ({
2953
+ id: message.id,
2954
+ topic: "SECURE_CHAT",
2955
+ sender_id: message.sender_id,
2956
+ sender_name: message.sender_name,
2957
+ timestamp: message.timestamp,
2958
+ data: message
2959
+ }));
2960
+ return {
2961
+ messages: chatMessages,
2962
+ publish: ((data) => {
2963
+ sdk.publishPubSub("SECURE_CHAT", data);
2964
+ })
2965
+ };
2892
2966
  }
2893
- return {
2894
- messages: sdk.state.getChatMessages(),
2895
- publish: sdk.sendChatMessage.bind(sdk)
2967
+ if (topic === "REACTION") {
2968
+ return {
2969
+ messages: reactionPubSubMessages,
2970
+ publish: ((data) => {
2971
+ if (!data?.emoji) {
2972
+ console.warn("[PubSub] REACTION requires an emoji");
2973
+ return;
2974
+ }
2975
+ sdk.publishPubSub("REACTION", data);
2976
+ })
2977
+ };
2978
+ }
2979
+ throw new Error(`Unsupported PubSub topic: "${topic}"`);
2980
+ },
2981
+ onPubSubMessage: (topic, cb) => {
2982
+ let listeners = pubSubListeners.current.get(topic);
2983
+ if (!listeners) {
2984
+ listeners = /* @__PURE__ */ new Set();
2985
+ pubSubListeners.current.set(topic, listeners);
2986
+ }
2987
+ listeners.add(cb);
2988
+ return () => {
2989
+ listeners?.delete(cb);
2990
+ if (listeners?.size === 0) {
2991
+ pubSubListeners.current.delete(topic);
2992
+ }
2896
2993
  };
2897
2994
  },
2898
2995
  approveJoinRequest: sdk.approveJoinRequest.bind(sdk),
@@ -2961,7 +3058,8 @@ var MeetingProvider = ({
2961
3058
  messages,
2962
3059
  presenterId,
2963
3060
  recording,
2964
- activeSpeakerIds
3061
+ activeSpeakerIds,
3062
+ reactionPubSubMessages
2965
3063
  ]);
2966
3064
  return /* @__PURE__ */ jsx(MeetingContext.Provider, { value, children });
2967
3065
  };
@@ -2975,7 +3073,7 @@ var useMeetingContext = () => {
2975
3073
  // src/react/useLocalParticipant.tsx
2976
3074
  var useLocalParticipant = () => {
2977
3075
  const { sdk } = useMeetingContext();
2978
- const [localParticipant, setLocalParticipant] = useState2(
3076
+ const [localParticipant, setLocalParticipant] = useState3(
2979
3077
  () => {
2980
3078
  const current = sdk.state.localParticipant;
2981
3079
  return current && current.id ? current : null;
@@ -3064,10 +3162,10 @@ var useMeeting = (handlers) => {
3064
3162
  };
3065
3163
 
3066
3164
  // src/react/useParticipants.ts
3067
- import { useEffect as useEffect4, useState as useState3 } from "react";
3165
+ import { useEffect as useEffect4, useState as useState4 } from "react";
3068
3166
  var useParticipants = () => {
3069
3167
  const { sdk } = useMeetingContext();
3070
- const [participants, setParticipants] = useState3(
3168
+ const [participants, setParticipants] = useState4(
3071
3169
  () => sdk.state.getParticipants()
3072
3170
  );
3073
3171
  useEffect4(() => {
@@ -3082,12 +3180,12 @@ var useParticipants = () => {
3082
3180
  };
3083
3181
 
3084
3182
  // src/react/useRemoteMedia.ts
3085
- import { useEffect as useEffect5, useRef as useRef3, useState as useState4 } from "react";
3183
+ import { useEffect as useEffect5, useRef as useRef3, useState as useState5 } from "react";
3086
3184
  var useRemoteMedia = (participantId) => {
3087
3185
  const { sdk } = useMeetingContext();
3088
3186
  const videoRef = useRef3(null);
3089
3187
  const audioRef = useRef3(null);
3090
- const [participant, setParticipant] = useState4(
3188
+ const [participant, setParticipant] = useState5(
3091
3189
  () => sdk.state.getParticipant(participantId) || null
3092
3190
  );
3093
3191
  useEffect5(() => {
@@ -3123,12 +3221,12 @@ var useRemoteMedia = (participantId) => {
3123
3221
  };
3124
3222
 
3125
3223
  // src/react/useMeetingPreview.ts
3126
- import { useEffect as useEffect6, useState as useState5 } from "react";
3224
+ import { useEffect as useEffect6, useState as useState6 } from "react";
3127
3225
  function useMeetingPreview(roomId, participantId) {
3128
- const [room, setRoom] = useState5(null);
3129
- const [error, setError] = useState5(null);
3130
- const [isConnected, setIsConnected] = useState5(false);
3131
- const [isLoading, setIsLoading] = useState5(true);
3226
+ const [room, setRoom] = useState6(null);
3227
+ const [error, setError] = useState6(null);
3228
+ const [isConnected, setIsConnected] = useState6(false);
3229
+ const [isLoading, setIsLoading] = useState6(true);
3132
3230
  useEffect6(() => {
3133
3231
  if (!roomId) {
3134
3232
  setIsLoading(false);
@@ -3191,6 +3289,20 @@ function useMeetingPreview(roomId, participantId) {
3191
3289
  error
3192
3290
  };
3193
3291
  }
3292
+
3293
+ // src/react/usePubSub.ts
3294
+ import { useEffect as useEffect7 } from "react";
3295
+ function usePubSub(topic, options) {
3296
+ const ctx = useMeetingContext();
3297
+ useEffect7(() => {
3298
+ if (!options?.onMessageReceived) return;
3299
+ return ctx.onPubSubMessage(
3300
+ topic,
3301
+ options.onMessageReceived
3302
+ );
3303
+ }, [ctx, topic, options?.onMessageReceived]);
3304
+ return ctx.usePubSub(topic);
3305
+ }
3194
3306
  export {
3195
3307
  ActiveSpeakerDetector,
3196
3308
  MeetingProvider,
@@ -3201,6 +3313,7 @@ export {
3201
3313
  useMeetingContext,
3202
3314
  useMeetingPreview,
3203
3315
  useParticipants,
3316
+ usePubSub,
3204
3317
  useRemoteMedia
3205
3318
  };
3206
3319
  //# sourceMappingURL=index.mjs.map