mediasfu-shared 1.1.0 → 1.2.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.
Files changed (137) hide show
  1. package/README.md +17 -0
  2. package/dist/ProducerClient/producerClientEmits/createDeviceClient.d.ts +1 -1
  3. package/dist/ProducerClient/producerClientEmits/createDeviceClient.d.ts.map +1 -1
  4. package/dist/ProducerClient/producerClientEmits/updateRoomParametersClient.d.ts +1 -1
  5. package/dist/ProducerClient/producerClientEmits/updateRoomParametersClient.d.ts.map +1 -1
  6. package/dist/consumers/connectIps.d.ts +1 -1
  7. package/dist/consumers/connectIps.d.ts.map +1 -1
  8. package/dist/consumers/connectRecvTransport.d.ts +1 -1
  9. package/dist/consumers/connectRecvTransport.d.ts.map +1 -1
  10. package/dist/consumers/connectSendTransport.d.ts +1 -1
  11. package/dist/consumers/connectSendTransport.d.ts.map +1 -1
  12. package/dist/consumers/connectSendTransportAudio.d.ts +1 -1
  13. package/dist/consumers/connectSendTransportAudio.d.ts.map +1 -1
  14. package/dist/consumers/connectSendTransportScreen.d.ts +1 -1
  15. package/dist/consumers/connectSendTransportScreen.d.ts.map +1 -1
  16. package/dist/consumers/connectSendTransportVideo.d.ts +1 -1
  17. package/dist/consumers/connectSendTransportVideo.d.ts.map +1 -1
  18. package/dist/consumers/createSendTransport.d.ts +1 -1
  19. package/dist/consumers/createSendTransport.d.ts.map +1 -1
  20. package/dist/consumers/disconnectSendTransportAudio.d.ts +1 -1
  21. package/dist/consumers/disconnectSendTransportAudio.d.ts.map +1 -1
  22. package/dist/consumers/disconnectSendTransportScreen.d.ts +1 -1
  23. package/dist/consumers/disconnectSendTransportScreen.d.ts.map +1 -1
  24. package/dist/consumers/disconnectSendTransportVideo.d.ts +1 -1
  25. package/dist/consumers/disconnectSendTransportVideo.d.ts.map +1 -1
  26. package/dist/consumers/index.cjs +80 -0
  27. package/dist/consumers/index.cjs.map +1 -0
  28. package/dist/consumers/index.d.ts +62 -0
  29. package/dist/consumers/index.d.ts.map +1 -0
  30. package/dist/consumers/index.js +80 -0
  31. package/dist/consumers/index.js.map +1 -0
  32. package/dist/consumers/resumeSendTransportAudio.d.ts +1 -1
  33. package/dist/consumers/resumeSendTransportAudio.d.ts.map +1 -1
  34. package/dist/consumers/signalNewConsumerTransport.d.ts +1 -1
  35. package/dist/consumers/signalNewConsumerTransport.d.ts.map +1 -1
  36. package/dist/consumers/socketReceiveMethods/joinConsumeRoom.d.ts +1 -1
  37. package/dist/consumers/socketReceiveMethods/joinConsumeRoom.d.ts.map +1 -1
  38. package/dist/consumers/socketReceiveMethods/newPipeProducer.d.ts +1 -1
  39. package/dist/consumers/socketReceiveMethods/newPipeProducer.d.ts.map +1 -1
  40. package/dist/consumers/streamSuccessAudio.d.ts +1 -1
  41. package/dist/consumers/streamSuccessAudio.d.ts.map +1 -1
  42. package/dist/consumers/streamSuccessAudioSwitch.d.ts +1 -1
  43. package/dist/consumers/streamSuccessAudioSwitch.d.ts.map +1 -1
  44. package/dist/consumers/streamSuccessVideo.d.ts +1 -1
  45. package/dist/consumers/streamSuccessVideo.d.ts.map +1 -1
  46. package/dist/getParticipantMedia-B0JS6d2b.js +3555 -0
  47. package/dist/getParticipantMedia-B0JS6d2b.js.map +1 -0
  48. package/dist/getParticipantMedia-CdcYqcbD.cjs +3554 -0
  49. package/dist/getParticipantMedia-CdcYqcbD.cjs.map +1 -0
  50. package/dist/index.cjs +299 -252
  51. package/dist/index.cjs.map +1 -1
  52. package/dist/index.d.ts +1 -0
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +1994 -1947
  55. package/dist/index.js.map +1 -1
  56. package/dist/index.native.cjs +230 -224
  57. package/dist/index.native.cjs.map +1 -1
  58. package/dist/index.native.js +349 -343
  59. package/dist/index.native.js.map +1 -1
  60. package/dist/joinLocalRoom-BdM1msQt.cjs +673 -0
  61. package/dist/joinLocalRoom-BdM1msQt.cjs.map +1 -0
  62. package/dist/joinLocalRoom-CvteNe4R.js +657 -0
  63. package/dist/joinLocalRoom-CvteNe4R.js.map +1 -0
  64. package/dist/joinRoomOnMediaSFU-CC8RVJgr.cjs +1222 -0
  65. package/dist/joinRoomOnMediaSFU-CC8RVJgr.cjs.map +1 -0
  66. package/dist/joinRoomOnMediaSFU-y6vJ1OBo.js +1223 -0
  67. package/dist/joinRoomOnMediaSFU-y6vJ1OBo.js.map +1 -0
  68. package/dist/methods/index.cjs +3975 -0
  69. package/dist/methods/index.cjs.map +1 -0
  70. package/dist/methods/index.js +3976 -0
  71. package/dist/methods/index.js.map +1 -0
  72. package/dist/methods/socketReceive/getDomains.d.ts +1 -1
  73. package/dist/methods/socketReceive/getDomains.d.ts.map +1 -1
  74. package/dist/methods/utils/headless/virtualBackground.d.ts +2 -2
  75. package/dist/methods/utils/headless/virtualBackground.d.ts.map +1 -1
  76. package/dist/methods/utils/virtualBackgroundCompositor.d.ts +21 -0
  77. package/dist/methods/utils/virtualBackgroundCompositor.d.ts.map +1 -0
  78. package/dist/methods/whiteboard/captureCanvasStream.d.ts +1 -1
  79. package/dist/methods/whiteboard/captureCanvasStream.d.ts.map +1 -1
  80. package/dist/producers/producerEmits/joinConRoom.d.ts +1 -1
  81. package/dist/producers/producerEmits/joinConRoom.d.ts.map +1 -1
  82. package/dist/producers/producerEmits/joinRoom.d.ts +1 -1
  83. package/dist/producers/producerEmits/joinRoom.d.ts.map +1 -1
  84. package/dist/translationConsumerSwitch-C20MfNNq.cjs +509 -0
  85. package/dist/translationConsumerSwitch-C20MfNNq.cjs.map +1 -0
  86. package/dist/translationConsumerSwitch-zKuS5wgH.js +510 -0
  87. package/dist/translationConsumerSwitch-zKuS5wgH.js.map +1 -0
  88. package/dist/types/index.cjs +85 -0
  89. package/dist/types/index.cjs.map +1 -0
  90. package/dist/types/index.d.ts +2 -0
  91. package/dist/types/index.d.ts.map +1 -0
  92. package/dist/types/index.js +85 -0
  93. package/dist/types/index.js.map +1 -0
  94. package/dist/types/shared-base-types.d.ts +1 -1
  95. package/dist/types/shared-base-types.d.ts.map +1 -1
  96. package/dist/updateParticipantAudioDecibels-DLd8Y-Fh.js +5392 -0
  97. package/dist/updateParticipantAudioDecibels-DLd8Y-Fh.js.map +1 -0
  98. package/dist/updateParticipantAudioDecibels-DPmHiy3K.cjs +5391 -0
  99. package/dist/updateParticipantAudioDecibels-DPmHiy3K.cjs.map +1 -0
  100. package/dist/validateAlphanumeric-DKn5BsUP.cjs +15 -0
  101. package/dist/validateAlphanumeric-DKn5BsUP.cjs.map +1 -0
  102. package/dist/validateAlphanumeric-Dk1JB80W.js +16 -0
  103. package/dist/validateAlphanumeric-Dk1JB80W.js.map +1 -0
  104. package/package.json +1 -1
  105. package/src/ProducerClient/producerClientEmits/createDeviceClient.ts +1 -2
  106. package/src/ProducerClient/producerClientEmits/updateRoomParametersClient.ts +1 -1
  107. package/src/consumers/connectIps.ts +1 -1
  108. package/src/consumers/connectRecvTransport.ts +1 -1
  109. package/src/consumers/connectSendTransport.ts +1 -1
  110. package/src/consumers/connectSendTransportAudio.ts +1 -1
  111. package/src/consumers/connectSendTransportScreen.ts +1 -1
  112. package/src/consumers/connectSendTransportVideo.ts +1 -1
  113. package/src/consumers/createSendTransport.ts +1 -1
  114. package/src/consumers/disconnectSendTransportAudio.ts +1 -1
  115. package/src/consumers/disconnectSendTransportScreen.ts +1 -1
  116. package/src/consumers/disconnectSendTransportVideo.ts +1 -1
  117. package/src/consumers/index.ts +61 -0
  118. package/src/consumers/resumeSendTransportAudio.ts +1 -1
  119. package/src/consumers/signalNewConsumerTransport.ts +1 -2
  120. package/src/consumers/socketReceiveMethods/joinConsumeRoom.ts +1 -1
  121. package/src/consumers/socketReceiveMethods/newPipeProducer.ts +1 -1
  122. package/src/consumers/streamSuccessAudio.ts +1 -2
  123. package/src/consumers/streamSuccessAudioSwitch.ts +1 -2
  124. package/src/consumers/streamSuccessVideo.ts +1 -1
  125. package/src/index.ts +2 -0
  126. package/src/methods/socketReceive/getDomains.ts +1 -1
  127. package/src/methods/utils/headless/virtualBackground.ts +45 -30
  128. package/src/methods/utils/virtualBackgroundCompositor.ts +53 -0
  129. package/src/methods/whiteboard/captureCanvasStream.ts +2 -2
  130. package/src/producers/producerEmits/joinConRoom.ts +1 -1
  131. package/src/producers/producerEmits/joinRoom.ts +1 -1
  132. package/src/types/index.ts +1 -0
  133. package/src/types/shared-base-types.ts +2 -3
  134. package/dist/getParticipantMedia-D9ChmEqq.js +0 -15265
  135. package/dist/getParticipantMedia-D9ChmEqq.js.map +0 -1
  136. package/dist/getParticipantMedia-DWvIhPPY.cjs +0 -15281
  137. package/dist/getParticipantMedia-DWvIhPPY.cjs.map +0 -1
@@ -0,0 +1,3976 @@
1
+ import { a as checkLimitsAndMakeRequest, G as resolveMediaSFURoomApi, H as Cookies } from "../joinRoomOnMediaSFU-y6vJ1OBo.js";
2
+ import { Q, u, m, A, f, e, c, b, d, l, y, p, D, g, k, x, o, C, h, j, q, z, r, E, F, s, i, w, n, B, t, v } from "../joinRoomOnMediaSFU-y6vJ1OBo.js";
3
+ import { v as v2 } from "../validateAlphanumeric-Dk1JB80W.js";
4
+ const launchPanelists = ({
5
+ updateIsPanelistsModalVisible,
6
+ isPanelistsModalVisible
7
+ }) => {
8
+ updateIsPanelistsModalVisible(!isPanelistsModalVisible);
9
+ };
10
+ const updatePanelists = async ({
11
+ socket,
12
+ panelists,
13
+ roomName,
14
+ member: _member,
15
+ islevel,
16
+ showAlert
17
+ }) => {
18
+ if (islevel !== "2") {
19
+ showAlert?.({ message: "Only the host can update panelists", type: "danger", duration: 3e3 });
20
+ return;
21
+ }
22
+ socket.emit(
23
+ "updatePanelists",
24
+ {
25
+ panelists: panelists.map((p2) => ({ id: p2.id, name: p2.name })),
26
+ roomName
27
+ },
28
+ (response) => {
29
+ if (!response?.success) {
30
+ showAlert?.({ message: response?.reason || "Failed to update panelists", type: "danger", duration: 3e3 });
31
+ }
32
+ }
33
+ );
34
+ };
35
+ const addPanelist = async ({
36
+ socket,
37
+ participant,
38
+ currentPanelists,
39
+ maxPanelists,
40
+ roomName,
41
+ member: _member,
42
+ islevel,
43
+ showAlert
44
+ }) => {
45
+ if (islevel !== "2") {
46
+ showAlert?.({ message: "Only the host can add panelists", type: "danger", duration: 3e3 });
47
+ return false;
48
+ }
49
+ if (currentPanelists.some((p2) => p2.id === participant.id)) {
50
+ showAlert?.({ message: `${participant.name} is already a panelist`, type: "success", duration: 3e3 });
51
+ return false;
52
+ }
53
+ if (currentPanelists.length >= maxPanelists) {
54
+ showAlert?.({ message: `Maximum panelist limit (${maxPanelists}) reached`, type: "danger", duration: 3e3 });
55
+ return false;
56
+ }
57
+ return new Promise((resolve) => {
58
+ socket.emit(
59
+ "addPanelist",
60
+ {
61
+ participantId: participant.id,
62
+ participantName: participant.name,
63
+ roomName
64
+ },
65
+ (response) => {
66
+ if (!response?.success) {
67
+ showAlert?.({ message: response?.reason || "Failed to add panelist", type: "danger", duration: 3e3 });
68
+ resolve(false);
69
+ } else {
70
+ resolve(true);
71
+ }
72
+ }
73
+ );
74
+ });
75
+ };
76
+ const removePanelist = async ({
77
+ socket,
78
+ participant,
79
+ roomName,
80
+ member: _member,
81
+ islevel,
82
+ showAlert
83
+ }) => {
84
+ if (islevel !== "2") {
85
+ showAlert?.({ message: "Only the host can remove panelists", type: "danger", duration: 3e3 });
86
+ return;
87
+ }
88
+ socket.emit(
89
+ "removePanelist",
90
+ {
91
+ participantId: participant.id,
92
+ participantName: participant.name,
93
+ roomName
94
+ },
95
+ (response) => {
96
+ if (!response?.success) {
97
+ showAlert?.({ message: response?.reason || "Failed to remove panelist", type: "danger", duration: 3e3 });
98
+ }
99
+ }
100
+ );
101
+ };
102
+ const focusPanelists = async ({
103
+ socket,
104
+ roomName,
105
+ member: _member,
106
+ islevel,
107
+ focusEnabled,
108
+ muteOthersMic = false,
109
+ muteOthersCamera = false,
110
+ showAlert
111
+ }) => {
112
+ if (islevel !== "2") {
113
+ showAlert?.({ message: "Only the host can focus panelists", type: "danger", duration: 3e3 });
114
+ return;
115
+ }
116
+ socket.emit(
117
+ "focusPanelists",
118
+ {
119
+ roomName,
120
+ focusEnabled,
121
+ muteOthersMic,
122
+ muteOthersCamera
123
+ },
124
+ (response) => {
125
+ if (!response?.success) {
126
+ showAlert?.({ message: response?.reason || "Failed to focus panelists", type: "danger", duration: 3e3 });
127
+ }
128
+ }
129
+ );
130
+ };
131
+ const unfocusPanelists = async ({
132
+ socket,
133
+ roomName,
134
+ member: _member,
135
+ islevel,
136
+ showAlert
137
+ }) => {
138
+ if (islevel !== "2") {
139
+ showAlert?.({ message: "Only the host can unfocus panelists", type: "danger", duration: 3e3 });
140
+ return;
141
+ }
142
+ socket.emit(
143
+ "focusPanelists",
144
+ {
145
+ roomName,
146
+ focusEnabled: false,
147
+ muteOthersMic: false,
148
+ muteOthersCamera: false
149
+ },
150
+ (response) => {
151
+ if (!response?.success) {
152
+ showAlert?.({ message: response?.reason || "Failed to unfocus panelists", type: "danger", duration: 3e3 });
153
+ }
154
+ }
155
+ );
156
+ };
157
+ const launchPermissions = ({
158
+ updateIsPermissionsModalVisible,
159
+ isPermissionsModalVisible
160
+ }) => {
161
+ updateIsPermissionsModalVisible(!isPermissionsModalVisible);
162
+ };
163
+ const updateParticipantPermission = async ({
164
+ socket,
165
+ participant,
166
+ newLevel,
167
+ member: _member,
168
+ islevel,
169
+ roomName,
170
+ showAlert
171
+ }) => {
172
+ if (islevel !== "2") {
173
+ showAlert?.({ message: "Only the host can update participant permissions", type: "danger", duration: 3e3 });
174
+ return;
175
+ }
176
+ if (participant.islevel === "2") {
177
+ showAlert?.({ message: "Cannot change the host's permission level", type: "danger", duration: 3e3 });
178
+ return;
179
+ }
180
+ if (participant.islevel === newLevel) return;
181
+ return new Promise((resolve) => {
182
+ socket.emit(
183
+ "updateParticipantPermission",
184
+ {
185
+ participantId: participant.id,
186
+ participantName: participant.name,
187
+ newLevel,
188
+ roomName
189
+ },
190
+ (response) => {
191
+ if (!response?.success) {
192
+ showAlert?.({ message: response?.reason || "Failed to update permission", type: "danger", duration: 3e3 });
193
+ }
194
+ resolve();
195
+ }
196
+ );
197
+ });
198
+ };
199
+ const bulkUpdateParticipantPermissions = async ({
200
+ socket,
201
+ participants,
202
+ newLevel,
203
+ member: _member,
204
+ islevel,
205
+ roomName,
206
+ showAlert,
207
+ maxBatchSize = 50
208
+ }) => {
209
+ if (islevel !== "2") {
210
+ showAlert?.({ message: "Only the host can update participant permissions", type: "danger", duration: 3e3 });
211
+ return;
212
+ }
213
+ const eligibleParticipants = participants.filter(
214
+ (p2) => p2.islevel !== "2" && p2.islevel !== newLevel
215
+ );
216
+ if (eligibleParticipants.length === 0) {
217
+ showAlert?.({
218
+ message: "No participants to update",
219
+ type: "info",
220
+ duration: 3e3
221
+ });
222
+ return;
223
+ }
224
+ const batch = eligibleParticipants.slice(0, maxBatchSize);
225
+ return new Promise((resolve) => {
226
+ socket.emit(
227
+ "bulkUpdateParticipantPermissions",
228
+ {
229
+ updates: batch.map((p2) => ({
230
+ participantId: p2.id,
231
+ participantName: p2.name,
232
+ newLevel
233
+ })),
234
+ roomName
235
+ },
236
+ (response) => {
237
+ if (!response?.success) {
238
+ showAlert?.({
239
+ message: response?.reason || "Failed to update permissions",
240
+ type: "danger",
241
+ duration: 3e3
242
+ });
243
+ } else if (eligibleParticipants.length > maxBatchSize) {
244
+ showAlert?.({
245
+ message: `Updated ${batch.length} participants. ${eligibleParticipants.length - maxBatchSize} remaining.`,
246
+ type: "info",
247
+ duration: 3e3
248
+ });
249
+ }
250
+ resolve();
251
+ }
252
+ );
253
+ });
254
+ };
255
+ const updatePermissionConfig = async ({
256
+ socket,
257
+ config,
258
+ islevel,
259
+ roomName,
260
+ showAlert
261
+ }) => {
262
+ if (islevel !== "2") {
263
+ showAlert?.({ message: "Only the host can update permission configuration", type: "danger", duration: 3e3 });
264
+ return;
265
+ }
266
+ return new Promise((resolve) => {
267
+ socket.emit(
268
+ "updatePermissionConfig",
269
+ {
270
+ config,
271
+ roomName
272
+ },
273
+ (response) => {
274
+ if (!response?.success) {
275
+ showAlert?.({ message: response?.reason || "Failed to update permission config", type: "danger", duration: 3e3 });
276
+ }
277
+ resolve();
278
+ }
279
+ );
280
+ });
281
+ };
282
+ const pollUpdated = async ({
283
+ data,
284
+ polls,
285
+ poll,
286
+ member,
287
+ islevel,
288
+ showAlert,
289
+ updatePolls,
290
+ updatePoll,
291
+ updateIsPollModalVisible
292
+ }) => {
293
+ try {
294
+ if (data.polls) {
295
+ polls = data.polls;
296
+ updatePolls(data.polls);
297
+ } else {
298
+ polls = [data.poll];
299
+ updatePolls(polls);
300
+ }
301
+ let tempPoll = { id: "" };
302
+ if (poll) {
303
+ tempPoll = { ...poll };
304
+ }
305
+ if (data.status !== "ended") {
306
+ poll = data.poll;
307
+ updatePoll(data.poll);
308
+ }
309
+ if (data.status === "started" && islevel !== "2") {
310
+ if (!poll.voters || poll.voters && !poll.voters[member]) {
311
+ showAlert?.({
312
+ message: "New poll started",
313
+ type: "success",
314
+ duration: 3e3
315
+ });
316
+ updateIsPollModalVisible(true);
317
+ }
318
+ } else if (data.status === "ended") {
319
+ if (tempPoll.id === data.poll.id) {
320
+ showAlert?.({ message: "Poll ended", type: "danger", duration: 3e3 });
321
+ updatePoll(data.poll);
322
+ }
323
+ }
324
+ } catch {
325
+ }
326
+ };
327
+ async function handleCreateRoom({
328
+ payload,
329
+ localLink = "",
330
+ connectMediaSFU = true,
331
+ apiUserName,
332
+ apiKey,
333
+ validate = true,
334
+ parameters,
335
+ initSocket,
336
+ localData,
337
+ createMediaSFURoom
338
+ }) {
339
+ const {
340
+ updateIsLoadingModalVisible,
341
+ updateSocket,
342
+ updateApiUserName,
343
+ updateApiToken,
344
+ updateLink,
345
+ updateRoomName,
346
+ updateMember,
347
+ updateValidated,
348
+ showAlert
349
+ } = parameters;
350
+ const createLocalRoom = async ({
351
+ createData,
352
+ link = localLink
353
+ }) => {
354
+ initSocket?.emit("createRoom", createData, (response) => {
355
+ if (response.success) {
356
+ updateSocket(initSocket);
357
+ updateApiUserName(localData?.apiUserName || "");
358
+ updateApiToken(response.secret);
359
+ updateLink(link);
360
+ updateRoomName(createData.eventID);
361
+ updateMember(createData.userName + "_2");
362
+ updateIsLoadingModalVisible(false);
363
+ updateValidated(true);
364
+ } else {
365
+ updateIsLoadingModalVisible(false);
366
+ showAlert?.({
367
+ message: `Unable to create room. ${response.reason}`,
368
+ type: "danger",
369
+ duration: 3e3
370
+ });
371
+ }
372
+ });
373
+ };
374
+ const roomCreator = async ({
375
+ payload: createPayload,
376
+ apiUserName: userName,
377
+ apiKey: key,
378
+ validate: shouldValidate = true
379
+ }) => {
380
+ const response = await createMediaSFURoom({
381
+ payload: createPayload,
382
+ apiUserName: userName,
383
+ apiKey: key,
384
+ localLink
385
+ });
386
+ if (response.success && response.data && "roomName" in response.data) {
387
+ await checkLimitsAndMakeRequest({
388
+ apiUserName: response.data.roomName,
389
+ apiToken: response.data.secret,
390
+ link: response.data.link,
391
+ userName: createPayload.userName,
392
+ parameters,
393
+ validate: shouldValidate
394
+ });
395
+ return response;
396
+ } else {
397
+ updateIsLoadingModalVisible(false);
398
+ showAlert?.({
399
+ message: `Unable to create room. ${response.data ? "error" in response.data ? response.data.error : "" : ""}`,
400
+ type: "danger",
401
+ duration: 3e3
402
+ });
403
+ }
404
+ };
405
+ updateIsLoadingModalVisible(true);
406
+ if (localLink.length > 0) {
407
+ const secureCode = Math.random().toString(30).substring(2, 14) + Math.random().toString(30).substring(2, 14);
408
+ let eventID = (/* @__PURE__ */ new Date()).getTime().toString(30) + (/* @__PURE__ */ new Date()).getUTCMilliseconds() + Math.floor(10 + Math.random() * 99).toString();
409
+ eventID = "m" + eventID;
410
+ const eventRoomParams = localData?.meetingRoomParams_;
411
+ if (eventRoomParams && payload.eventType) {
412
+ eventRoomParams.type = payload.eventType;
413
+ }
414
+ const createData = {
415
+ eventID,
416
+ duration: payload.duration,
417
+ capacity: payload.capacity,
418
+ userName: payload.userName,
419
+ scheduledDate: /* @__PURE__ */ new Date(),
420
+ secureCode,
421
+ waitRoom: false,
422
+ recordingParams: localData?.recordingParams_,
423
+ eventRoomParams,
424
+ videoPreference: null,
425
+ audioPreference: null,
426
+ audioOutputPreference: null,
427
+ mediasfuURL: ""
428
+ };
429
+ if (connectMediaSFU && initSocket && localData && localData.apiUserName && localData.apiKey) {
430
+ const localApiUserName = localData.apiUserName;
431
+ const localApiKey = localData.apiKey;
432
+ const roomIdentifier = `local_create_${payload.userName}_${payload.duration}_${payload.capacity}`;
433
+ const pendingKey = `prejoin_pending_${roomIdentifier}`;
434
+ const PENDING_TIMEOUT = 30 * 1e3;
435
+ try {
436
+ const pendingRequest = localStorage.getItem(pendingKey);
437
+ if (pendingRequest) {
438
+ const pendingData = JSON.parse(pendingRequest);
439
+ const timeSincePending = Date.now() - (pendingData?.timestamp ?? 0);
440
+ if (timeSincePending < PENDING_TIMEOUT) {
441
+ updateIsLoadingModalVisible(false);
442
+ showAlert?.({
443
+ message: "Room creation already in progress",
444
+ type: "danger",
445
+ duration: 3e3
446
+ });
447
+ return;
448
+ } else {
449
+ try {
450
+ localStorage.removeItem(pendingKey);
451
+ } catch {
452
+ }
453
+ }
454
+ }
455
+ } catch {
456
+ }
457
+ try {
458
+ localStorage.setItem(
459
+ pendingKey,
460
+ JSON.stringify({
461
+ timestamp: Date.now(),
462
+ payload: {
463
+ action: "create",
464
+ userName: payload.userName,
465
+ duration: payload.duration,
466
+ capacity: payload.capacity
467
+ }
468
+ })
469
+ );
470
+ setTimeout(() => {
471
+ try {
472
+ localStorage.removeItem(pendingKey);
473
+ } catch {
474
+ }
475
+ }, PENDING_TIMEOUT);
476
+ } catch {
477
+ }
478
+ payload.recordOnly = true;
479
+ try {
480
+ const response = await roomCreator({
481
+ payload,
482
+ apiUserName: localApiUserName,
483
+ apiKey: localApiKey,
484
+ validate: false
485
+ });
486
+ try {
487
+ localStorage.removeItem(pendingKey);
488
+ } catch {
489
+ }
490
+ if (response && response.success && response.data && "roomName" in response.data) {
491
+ createData.eventID = response.data.roomName;
492
+ createData.secureCode = response.data.secureCode || "";
493
+ createData.mediasfuURL = response.data.publicURL;
494
+ await createLocalRoom({
495
+ createData,
496
+ link: response.data.link
497
+ });
498
+ } else {
499
+ updateIsLoadingModalVisible(false);
500
+ showAlert?.({
501
+ message: `Unable to create room on MediaSFU.`,
502
+ type: "danger",
503
+ duration: 3e3
504
+ });
505
+ try {
506
+ updateSocket(initSocket);
507
+ await createLocalRoom({ createData });
508
+ } catch (error) {
509
+ updateIsLoadingModalVisible(false);
510
+ showAlert?.({
511
+ message: `Unable to create room. ${error}`,
512
+ type: "danger",
513
+ duration: 3e3
514
+ });
515
+ }
516
+ }
517
+ } catch (error) {
518
+ try {
519
+ localStorage.removeItem(pendingKey);
520
+ } catch {
521
+ }
522
+ updateIsLoadingModalVisible(false);
523
+ showAlert?.({
524
+ message: `Unable to create room on MediaSFU. ${error}`,
525
+ type: "danger",
526
+ duration: 3e3
527
+ });
528
+ }
529
+ } else {
530
+ try {
531
+ updateSocket(initSocket);
532
+ await createLocalRoom({ createData });
533
+ } catch (error) {
534
+ updateIsLoadingModalVisible(false);
535
+ showAlert?.({
536
+ message: `Unable to create room. ${error}`,
537
+ type: "danger",
538
+ duration: 3e3
539
+ });
540
+ }
541
+ }
542
+ } else {
543
+ const roomIdentifier = `mediasfu_create_${payload.userName}_${payload.duration}_${payload.capacity}`;
544
+ const pendingKey = `prejoin_pending_${roomIdentifier}`;
545
+ const PENDING_TIMEOUT = 30 * 1e3;
546
+ try {
547
+ const pendingRequest = localStorage.getItem(pendingKey);
548
+ if (pendingRequest) {
549
+ const pendingData = JSON.parse(pendingRequest);
550
+ const timeSincePending = Date.now() - (pendingData?.timestamp ?? 0);
551
+ if (timeSincePending < PENDING_TIMEOUT) {
552
+ updateIsLoadingModalVisible(false);
553
+ showAlert?.({
554
+ message: "Room creation already in progress",
555
+ type: "danger",
556
+ duration: 3e3
557
+ });
558
+ return;
559
+ } else {
560
+ try {
561
+ localStorage.removeItem(pendingKey);
562
+ } catch {
563
+ }
564
+ }
565
+ }
566
+ } catch {
567
+ }
568
+ try {
569
+ localStorage.setItem(
570
+ pendingKey,
571
+ JSON.stringify({
572
+ timestamp: Date.now(),
573
+ payload: {
574
+ action: "create",
575
+ userName: payload.userName,
576
+ duration: payload.duration,
577
+ capacity: payload.capacity
578
+ }
579
+ })
580
+ );
581
+ setTimeout(() => {
582
+ try {
583
+ localStorage.removeItem(pendingKey);
584
+ } catch {
585
+ }
586
+ }, PENDING_TIMEOUT);
587
+ } catch {
588
+ }
589
+ try {
590
+ await roomCreator({
591
+ payload,
592
+ apiUserName,
593
+ apiKey,
594
+ validate
595
+ });
596
+ try {
597
+ localStorage.removeItem(pendingKey);
598
+ } catch {
599
+ }
600
+ } catch (error) {
601
+ try {
602
+ localStorage.removeItem(pendingKey);
603
+ } catch {
604
+ }
605
+ updateIsLoadingModalVisible(false);
606
+ showAlert?.({
607
+ message: `Unable to create room. ${error}`,
608
+ type: "danger",
609
+ duration: 3e3
610
+ });
611
+ }
612
+ }
613
+ }
614
+ async function handleJoinRoom({
615
+ payload,
616
+ localLink = "",
617
+ apiUserName,
618
+ apiKey,
619
+ parameters,
620
+ initSocket,
621
+ localData,
622
+ joinMediaSFURoom
623
+ }) {
624
+ const {
625
+ updateIsLoadingModalVisible,
626
+ updateSocket,
627
+ updateApiUserName,
628
+ updateApiToken,
629
+ updateLink,
630
+ updateRoomName,
631
+ updateMember,
632
+ updateValidated,
633
+ showAlert
634
+ } = parameters;
635
+ const joinLocalRoom = async ({ joinData, link = localLink }) => {
636
+ initSocket?.emit("joinEventRoom", joinData, (response2) => {
637
+ if (response2.success) {
638
+ updateSocket(initSocket);
639
+ updateApiUserName(localData?.apiUserName || "");
640
+ updateApiToken(response2.secret);
641
+ updateLink(link);
642
+ updateRoomName(joinData.eventID);
643
+ updateMember(joinData.userName);
644
+ updateIsLoadingModalVisible(false);
645
+ updateValidated(true);
646
+ } else {
647
+ updateIsLoadingModalVisible(false);
648
+ showAlert?.({
649
+ message: `Unable to join room. ${response2.reason}`,
650
+ type: "danger",
651
+ duration: 3e3
652
+ });
653
+ }
654
+ });
655
+ };
656
+ if (localLink.length > 0 && !localLink.includes("mediasfu.com")) {
657
+ const joinData = {
658
+ eventID: payload.meetingID,
659
+ userName: payload.userName,
660
+ secureCode: "",
661
+ videoPreference: null,
662
+ audioPreference: null,
663
+ audioOutputPreference: null
664
+ };
665
+ await joinLocalRoom({ joinData });
666
+ return;
667
+ }
668
+ updateIsLoadingModalVisible(true);
669
+ const response = await joinMediaSFURoom({
670
+ payload,
671
+ apiUserName,
672
+ apiKey,
673
+ localLink
674
+ });
675
+ if (response.success && response.data && "roomName" in response.data) {
676
+ await checkLimitsAndMakeRequest({
677
+ apiUserName: response.data.roomName,
678
+ apiToken: response.data.secret,
679
+ link: response.data.link,
680
+ userName: payload.userName,
681
+ parameters
682
+ });
683
+ } else {
684
+ updateIsLoadingModalVisible(false);
685
+ showAlert?.({
686
+ message: `Unable to join room. ${response.data ? "error" in response.data ? response.data.error : "" : ""}`,
687
+ type: "danger",
688
+ duration: 3e3
689
+ });
690
+ }
691
+ }
692
+ const clickChat = async ({
693
+ isMessagesModalVisible,
694
+ updateIsMessagesModalVisible,
695
+ chatSetting,
696
+ islevel,
697
+ showAlert
698
+ }) => {
699
+ if (isMessagesModalVisible) {
700
+ updateIsMessagesModalVisible(false);
701
+ return;
702
+ }
703
+ if (chatSetting !== "allow" && islevel !== "2") {
704
+ updateIsMessagesModalVisible(false);
705
+ showAlert?.({
706
+ message: "Chat is disabled for this event.",
707
+ type: "danger",
708
+ duration: 3e3
709
+ });
710
+ return;
711
+ }
712
+ updateIsMessagesModalVisible(true);
713
+ };
714
+ const createLiveSubtitle = (params) => {
715
+ const timestamp = params.timestamp ?? Date.now();
716
+ const duration = Math.min(8e3, Math.max(3e3, 3e3 + params.text.length * 50));
717
+ return {
718
+ text: params.text,
719
+ language: params.language,
720
+ timestamp,
721
+ expiresAt: timestamp + duration,
722
+ speakerId: params.speakerId,
723
+ speakerName: params.speakerName
724
+ };
725
+ };
726
+ const isSubtitleExpired = (subtitle, now = Date.now()) => {
727
+ return now >= subtitle.expiresAt;
728
+ };
729
+ const pruneExpiredSubtitles = (subtitles, now = Date.now()) => {
730
+ const next = new Map(subtitles);
731
+ for (const [key, subtitle] of next.entries()) {
732
+ if (isSubtitleExpired(subtitle, now)) {
733
+ next.delete(key);
734
+ }
735
+ }
736
+ return next;
737
+ };
738
+ const updateLiveSubtitlesFromTranscript = ({
739
+ currentSubtitles,
740
+ transcript,
741
+ now
742
+ }) => {
743
+ const subtitle = createLiveSubtitle({
744
+ text: transcript.translatedText || transcript.originalText,
745
+ language: transcript.language,
746
+ speakerId: transcript.speakerId,
747
+ speakerName: transcript.speakerName,
748
+ timestamp: now ?? transcript.timestamp
749
+ });
750
+ const next = pruneExpiredSubtitles(currentSubtitles, subtitle.timestamp);
751
+ next.set(transcript.speakerId, subtitle);
752
+ if (transcript.speakerName) {
753
+ next.set(transcript.speakerName, subtitle);
754
+ }
755
+ return next;
756
+ };
757
+ const getSubtitleForSpeaker = (subtitles, speakerId, speakerName, now = Date.now()) => {
758
+ const activeSubtitles = pruneExpiredSubtitles(subtitles, now);
759
+ if (speakerId && activeSubtitles.has(speakerId)) {
760
+ return activeSubtitles.get(speakerId) || null;
761
+ }
762
+ if (speakerName && activeSubtitles.has(speakerName)) {
763
+ return activeSubtitles.get(speakerName) || null;
764
+ }
765
+ return null;
766
+ };
767
+ const SUPPORTED_LANGUAGE_CODES = [
768
+ "en",
769
+ "es",
770
+ "fr",
771
+ "de",
772
+ "it",
773
+ "pt",
774
+ "ru",
775
+ "zh",
776
+ "ja",
777
+ "ko",
778
+ "ar",
779
+ "hi",
780
+ "bn",
781
+ "pa",
782
+ "te",
783
+ "mr",
784
+ "ta",
785
+ "ur",
786
+ "gu",
787
+ "kn",
788
+ "ml",
789
+ "ne",
790
+ "si",
791
+ "nl",
792
+ "pl",
793
+ "tr",
794
+ "cs",
795
+ "el",
796
+ "hu",
797
+ "ro",
798
+ "sv",
799
+ "da",
800
+ "fi",
801
+ "no",
802
+ "sk",
803
+ "uk",
804
+ "bg",
805
+ "hr",
806
+ "et",
807
+ "lt",
808
+ "lv",
809
+ "sl",
810
+ "sr",
811
+ "bs",
812
+ "mk",
813
+ "is",
814
+ "ga",
815
+ "cy",
816
+ "mt",
817
+ "lb",
818
+ "sq",
819
+ "be",
820
+ "he",
821
+ "fa",
822
+ "ps",
823
+ "ku",
824
+ "vi",
825
+ "th",
826
+ "id",
827
+ "ms",
828
+ "tl",
829
+ "km",
830
+ "lo",
831
+ "my",
832
+ "sw",
833
+ "yo",
834
+ "ig",
835
+ "ha",
836
+ "zu",
837
+ "xh",
838
+ "af",
839
+ "st",
840
+ "tn",
841
+ "sn",
842
+ "am",
843
+ "so",
844
+ "rw",
845
+ "mg",
846
+ "ny",
847
+ "ee",
848
+ "tw",
849
+ "gaa",
850
+ "ka",
851
+ "hy",
852
+ "az",
853
+ "eu",
854
+ "gl",
855
+ "ca",
856
+ "la",
857
+ "eo",
858
+ "kk",
859
+ "uz",
860
+ "tg",
861
+ "ky",
862
+ "tk",
863
+ "mn",
864
+ "auto"
865
+ ];
866
+ const REGION_BY_LANGUAGE = {
867
+ en: "global",
868
+ es: "global",
869
+ fr: "europe",
870
+ de: "europe",
871
+ it: "europe",
872
+ pt: "global",
873
+ ru: "europe",
874
+ zh: "asia",
875
+ ja: "asia",
876
+ ko: "asia",
877
+ ar: "mena",
878
+ hi: "south-asia",
879
+ bn: "south-asia",
880
+ pa: "south-asia",
881
+ te: "south-asia",
882
+ mr: "south-asia",
883
+ ta: "south-asia",
884
+ ur: "south-asia",
885
+ gu: "south-asia",
886
+ kn: "south-asia",
887
+ ml: "south-asia",
888
+ ne: "south-asia",
889
+ si: "south-asia",
890
+ nl: "europe",
891
+ pl: "europe",
892
+ tr: "europe",
893
+ cs: "europe",
894
+ el: "europe",
895
+ hu: "europe",
896
+ ro: "europe",
897
+ sv: "europe",
898
+ da: "europe",
899
+ fi: "europe",
900
+ no: "europe",
901
+ sk: "europe",
902
+ uk: "europe",
903
+ bg: "europe",
904
+ hr: "europe",
905
+ et: "europe",
906
+ lt: "europe",
907
+ lv: "europe",
908
+ sl: "europe",
909
+ sr: "europe",
910
+ bs: "europe",
911
+ mk: "europe",
912
+ is: "europe",
913
+ ga: "europe",
914
+ cy: "europe",
915
+ mt: "europe",
916
+ lb: "europe",
917
+ sq: "europe",
918
+ be: "europe",
919
+ he: "mena",
920
+ fa: "mena",
921
+ ps: "mena",
922
+ ku: "mena",
923
+ vi: "asia",
924
+ th: "asia",
925
+ id: "asia",
926
+ ms: "asia",
927
+ tl: "asia",
928
+ km: "asia",
929
+ lo: "asia",
930
+ my: "asia",
931
+ sw: "africa",
932
+ yo: "africa",
933
+ ig: "africa",
934
+ ha: "africa",
935
+ zu: "africa",
936
+ xh: "africa",
937
+ af: "africa",
938
+ st: "africa",
939
+ tn: "africa",
940
+ sn: "africa",
941
+ am: "africa",
942
+ so: "africa",
943
+ rw: "africa",
944
+ mg: "africa",
945
+ ny: "africa",
946
+ ee: "africa",
947
+ tw: "africa",
948
+ gaa: "africa",
949
+ ka: "caucasus",
950
+ hy: "caucasus",
951
+ az: "caucasus",
952
+ eu: "europe",
953
+ gl: "europe",
954
+ ca: "europe",
955
+ la: "europe",
956
+ eo: "constructed",
957
+ kk: "central-asia",
958
+ uz: "central-asia",
959
+ tg: "central-asia",
960
+ ky: "central-asia",
961
+ tk: "central-asia",
962
+ mn: "central-asia",
963
+ auto: "special"
964
+ };
965
+ const TTS_SUPPORT_BY_LANGUAGE = {
966
+ en: "excellent",
967
+ es: "excellent",
968
+ fr: "excellent",
969
+ de: "excellent",
970
+ it: "excellent",
971
+ pt: "excellent",
972
+ ru: "excellent",
973
+ zh: "excellent",
974
+ ja: "excellent",
975
+ ko: "excellent",
976
+ ar: "excellent",
977
+ hi: "good",
978
+ bn: "good",
979
+ te: "good",
980
+ mr: "good",
981
+ ta: "good",
982
+ ur: "good",
983
+ nl: "excellent",
984
+ pl: "excellent",
985
+ tr: "excellent",
986
+ cs: "good",
987
+ el: "good",
988
+ hu: "good",
989
+ ro: "good",
990
+ sv: "excellent",
991
+ da: "good",
992
+ fi: "good",
993
+ no: "good",
994
+ uk: "good",
995
+ he: "good",
996
+ vi: "good",
997
+ th: "good",
998
+ id: "good",
999
+ ms: "good",
1000
+ af: "good",
1001
+ ca: "good",
1002
+ auto: "n/a"
1003
+ };
1004
+ const LANGUAGE_NAMES_EN = {
1005
+ en: "English",
1006
+ es: "Spanish",
1007
+ fr: "French",
1008
+ de: "German",
1009
+ it: "Italian",
1010
+ pt: "Portuguese",
1011
+ nl: "Dutch",
1012
+ ru: "Russian",
1013
+ zh: "Chinese",
1014
+ ja: "Japanese",
1015
+ ko: "Korean",
1016
+ ar: "Arabic",
1017
+ hi: "Hindi",
1018
+ bn: "Bengali",
1019
+ pa: "Punjabi",
1020
+ te: "Telugu",
1021
+ mr: "Marathi",
1022
+ ta: "Tamil",
1023
+ ur: "Urdu",
1024
+ gu: "Gujarati",
1025
+ kn: "Kannada",
1026
+ ml: "Malayalam",
1027
+ ne: "Nepali",
1028
+ si: "Sinhala",
1029
+ tr: "Turkish",
1030
+ pl: "Polish",
1031
+ vi: "Vietnamese",
1032
+ th: "Thai",
1033
+ id: "Indonesian",
1034
+ ms: "Malay",
1035
+ tl: "Filipino",
1036
+ km: "Khmer",
1037
+ lo: "Lao",
1038
+ my: "Burmese",
1039
+ sw: "Swahili",
1040
+ yo: "Yoruba",
1041
+ ha: "Hausa",
1042
+ ig: "Igbo",
1043
+ zu: "Zulu",
1044
+ xh: "Xhosa",
1045
+ af: "Afrikaans",
1046
+ st: "Sesotho",
1047
+ tn: "Tswana",
1048
+ sn: "Shona",
1049
+ am: "Amharic",
1050
+ so: "Somali",
1051
+ rw: "Kinyarwanda",
1052
+ mg: "Malagasy",
1053
+ ny: "Chichewa",
1054
+ ee: "Ewe",
1055
+ tw: "Twi",
1056
+ gaa: "Ga",
1057
+ he: "Hebrew",
1058
+ fa: "Persian",
1059
+ ps: "Pashto",
1060
+ ku: "Kurdish",
1061
+ uk: "Ukrainian",
1062
+ el: "Greek",
1063
+ cs: "Czech",
1064
+ ro: "Romanian",
1065
+ hu: "Hungarian",
1066
+ sv: "Swedish",
1067
+ da: "Danish",
1068
+ no: "Norwegian",
1069
+ fi: "Finnish",
1070
+ sk: "Slovak",
1071
+ bg: "Bulgarian",
1072
+ hr: "Croatian",
1073
+ et: "Estonian",
1074
+ lt: "Lithuanian",
1075
+ lv: "Latvian",
1076
+ sl: "Slovenian",
1077
+ sr: "Serbian",
1078
+ bs: "Bosnian",
1079
+ mk: "Macedonian",
1080
+ is: "Icelandic",
1081
+ ga: "Irish",
1082
+ cy: "Welsh",
1083
+ mt: "Maltese",
1084
+ lb: "Luxembourgish",
1085
+ sq: "Albanian",
1086
+ be: "Belarusian",
1087
+ ka: "Georgian",
1088
+ hy: "Armenian",
1089
+ az: "Azerbaijani",
1090
+ eu: "Basque",
1091
+ gl: "Galician",
1092
+ ca: "Catalan",
1093
+ la: "Latin",
1094
+ eo: "Esperanto",
1095
+ kk: "Kazakh",
1096
+ uz: "Uzbek",
1097
+ tg: "Tajik",
1098
+ ky: "Kyrgyz",
1099
+ tk: "Turkmen",
1100
+ mn: "Mongolian"
1101
+ };
1102
+ const getDisplayName = (code, locale, fallback) => {
1103
+ try {
1104
+ const displayNames = new Intl.DisplayNames([locale], { type: "language" });
1105
+ const result = displayNames.of(code);
1106
+ if (result) return result;
1107
+ } catch {
1108
+ }
1109
+ return LANGUAGE_NAMES_EN[code] ?? fallback;
1110
+ };
1111
+ const normalizeLanguageCode = (code) => {
1112
+ if (!code || typeof code !== "string") {
1113
+ return "en";
1114
+ }
1115
+ return code.trim().toLowerCase().split("-")[0];
1116
+ };
1117
+ const isLanguageSupported = (code) => {
1118
+ const normalized = normalizeLanguageCode(code);
1119
+ return SUPPORTED_LANGUAGE_CODES.includes(normalized);
1120
+ };
1121
+ const getLanguageName = (code, displayLocale = "en") => {
1122
+ const normalized = normalizeLanguageCode(code);
1123
+ if (normalized === "auto") {
1124
+ return "Auto-detect";
1125
+ }
1126
+ return getDisplayName(normalized, displayLocale, normalized.toUpperCase());
1127
+ };
1128
+ const getLanguageNativeName = (code) => {
1129
+ const normalized = normalizeLanguageCode(code);
1130
+ if (normalized === "auto") {
1131
+ return "Auto";
1132
+ }
1133
+ return getDisplayName(normalized, normalized, getLanguageName(normalized));
1134
+ };
1135
+ const getLanguageMetadata = (code) => {
1136
+ const normalized = normalizeLanguageCode(code);
1137
+ return {
1138
+ name: getLanguageName(normalized),
1139
+ nativeName: getLanguageNativeName(normalized),
1140
+ region: REGION_BY_LANGUAGE[normalized] || "other",
1141
+ ttsSupport: TTS_SUPPORT_BY_LANGUAGE[normalized] || "unknown"
1142
+ };
1143
+ };
1144
+ const getSupportedLanguages = (displayLocale = "en") => {
1145
+ return SUPPORTED_LANGUAGE_CODES.map((code) => {
1146
+ const metadata = getLanguageMetadata(code);
1147
+ return {
1148
+ code,
1149
+ name: getLanguageName(code, displayLocale),
1150
+ nativeName: metadata.nativeName,
1151
+ region: metadata.region,
1152
+ ttsSupport: metadata.ttsSupport
1153
+ };
1154
+ }).sort((left, right) => left.name.localeCompare(right.name));
1155
+ };
1156
+ const COMMON_LANGUAGE_CODES = [
1157
+ "en",
1158
+ "es",
1159
+ "fr",
1160
+ "de",
1161
+ "it",
1162
+ "pt",
1163
+ "nl",
1164
+ "ru",
1165
+ "zh",
1166
+ "ja",
1167
+ "ko",
1168
+ "ar",
1169
+ "hi",
1170
+ "bn",
1171
+ "tr",
1172
+ "pl",
1173
+ "vi",
1174
+ "th",
1175
+ "id",
1176
+ "ms",
1177
+ "sw",
1178
+ "yo",
1179
+ "ha",
1180
+ "ig",
1181
+ "zu",
1182
+ "am",
1183
+ "tw",
1184
+ "he",
1185
+ "fa",
1186
+ "uk",
1187
+ "el",
1188
+ "cs",
1189
+ "ro",
1190
+ "hu",
1191
+ "sv",
1192
+ "da",
1193
+ "no",
1194
+ "fi"
1195
+ ];
1196
+ const getCommonLanguages = (displayLocale = "en") => {
1197
+ return COMMON_LANGUAGE_CODES.map((code) => {
1198
+ const metadata = getLanguageMetadata(code);
1199
+ return {
1200
+ code,
1201
+ name: getLanguageName(code, displayLocale),
1202
+ nativeName: metadata.nativeName,
1203
+ region: metadata.region,
1204
+ ttsSupport: metadata.ttsSupport
1205
+ };
1206
+ }).sort((left, right) => left.name.localeCompare(right.name));
1207
+ };
1208
+ const TTS_PROVIDERS = {
1209
+ deepgram: { name: "Deepgram Aura", supportsSSML: false, isDefault: true },
1210
+ openai: { name: "OpenAI TTS", supportsSSML: false, multilingual: true },
1211
+ azure: { name: "Azure Neural TTS", supportsSSML: true },
1212
+ google: { name: "Google Cloud TTS", supportsSSML: true },
1213
+ aws: { name: "AWS Polly", supportsSSML: true },
1214
+ elevenlabs: { name: "ElevenLabs", supportsSSML: false, multilingual: true },
1215
+ playht: { name: "PlayHT", supportsSSML: false, multilingual: true },
1216
+ cartesia: { name: "Cartesia Sonic", supportsSSML: false, multilingual: true },
1217
+ rime: { name: "Rime AI", supportsSSML: false, multilingual: true },
1218
+ kokoro: { name: "Kokoro", supportsSSML: false, multilingual: true },
1219
+ gemini: { name: "Google Gemini TTS", supportsSSML: false, multilingual: true },
1220
+ assemblyai: { name: "AssemblyAI", supportsSSML: false }
1221
+ };
1222
+ const buildFallbackVoices = (langCode, provider) => {
1223
+ const normalizedLanguage = normalizeLanguageCode(langCode === "auto" ? "en" : langCode);
1224
+ const providerKey = provider.toLowerCase();
1225
+ const providerName = TTS_PROVIDERS[providerKey]?.name || provider;
1226
+ const languageName = getLanguageName(normalizedLanguage);
1227
+ return {
1228
+ female: [
1229
+ {
1230
+ id: `${providerKey}-${normalizedLanguage}-female-1`,
1231
+ name: `${providerName} ${languageName} Female`,
1232
+ gender: "female",
1233
+ provider: providerKey,
1234
+ language: normalizedLanguage
1235
+ },
1236
+ {
1237
+ id: `${providerKey}-${normalizedLanguage}-female-2`,
1238
+ name: `${providerName} ${languageName} Female 2`,
1239
+ gender: "female",
1240
+ provider: providerKey,
1241
+ language: normalizedLanguage
1242
+ }
1243
+ ],
1244
+ male: [
1245
+ {
1246
+ id: `${providerKey}-${normalizedLanguage}-male-1`,
1247
+ name: `${providerName} ${languageName} Male`,
1248
+ gender: "male",
1249
+ provider: providerKey,
1250
+ language: normalizedLanguage
1251
+ },
1252
+ {
1253
+ id: `${providerKey}-${normalizedLanguage}-male-2`,
1254
+ name: `${providerName} ${languageName} Male 2`,
1255
+ gender: "male",
1256
+ provider: providerKey,
1257
+ language: normalizedLanguage
1258
+ }
1259
+ ]
1260
+ };
1261
+ };
1262
+ const getAvailableVoices = (langCode, provider = "deepgram") => {
1263
+ return buildFallbackVoices(langCode, provider.toString());
1264
+ };
1265
+ const fetchVoicesViaSocket = (socket, provider = "deepgram", language = "en") => {
1266
+ return new Promise((resolve) => {
1267
+ const providerName = provider.toString();
1268
+ const fallbackVoices = getAvailableVoices(language, providerName);
1269
+ const timeout = setTimeout(() => {
1270
+ resolve({
1271
+ provider: providerName,
1272
+ language,
1273
+ voices: fallbackVoices,
1274
+ error: "Request timed out, using shared fallback voices"
1275
+ });
1276
+ }, 5e3);
1277
+ socket.emit("translation:getVoices", { provider, language }, (response) => {
1278
+ clearTimeout(timeout);
1279
+ if (response?.voices) {
1280
+ resolve(response);
1281
+ return;
1282
+ }
1283
+ resolve({
1284
+ provider: response?.provider || providerName,
1285
+ language: response?.language || language,
1286
+ voices: fallbackVoices,
1287
+ error: response?.error || "No voices returned, using shared fallback voices"
1288
+ });
1289
+ });
1290
+ });
1291
+ };
1292
+ const fetchLanguagesViaSocket = (socket, displayLocale = "en") => {
1293
+ return new Promise((resolve) => {
1294
+ const timeout = setTimeout(() => {
1295
+ resolve(getSupportedLanguages(displayLocale));
1296
+ }, 5e3);
1297
+ socket.emit("translation:getLanguages", { displayLocale }, (response) => {
1298
+ clearTimeout(timeout);
1299
+ resolve(response?.languages?.length ? response.languages : getSupportedLanguages(displayLocale));
1300
+ });
1301
+ });
1302
+ };
1303
+ const SoundPlayer = async ({ soundUrl }) => {
1304
+ if (!soundUrl || typeof Audio === "undefined") {
1305
+ return;
1306
+ }
1307
+ try {
1308
+ const audio = new Audio(soundUrl);
1309
+ await audio.play();
1310
+ } catch (error) {
1311
+ console.error("Error playing sound:", error);
1312
+ }
1313
+ };
1314
+ const getOverlayPosition = ({ position }) => {
1315
+ switch (position) {
1316
+ case "topLeft":
1317
+ return { top: 0, left: 0 };
1318
+ case "topRight":
1319
+ return { top: 0, right: 0 };
1320
+ case "bottomLeft":
1321
+ return { bottom: 0, left: 0 };
1322
+ case "bottomRight":
1323
+ return { bottom: 0, right: 0 };
1324
+ default:
1325
+ return {};
1326
+ }
1327
+ };
1328
+ function sleep({ ms }) {
1329
+ return new Promise((resolve) => setTimeout(resolve, ms));
1330
+ }
1331
+ const formatNumber = async ({ number }) => {
1332
+ if (number) {
1333
+ if (number < 1e3) {
1334
+ return number.toString();
1335
+ }
1336
+ if (number < 1e6) {
1337
+ return `${(number / 1e3).toFixed(1)}K`;
1338
+ }
1339
+ if (number < 1e9) {
1340
+ return `${(number / 1e6).toFixed(1)}M`;
1341
+ }
1342
+ if (number < 1e12) {
1343
+ return `${(number / 1e9).toFixed(1)}B`;
1344
+ }
1345
+ }
1346
+ return void 0;
1347
+ };
1348
+ const generateRandomMessages = ({
1349
+ participants,
1350
+ member,
1351
+ coHost = "",
1352
+ host,
1353
+ forChatBroadcast = false
1354
+ }) => {
1355
+ const messages = [];
1356
+ const getRandomReceiver = (sender) => {
1357
+ const potentialReceivers = participants.filter((participant) => participant.name !== sender);
1358
+ const randomReceiver = potentialReceivers[Math.floor(Math.random() * potentialReceivers.length)];
1359
+ return randomReceiver?.name || "";
1360
+ };
1361
+ let refNames = [];
1362
+ if (forChatBroadcast) {
1363
+ refNames = [member, host];
1364
+ } else if (coHost) {
1365
+ refNames = [
1366
+ member,
1367
+ coHost,
1368
+ host,
1369
+ ...participants.map((participant) => participant.name).filter((name) => name !== void 0)
1370
+ ];
1371
+ } else {
1372
+ refNames = [
1373
+ member,
1374
+ host,
1375
+ ...participants.map((participant) => participant.name).filter((name) => name !== void 0)
1376
+ ];
1377
+ }
1378
+ refNames = [...new Set(refNames)];
1379
+ let timeIncrement = 0;
1380
+ refNames.forEach((sender) => {
1381
+ messages.push({
1382
+ sender,
1383
+ receivers: [getRandomReceiver(sender)],
1384
+ message: `Direct message from ${sender}`,
1385
+ timestamp: new Date(Date.now() + timeIncrement).toLocaleTimeString(),
1386
+ group: false
1387
+ });
1388
+ messages.push({
1389
+ sender,
1390
+ receivers: participants.map((participant) => participant.name).filter((name) => name !== void 0),
1391
+ message: `Group message from ${sender}`,
1392
+ timestamp: new Date(Date.now() + timeIncrement).toLocaleTimeString(),
1393
+ group: true
1394
+ });
1395
+ timeIncrement += 15e3;
1396
+ });
1397
+ return messages;
1398
+ };
1399
+ const generateRandomParticipants = ({
1400
+ member,
1401
+ coHost = "",
1402
+ host,
1403
+ forChatBroadcast = false
1404
+ }) => {
1405
+ const participants = [];
1406
+ let names = [
1407
+ "Alice",
1408
+ "Bob",
1409
+ "Charlie",
1410
+ "David",
1411
+ "Eve",
1412
+ "Frank",
1413
+ "Grace",
1414
+ "Hank",
1415
+ "Ivy",
1416
+ "Jack",
1417
+ "Kate",
1418
+ "Liam",
1419
+ "Mia",
1420
+ "Nina",
1421
+ "Olivia",
1422
+ "Pete",
1423
+ "Quinn",
1424
+ "Rachel",
1425
+ "Steve",
1426
+ "Tina",
1427
+ "Ursula",
1428
+ "Vince",
1429
+ "Wendy",
1430
+ "Xander",
1431
+ "Yvonne",
1432
+ "Zack"
1433
+ ];
1434
+ if (forChatBroadcast) {
1435
+ names.splice(2);
1436
+ }
1437
+ if (!names.includes(member)) {
1438
+ names.unshift(member);
1439
+ }
1440
+ if (!names.includes(coHost) && !forChatBroadcast) {
1441
+ names.unshift(coHost);
1442
+ }
1443
+ if (!names.includes(host)) {
1444
+ names.unshift(host);
1445
+ }
1446
+ if (forChatBroadcast) {
1447
+ names.splice(2);
1448
+ }
1449
+ names = names.filter((name) => name.length > 1);
1450
+ const shuffledNames = [...names];
1451
+ for (let index = shuffledNames.length - 1; index > 0; index -= 1) {
1452
+ const randomIndex = Math.floor(Math.random() * (index + 1));
1453
+ [shuffledNames[index], shuffledNames[randomIndex]] = [shuffledNames[randomIndex], shuffledNames[index]];
1454
+ }
1455
+ let hasLevel2Participant = false;
1456
+ for (let index = 0; index < shuffledNames.length; index += 1) {
1457
+ const randomName = shuffledNames[index];
1458
+ const randomLevel = hasLevel2Participant ? "1" : randomName === host ? "2" : "1";
1459
+ const randomMuted = forChatBroadcast ? true : Math.random() < 0.5;
1460
+ if (randomLevel === "2") {
1461
+ hasLevel2Participant = true;
1462
+ }
1463
+ participants.push({
1464
+ name: randomName,
1465
+ islevel: randomLevel,
1466
+ muted: randomMuted,
1467
+ id: index.toString(),
1468
+ audioID: `audio-${index}`,
1469
+ videoID: `video-${index}`
1470
+ });
1471
+ }
1472
+ return participants;
1473
+ };
1474
+ const generateRandomPolls = ({ numberOfPolls }) => {
1475
+ const pollTypes = ["trueFalse", "yesNo", "custom"];
1476
+ const polls = [];
1477
+ for (let index = 0; index < numberOfPolls; index += 1) {
1478
+ const type = pollTypes[Math.floor(Math.random() * pollTypes.length)];
1479
+ let options;
1480
+ switch (type) {
1481
+ case "trueFalse":
1482
+ options = ["True", "False"];
1483
+ break;
1484
+ case "yesNo":
1485
+ options = ["Yes", "No"];
1486
+ break;
1487
+ case "custom":
1488
+ options = Array.from({ length: Math.floor(Math.random() * 5) + 2 }, (_, optionIndex) => `Option ${optionIndex + 1}`);
1489
+ break;
1490
+ default:
1491
+ options = [];
1492
+ }
1493
+ polls.push({
1494
+ id: `${index + 1}`,
1495
+ question: `Random Question ${index + 1}`,
1496
+ type,
1497
+ options,
1498
+ votes: Array(options.length).fill(0),
1499
+ status: "inactive",
1500
+ voters: {}
1501
+ });
1502
+ }
1503
+ return polls;
1504
+ };
1505
+ const generateRandomRequestList = ({
1506
+ participants,
1507
+ hostName,
1508
+ coHostName,
1509
+ numberOfRequests
1510
+ }) => {
1511
+ const filteredParticipants = participants.filter(
1512
+ (participant) => participant.name !== hostName && participant.name !== coHostName
1513
+ );
1514
+ const requestIcons = ["fa-video", "fa-desktop", "fa-microphone"];
1515
+ for (let index = requestIcons.length - 1; index > 0; index -= 1) {
1516
+ const randomIndex = Math.floor(Math.random() * (index + 1));
1517
+ [requestIcons[index], requestIcons[randomIndex]] = [requestIcons[randomIndex], requestIcons[index]];
1518
+ }
1519
+ return filteredParticipants.flatMap((participant) => {
1520
+ const uniqueIcons = /* @__PURE__ */ new Set();
1521
+ const requests = [];
1522
+ for (let index = 0; index < numberOfRequests; index += 1) {
1523
+ let randomIcon;
1524
+ do {
1525
+ randomIcon = requestIcons[Math.floor(Math.random() * requestIcons.length)];
1526
+ } while (uniqueIcons.has(randomIcon));
1527
+ uniqueIcons.add(randomIcon);
1528
+ requests.push({
1529
+ id: participant.id || "",
1530
+ name: participant.name ? participant.name.toLowerCase().replace(/\s/g, "_") : "",
1531
+ icon: randomIcon,
1532
+ username: participant.name ? participant.name.toLowerCase().replace(/\s/g, "_") : ""
1533
+ });
1534
+ }
1535
+ return requests;
1536
+ });
1537
+ };
1538
+ const generateRandomWaitingRoomList = () => {
1539
+ const names = ["Dimen", "Nore", "Ker", "Lor", "Mik"];
1540
+ const waitingRoomList = [];
1541
+ for (let index = 0; index < names.length; index += 1) {
1542
+ waitingRoomList.push({
1543
+ name: names[index],
1544
+ id: index.toString()
1545
+ });
1546
+ }
1547
+ return waitingRoomList;
1548
+ };
1549
+ const initialValuesState = {
1550
+ // The following are the initial values
1551
+ roomName: "",
1552
+ member: "",
1553
+ adminPasscode: "",
1554
+ islevel: "1",
1555
+ coHost: "No coHost",
1556
+ coHostResponsibility: [
1557
+ { name: "participants", value: false, dedicated: false },
1558
+ { name: "media", value: false, dedicated: false },
1559
+ { name: "waiting", value: false, dedicated: false },
1560
+ { name: "chat", value: false, dedicated: false }
1561
+ ],
1562
+ youAreCoHost: false,
1563
+ youAreHost: false,
1564
+ confirmedToRecord: false,
1565
+ meetingDisplayType: "media",
1566
+ meetingVideoOptimized: false,
1567
+ eventType: "webinar",
1568
+ participants: [],
1569
+ filteredParticipants: [],
1570
+ participantsCounter: 0,
1571
+ participantsFilter: "",
1572
+ validated: false,
1573
+ localUIMode: false,
1574
+ socket: {},
1575
+ localSocket: void 0,
1576
+ roomData: null,
1577
+ device: null,
1578
+ apiKey: "",
1579
+ apiUserName: "",
1580
+ apiToken: "",
1581
+ link: "",
1582
+ consume_sockets: [],
1583
+ rtpCapabilities: null,
1584
+ roomRecvIPs: [],
1585
+ meetingRoomParams: null,
1586
+ itemPageLimit: 4,
1587
+ audioOnlyRoom: false,
1588
+ addForBasic: false,
1589
+ screenPageLimit: 4,
1590
+ shareScreenStarted: false,
1591
+ shared: false,
1592
+ targetOrientation: "landscape",
1593
+ targetResolution: "sd",
1594
+ targetResolutionHost: "sd",
1595
+ vidCons: { width: 640, height: 360 },
1596
+ frameRate: 10,
1597
+ hParams: {},
1598
+ vParams: {},
1599
+ screenParams: {},
1600
+ aParams: {},
1601
+ // Initial Values for New Recording Fields
1602
+ recordingAudioPausesLimit: 0,
1603
+ recordingAudioPausesCount: 0,
1604
+ recordingAudioSupport: false,
1605
+ recordingAudioPeopleLimit: 0,
1606
+ recordingAudioParticipantsTimeLimit: 0,
1607
+ recordingVideoPausesCount: 0,
1608
+ recordingVideoPausesLimit: 0,
1609
+ recordingVideoSupport: false,
1610
+ recordingVideoPeopleLimit: 0,
1611
+ recordingVideoParticipantsTimeLimit: 0,
1612
+ recordingAllParticipantsSupport: false,
1613
+ recordingVideoParticipantsSupport: false,
1614
+ recordingAllParticipantsFullRoomSupport: false,
1615
+ recordingVideoParticipantsFullRoomSupport: false,
1616
+ recordingPreferredOrientation: "landscape",
1617
+ recordingSupportForOtherOrientation: false,
1618
+ recordingMultiFormatsSupport: false,
1619
+ userRecordingParams: {
1620
+ mainSpecs: {
1621
+ mediaOptions: "video",
1622
+ audioOptions: "all",
1623
+ videoOptions: "all",
1624
+ videoType: "fullDisplay",
1625
+ videoOptimized: false,
1626
+ recordingDisplayType: "media",
1627
+ addHLS: false
1628
+ },
1629
+ dispSpecs: {
1630
+ nameTags: true,
1631
+ backgroundColor: "#000000",
1632
+ nameTagsColor: "#ffffff",
1633
+ orientationVideo: "portrait"
1634
+ }
1635
+ },
1636
+ canRecord: false,
1637
+ startReport: false,
1638
+ endReport: false,
1639
+ recordTimerInterval: null,
1640
+ recordStartTime: 0,
1641
+ recordElapsedTime: 0,
1642
+ isTimerRunning: false,
1643
+ canPauseResume: false,
1644
+ recordChangeSeconds: 15e3,
1645
+ pauseLimit: 0,
1646
+ pauseRecordCount: 0,
1647
+ canLaunchRecord: true,
1648
+ stopLaunchRecord: false,
1649
+ // Room properties
1650
+ participantsAll: [],
1651
+ firstAll: false,
1652
+ updateMainWindow: false,
1653
+ first_round: false,
1654
+ landScaped: false,
1655
+ lock_screen: false,
1656
+ screenId: "",
1657
+ allVideoStreams: [],
1658
+ newLimitedStreams: [],
1659
+ newLimitedStreamsIDs: [],
1660
+ activeSounds: [],
1661
+ screenShareIDStream: "",
1662
+ screenShareNameStream: "",
1663
+ adminIDStream: "",
1664
+ adminNameStream: "",
1665
+ youYouStream: [],
1666
+ youYouStreamIDs: [],
1667
+ localStream: null,
1668
+ recordStarted: false,
1669
+ recordResumed: false,
1670
+ recordPaused: false,
1671
+ recordStopped: false,
1672
+ adminRestrictSetting: false,
1673
+ videoRequestState: null,
1674
+ videoRequestTime: 0,
1675
+ videoAction: false,
1676
+ localStreamVideo: null,
1677
+ userDefaultVideoInputDevice: "",
1678
+ currentFacingMode: "user",
1679
+ prevFacingMode: "user",
1680
+ defVideoID: "",
1681
+ allowed: false,
1682
+ dispActiveNames: [],
1683
+ activeNames: [],
1684
+ prevActiveNames: [],
1685
+ p_activeNames: [],
1686
+ p_dispActiveNames: [],
1687
+ membersReceived: false,
1688
+ deferScreenReceived: false,
1689
+ hostFirstSwitch: false,
1690
+ micAction: false,
1691
+ screenAction: false,
1692
+ chatAction: false,
1693
+ audioRequestState: null,
1694
+ screenRequestState: null,
1695
+ chatRequestState: null,
1696
+ audioRequestTime: 0,
1697
+ screenRequestTime: 0,
1698
+ chatRequestTime: 0,
1699
+ updateRequestIntervalSeconds: 240,
1700
+ oldSoundIds: [],
1701
+ hostLabel: "Host",
1702
+ mainScreenFilled: false,
1703
+ localStreamScreen: null,
1704
+ screenAlreadyOn: false,
1705
+ chatAlreadyOn: false,
1706
+ redirectURL: "",
1707
+ oldAllStreams: [],
1708
+ adminVidID: "",
1709
+ streamNames: [],
1710
+ non_alVideoStreams: [],
1711
+ sortAudioLoudness: false,
1712
+ audioDecibels: [],
1713
+ mixed_alVideoStreams: [],
1714
+ non_alVideoStreams_muted: [],
1715
+ paginatedStreams: [],
1716
+ localStreamAudio: null,
1717
+ defAudioID: "",
1718
+ userDefaultAudioInputDevice: "",
1719
+ userDefaultAudioOutputDevice: "",
1720
+ prevAudioInputDevice: "",
1721
+ prevVideoInputDevice: "",
1722
+ audioPaused: false,
1723
+ mainScreenPerson: "",
1724
+ adminOnMainScreen: false,
1725
+ screenStates: [{
1726
+ mainScreenPerson: "",
1727
+ mainScreenProducerId: "",
1728
+ mainScreenFilled: false,
1729
+ adminOnMainScreen: false
1730
+ }],
1731
+ prevScreenStates: [{
1732
+ mainScreenPerson: "",
1733
+ mainScreenProducerId: "",
1734
+ mainScreenFilled: false,
1735
+ adminOnMainScreen: false
1736
+ }],
1737
+ updateDateState: null,
1738
+ lastUpdate: null,
1739
+ nForReadjustRecord: 0,
1740
+ fixedPageLimit: 4,
1741
+ removeAltGrid: false,
1742
+ nForReadjust: 0,
1743
+ reorderInterval: 3e4,
1744
+ fastReorderInterval: 1e4,
1745
+ lastReorderTime: 0,
1746
+ audStreamNames: [],
1747
+ currentUserPage: 0,
1748
+ mainHeightWidth: 0,
1749
+ prevMainHeightWidth: 0,
1750
+ prevDoPaginate: false,
1751
+ doPaginate: false,
1752
+ shareEnded: false,
1753
+ lStreams: [],
1754
+ chatRefStreams: [],
1755
+ controlHeight: 0,
1756
+ isWideScreen: false,
1757
+ isMediumScreen: false,
1758
+ isSmallScreen: false,
1759
+ addGrid: false,
1760
+ addAltGrid: false,
1761
+ gridRows: 0,
1762
+ gridCols: 0,
1763
+ altGridRows: 0,
1764
+ altGridCols: 0,
1765
+ numberPages: 0,
1766
+ currentStreams: [],
1767
+ showMiniView: false,
1768
+ nStream: null,
1769
+ defer_receive: false,
1770
+ allAudioStreams: [],
1771
+ remoteScreenStream: [],
1772
+ screenProducer: null,
1773
+ localScreenProducer: null,
1774
+ gotAllVids: false,
1775
+ paginationHeightWidth: 40,
1776
+ paginationDirection: "horizontal",
1777
+ gridSizes: {
1778
+ gridWidth: 0,
1779
+ gridHeight: 0,
1780
+ altGridWidth: 0,
1781
+ altGridHeight: 0
1782
+ },
1783
+ screenForceFullDisplay: false,
1784
+ mainGridStream: [],
1785
+ otherGridStreams: [[], []],
1786
+ audioOnlyStreams: [],
1787
+ videoInputs: [],
1788
+ audioInputs: [],
1789
+ meetingProgressTime: "00:00:00",
1790
+ meetingElapsedTime: 0,
1791
+ ref_participants: [],
1792
+ // Messaging, event, modals, and other UI states
1793
+ messages: [],
1794
+ startDirectMessage: false,
1795
+ directMessageDetails: null,
1796
+ showMessagesBadge: false,
1797
+ audioSetting: "allow",
1798
+ videoSetting: "allow",
1799
+ screenshareSetting: "allow",
1800
+ chatSetting: "allow",
1801
+ displayOption: "media",
1802
+ autoWave: true,
1803
+ forceFullDisplay: true,
1804
+ prevForceFullDisplay: false,
1805
+ prevMeetingDisplayType: "video",
1806
+ waitingRoomFilter: "",
1807
+ waitingRoomList: [],
1808
+ waitingRoomCounter: 0,
1809
+ filteredWaitingRoomList: [],
1810
+ requestFilter: "",
1811
+ requestList: [],
1812
+ requestCounter: 0,
1813
+ filteredRequestList: [],
1814
+ totalReqWait: 0,
1815
+ alertVisible: false,
1816
+ alertMessage: "",
1817
+ alertType: "success",
1818
+ alertDuration: 3e3,
1819
+ progressTimerVisible: true,
1820
+ progressTimerValue: 0,
1821
+ isMenuModalVisible: false,
1822
+ isRecordingModalVisible: false,
1823
+ isSettingsModalVisible: false,
1824
+ isRequestsModalVisible: false,
1825
+ isWaitingModalVisible: false,
1826
+ isCoHostModalVisible: false,
1827
+ isMediaSettingsModalVisible: false,
1828
+ isDisplaySettingsModalVisible: false,
1829
+ isParticipantsModalVisible: false,
1830
+ isMessagesModalVisible: false,
1831
+ isConfirmExitModalVisible: false,
1832
+ isConfirmHereModalVisible: false,
1833
+ isShareEventModalVisible: false,
1834
+ isLoadingModalVisible: false,
1835
+ recordingMediaOptions: "video",
1836
+ recordingAudioOptions: "all",
1837
+ recordingVideoOptions: "all",
1838
+ recordingVideoType: "fullDisplay",
1839
+ recordingVideoOptimized: false,
1840
+ recordingDisplayType: "video",
1841
+ recordingAddHLS: true,
1842
+ recordingNameTags: true,
1843
+ recordingBackgroundColor: "#83c0e9",
1844
+ recordingNameTagsColor: "#ffffff",
1845
+ recordingAddText: false,
1846
+ recordingCustomText: "Add Text",
1847
+ recordingCustomTextPosition: "top",
1848
+ recordingCustomTextColor: "#ffffff",
1849
+ recordingOrientationVideo: "landscape",
1850
+ clearedToResume: true,
1851
+ clearedToRecord: true,
1852
+ recordState: "green",
1853
+ showRecordButtons: false,
1854
+ recordingProgressTime: "00:00:00",
1855
+ audioSwitching: false,
1856
+ videoSwitching: false,
1857
+ videoAlreadyOn: false,
1858
+ audioAlreadyOn: false,
1859
+ componentSizes: {
1860
+ mainHeight: 0,
1861
+ otherHeight: 0,
1862
+ mainWidth: 0,
1863
+ otherWidth: 0
1864
+ },
1865
+ hasCameraPermission: false,
1866
+ hasAudioPermission: false,
1867
+ transportCreated: false,
1868
+ localTransportCreated: false,
1869
+ transportCreatedVideo: false,
1870
+ transportCreatedAudio: false,
1871
+ transportCreatedScreen: false,
1872
+ producerTransport: null,
1873
+ localProducerTransport: null,
1874
+ videoProducer: null,
1875
+ localVideoProducer: null,
1876
+ params: {},
1877
+ videoParams: {},
1878
+ audioParams: {},
1879
+ audioProducer: null,
1880
+ localAudioProducer: null,
1881
+ consumerTransports: [],
1882
+ consumingTransports: [],
1883
+ // Polls
1884
+ polls: [],
1885
+ poll: null,
1886
+ isPollModalVisible: false,
1887
+ // Background
1888
+ customImage: "",
1889
+ selectedImage: "",
1890
+ segmentVideo: null,
1891
+ selfieSegmentation: null,
1892
+ pauseSegmentation: false,
1893
+ processedStream: null,
1894
+ keepBackground: false,
1895
+ backgroundHasChanged: false,
1896
+ virtualStream: null,
1897
+ mainCanvas: null,
1898
+ prevKeepBackground: false,
1899
+ appliedBackground: false,
1900
+ isBackgroundModalVisible: false,
1901
+ autoClickBackground: false,
1902
+ // Breakout Rooms
1903
+ breakoutRooms: [],
1904
+ currentRoomIndex: 0,
1905
+ canStartBreakout: false,
1906
+ breakOutRoomStarted: false,
1907
+ breakOutRoomEnded: false,
1908
+ hostNewRoom: -1,
1909
+ limitedBreakRoom: [],
1910
+ mainRoomsLength: 0,
1911
+ memberRoom: -1,
1912
+ isBreakoutRoomsModalVisible: false,
1913
+ // Whiteboard
1914
+ whiteboardUsers: [],
1915
+ currentWhiteboardIndex: 0,
1916
+ canStartWhiteboard: false,
1917
+ whiteboardStarted: false,
1918
+ whiteboardEnded: false,
1919
+ whiteboardLimit: 4,
1920
+ isWhiteboardModalVisible: false,
1921
+ isConfigureWhiteboardModalVisible: false,
1922
+ shapes: [],
1923
+ useImageBackground: true,
1924
+ redoStack: [],
1925
+ undoStack: [],
1926
+ canvasStream: null,
1927
+ canvasWhiteboard: null,
1928
+ // Screenboard
1929
+ canvasScreenboard: null,
1930
+ processedScreenStream: null,
1931
+ annotateScreenStream: false,
1932
+ mainScreenCanvas: null,
1933
+ isScreenboardModalVisible: false,
1934
+ // Control Buttons
1935
+ micActive: false,
1936
+ videoActive: false,
1937
+ screenShareActive: false,
1938
+ endCallActive: false,
1939
+ participantsActive: false,
1940
+ menuActive: false,
1941
+ commentsActive: false
1942
+ };
1943
+ const mediaDevices = {
1944
+ getUserMedia: async (_constraints) => {
1945
+ console.warn("getUserMedia is not implemented in this environment.");
1946
+ return new MediaStream();
1947
+ },
1948
+ getDisplayMedia: async (_constraints) => {
1949
+ console.warn("getDisplayMedia is not implemented in this environment.");
1950
+ return new MediaStream();
1951
+ },
1952
+ enumerateDevices: async () => {
1953
+ console.warn("enumerateDevices is not implemented in this environment.");
1954
+ return [];
1955
+ }
1956
+ };
1957
+ function registerGlobals() {
1958
+ }
1959
+ class MediaStream {
1960
+ tracks;
1961
+ constructor(tracks = []) {
1962
+ this.tracks = tracks;
1963
+ }
1964
+ }
1965
+ class MediaStreamTrack {
1966
+ }
1967
+ class RTCView {
1968
+ render() {
1969
+ return null;
1970
+ }
1971
+ }
1972
+ const createResponseJoinRoom = async ({
1973
+ localRoom
1974
+ }) => {
1975
+ return {
1976
+ rtpCapabilities: localRoom.rtpCapabilities ?? null,
1977
+ success: localRoom.rtpCapabilities !== null,
1978
+ roomRecvIPs: [],
1979
+ meetingRoomParams: localRoom.eventRoomParams,
1980
+ recordingParams: localRoom.recordingParams,
1981
+ secureCode: localRoom.secureCode,
1982
+ recordOnly: false,
1983
+ isHost: localRoom.isHost,
1984
+ safeRoom: false,
1985
+ autoStartSafeRoom: false,
1986
+ safeRoomStarted: false,
1987
+ safeRoomEnded: false,
1988
+ reason: localRoom.isBanned ? "User is banned from the room." : void 0,
1989
+ banned: localRoom.isBanned,
1990
+ suspended: false,
1991
+ noAdmin: localRoom.hostNotJoined
1992
+ };
1993
+ };
1994
+ const readResponseError = async (response) => {
1995
+ const fallbackMessage = `HTTP error! Status: ${response.status}`;
1996
+ try {
1997
+ const responseText = await response.text();
1998
+ if (!responseText) {
1999
+ return fallbackMessage;
2000
+ }
2001
+ const parsedResponse = JSON.parse(responseText);
2002
+ return parsedResponse.error || parsedResponse.message || responseText;
2003
+ } catch {
2004
+ return fallbackMessage;
2005
+ }
2006
+ };
2007
+ const createBrowserPendingRequestStorage = () => {
2008
+ if (typeof localStorage === "undefined") {
2009
+ return void 0;
2010
+ }
2011
+ return {
2012
+ getItem: async (key) => localStorage.getItem(key),
2013
+ setItem: async (key, value) => {
2014
+ localStorage.setItem(key, value);
2015
+ },
2016
+ removeItem: async (key) => {
2017
+ localStorage.removeItem(key);
2018
+ }
2019
+ };
2020
+ };
2021
+ const createRoomOnMediaSFU = async ({
2022
+ payload,
2023
+ apiUserName,
2024
+ apiKey,
2025
+ localLink = "",
2026
+ pendingRequestStorage
2027
+ }) => {
2028
+ const storage = pendingRequestStorage ?? createBrowserPendingRequestStorage();
2029
+ const roomIdentifier = `create_${payload.userName}_${payload.duration}_${payload.capacity}`;
2030
+ const pendingKey = `mediasfu_pending_${roomIdentifier}`;
2031
+ const pendingTimeout = 30 * 1e3;
2032
+ try {
2033
+ const pendingRequest = storage ? await storage.getItem(pendingKey) : null;
2034
+ if (storage && pendingRequest) {
2035
+ const pendingData = JSON.parse(pendingRequest);
2036
+ const timeSincePending = Date.now() - pendingData.timestamp;
2037
+ if (timeSincePending < pendingTimeout) {
2038
+ return {
2039
+ data: { error: "Room creation already in progress" },
2040
+ success: false
2041
+ };
2042
+ }
2043
+ await storage.removeItem(pendingKey);
2044
+ }
2045
+ if (!apiUserName || !apiKey || apiUserName === "yourAPIUSERNAME" || apiKey === "yourAPIKEY" || apiKey.length !== 64 || apiUserName.length < 6) {
2046
+ return { data: { error: "Invalid credentials" }, success: false };
2047
+ }
2048
+ const finalLink = resolveMediaSFURoomApi(localLink, "createRoom");
2049
+ if (storage) {
2050
+ await storage.setItem(pendingKey, JSON.stringify({
2051
+ timestamp: Date.now(),
2052
+ payload: {
2053
+ action: payload.action,
2054
+ userName: payload.userName,
2055
+ meetingID: "create"
2056
+ }
2057
+ }));
2058
+ setTimeout(() => {
2059
+ storage.removeItem(pendingKey).catch(() => {
2060
+ });
2061
+ }, pendingTimeout);
2062
+ }
2063
+ const response = await fetch(finalLink, {
2064
+ method: "POST",
2065
+ headers: {
2066
+ "Content-Type": "application/json",
2067
+ Authorization: `Bearer ${apiUserName}:${apiKey}`
2068
+ },
2069
+ body: JSON.stringify(payload)
2070
+ });
2071
+ if (!response.ok) {
2072
+ throw new Error(await readResponseError(response));
2073
+ }
2074
+ const data = await response.json();
2075
+ if (storage) {
2076
+ await storage.removeItem(pendingKey);
2077
+ }
2078
+ return { data, success: true };
2079
+ } catch (error) {
2080
+ if (storage) {
2081
+ try {
2082
+ await storage.removeItem(pendingKey);
2083
+ } catch {
2084
+ }
2085
+ }
2086
+ const errorMessage = error.message || "unknown error";
2087
+ return {
2088
+ data: { error: `Unable to create room, ${errorMessage}` },
2089
+ success: false
2090
+ };
2091
+ }
2092
+ };
2093
+ function startMeetingProgressTimer({
2094
+ startTime,
2095
+ parameters
2096
+ }) {
2097
+ let { updateMeetingProgressTime, getUpdatedAllParams } = parameters;
2098
+ function calculateElapsedTime(currentStartTime) {
2099
+ const currentTime = Math.floor((/* @__PURE__ */ new Date()).getTime() / 1e3);
2100
+ return currentTime - currentStartTime;
2101
+ }
2102
+ function padNumber2(value) {
2103
+ return value.toString().padStart(2, "0");
2104
+ }
2105
+ function formatTime(time) {
2106
+ const hours = Math.floor(time / 3600);
2107
+ const minutes = Math.floor(time % 3600 / 60);
2108
+ const seconds = Math.floor(time % 60);
2109
+ return `${padNumber2(hours)}:${padNumber2(minutes)}:${padNumber2(seconds)}`;
2110
+ }
2111
+ let elapsedTime = calculateElapsedTime(startTime);
2112
+ let timeProgress = setInterval(() => {
2113
+ elapsedTime++;
2114
+ updateMeetingProgressTime(formatTime(elapsedTime));
2115
+ parameters = getUpdatedAllParams();
2116
+ if (!parameters.validated || !parameters.roomName) {
2117
+ clearInterval(timeProgress);
2118
+ timeProgress = null;
2119
+ }
2120
+ }, 1e3);
2121
+ }
2122
+ const meetingTimeRemaining = async ({
2123
+ timeRemaining,
2124
+ showAlert,
2125
+ eventType
2126
+ }) => {
2127
+ const minutes = Math.floor(timeRemaining / 6e4);
2128
+ const seconds = Math.floor(timeRemaining % 6e4 / 1e3);
2129
+ const timeRemainingString = `${minutes}:${seconds < 10 ? "0" : ""}${seconds}`;
2130
+ if (eventType !== "chat") {
2131
+ showAlert?.({
2132
+ message: `The event will end in ${timeRemainingString} minutes.`,
2133
+ type: "success",
2134
+ duration: 3e3
2135
+ });
2136
+ }
2137
+ };
2138
+ const allWaitingRoomMembers = async ({
2139
+ waitingParticipants,
2140
+ updateWaitingRoomList,
2141
+ updateTotalReqWait
2142
+ }) => {
2143
+ updateWaitingRoomList(waitingParticipants);
2144
+ updateTotalReqWait(waitingParticipants.length);
2145
+ };
2146
+ const allMembers = async ({
2147
+ members,
2148
+ requestss,
2149
+ coHoste,
2150
+ coHostRes,
2151
+ parameters,
2152
+ consume_sockets,
2153
+ apiUserName,
2154
+ apiKey,
2155
+ apiToken
2156
+ }) => {
2157
+ let {
2158
+ participantsAll,
2159
+ participants,
2160
+ dispActiveNames,
2161
+ requestList,
2162
+ lock_screen,
2163
+ firstAll,
2164
+ membersReceived,
2165
+ roomRecvIPs,
2166
+ deferScreenReceived,
2167
+ screenId,
2168
+ shareScreenStarted,
2169
+ meetingDisplayType,
2170
+ hostFirstSwitch,
2171
+ waitingRoomList,
2172
+ islevel,
2173
+ socket,
2174
+ updateParticipantsAll,
2175
+ updateParticipants,
2176
+ updateRequestList,
2177
+ updateCoHost,
2178
+ updateCoHostResponsibility,
2179
+ updateFirstAll,
2180
+ updateMembersReceived,
2181
+ updateDeferScreenReceived,
2182
+ updateShareScreenStarted,
2183
+ updateHostFirstSwitch,
2184
+ updateConsume_sockets,
2185
+ updateRoomRecvIPs,
2186
+ updateIsLoadingModalVisible,
2187
+ updateTotalReqWait,
2188
+ onScreenChanges,
2189
+ connectIps,
2190
+ connectLocalIps,
2191
+ sleep: sleep2,
2192
+ reorderStreams
2193
+ } = parameters;
2194
+ participantsAll = members.map(({ isBanned, isSuspended, name, audioID, videoID }) => ({
2195
+ isBanned,
2196
+ isSuspended,
2197
+ name,
2198
+ audioID,
2199
+ videoID
2200
+ }));
2201
+ updateParticipantsAll(participantsAll);
2202
+ participants = members.filter(
2203
+ (participant) => !participant.isBanned && !participant.isSuspended
2204
+ );
2205
+ updateParticipants(participants);
2206
+ if (dispActiveNames.length > 0) {
2207
+ const missingDisplayedParticipants = dispActiveNames.filter(
2208
+ (name) => !participants.some((participant) => participant.name === name)
2209
+ );
2210
+ if (missingDisplayedParticipants.length > 0) {
2211
+ await reorderStreams({ add: false, screenChanged: true, parameters });
2212
+ }
2213
+ }
2214
+ const onLocal = roomRecvIPs.length === 1 && roomRecvIPs[0] === "none";
2215
+ if (!membersReceived && !onLocal) {
2216
+ if (roomRecvIPs.length < 1) {
2217
+ const checkIPs = setInterval(async () => {
2218
+ if (roomRecvIPs.length > 0) {
2219
+ clearInterval(checkIPs);
2220
+ if (deferScreenReceived && screenId) {
2221
+ shareScreenStarted = true;
2222
+ updateShareScreenStarted(shareScreenStarted);
2223
+ }
2224
+ const [sockets_, ips_] = await connectIps({
2225
+ consume_sockets,
2226
+ remIP: roomRecvIPs,
2227
+ parameters,
2228
+ apiUserName,
2229
+ apiKey,
2230
+ apiToken
2231
+ });
2232
+ updateConsume_sockets(sockets_);
2233
+ updateRoomRecvIPs(ips_);
2234
+ membersReceived = true;
2235
+ updateMembersReceived(membersReceived);
2236
+ await sleep2({ ms: 250 });
2237
+ updateIsLoadingModalVisible(false);
2238
+ deferScreenReceived = false;
2239
+ updateDeferScreenReceived(deferScreenReceived);
2240
+ }
2241
+ }, 10);
2242
+ } else {
2243
+ const [sockets_, ips_] = await connectIps({
2244
+ consume_sockets,
2245
+ remIP: roomRecvIPs,
2246
+ parameters,
2247
+ apiUserName,
2248
+ apiKey,
2249
+ apiToken
2250
+ });
2251
+ updateConsume_sockets(sockets_);
2252
+ updateRoomRecvIPs(ips_);
2253
+ membersReceived = true;
2254
+ updateMembersReceived(membersReceived);
2255
+ if (deferScreenReceived && screenId) {
2256
+ shareScreenStarted = true;
2257
+ updateShareScreenStarted(shareScreenStarted);
2258
+ }
2259
+ await sleep2({ ms: 250 });
2260
+ updateIsLoadingModalVisible(false);
2261
+ deferScreenReceived = false;
2262
+ updateDeferScreenReceived(deferScreenReceived);
2263
+ }
2264
+ }
2265
+ if (onLocal && !membersReceived) {
2266
+ if (connectLocalIps) {
2267
+ await connectLocalIps({ socket, parameters });
2268
+ }
2269
+ await sleep2({ ms: 50 });
2270
+ updateIsLoadingModalVisible(false);
2271
+ }
2272
+ requestList = requestss.filter(
2273
+ (request) => participants.some((participant) => participant.id === request.id)
2274
+ );
2275
+ updateRequestList(requestList);
2276
+ updateTotalReqWait(requestList.length + waitingRoomList.length);
2277
+ updateCoHost(coHoste);
2278
+ updateCoHostResponsibility(coHostRes);
2279
+ if (!lock_screen && !firstAll) {
2280
+ await onScreenChanges({ parameters });
2281
+ if (meetingDisplayType !== "all") {
2282
+ updateFirstAll(true);
2283
+ }
2284
+ } else if (islevel === "2" && !hostFirstSwitch) {
2285
+ await onScreenChanges({ parameters });
2286
+ updateHostFirstSwitch(true);
2287
+ }
2288
+ };
2289
+ const allMembersRest = async ({
2290
+ members,
2291
+ settings,
2292
+ coHoste,
2293
+ coHostRes,
2294
+ parameters,
2295
+ consume_sockets,
2296
+ apiUserName,
2297
+ apiKey,
2298
+ apiToken
2299
+ }) => {
2300
+ let {
2301
+ participantsAll,
2302
+ participants,
2303
+ dispActiveNames,
2304
+ requestList,
2305
+ coHost,
2306
+ coHostResponsibility,
2307
+ lock_screen,
2308
+ firstAll,
2309
+ membersReceived,
2310
+ roomRecvIPs,
2311
+ deferScreenReceived,
2312
+ screenId,
2313
+ shareScreenStarted,
2314
+ meetingDisplayType,
2315
+ audioSetting,
2316
+ videoSetting,
2317
+ screenshareSetting,
2318
+ chatSetting,
2319
+ socket,
2320
+ updateParticipantsAll,
2321
+ updateParticipants,
2322
+ updateRequestList,
2323
+ updateCoHost,
2324
+ updateCoHostResponsibility,
2325
+ updateFirstAll,
2326
+ updateMembersReceived,
2327
+ updateDeferScreenReceived,
2328
+ updateShareScreenStarted,
2329
+ updateAudioSetting,
2330
+ updateVideoSetting,
2331
+ updateScreenshareSetting,
2332
+ updateChatSetting,
2333
+ updateConsume_sockets,
2334
+ updateRoomRecvIPs,
2335
+ updateIsLoadingModalVisible,
2336
+ onScreenChanges,
2337
+ connectIps,
2338
+ connectLocalIps,
2339
+ sleep: sleep2,
2340
+ reorderStreams
2341
+ } = parameters;
2342
+ participantsAll = members.map((participant) => ({
2343
+ isBanned: participant.isBanned,
2344
+ isSuspended: participant.isSuspended,
2345
+ name: participant.name,
2346
+ audioID: participant.audioID,
2347
+ videoID: participant.videoID
2348
+ }));
2349
+ updateParticipantsAll(participantsAll);
2350
+ participants = members.filter(
2351
+ (participant) => !participant.isBanned && !participant.isSuspended
2352
+ );
2353
+ updateParticipants(participants);
2354
+ if (dispActiveNames.length > 0) {
2355
+ const missingDisplayedParticipants = dispActiveNames.filter(
2356
+ (name) => !participants.some((participant) => participant.name === name)
2357
+ );
2358
+ if (missingDisplayedParticipants.length > 0 && membersReceived) {
2359
+ await reorderStreams({ add: false, screenChanged: true, parameters });
2360
+ }
2361
+ }
2362
+ const onLocal = roomRecvIPs.length === 1 && roomRecvIPs[0] === "none";
2363
+ if (!onLocal) {
2364
+ if (!membersReceived) {
2365
+ if (roomRecvIPs.length < 1) {
2366
+ const checkIPs = setInterval(async () => {
2367
+ if (roomRecvIPs.length > 0) {
2368
+ clearInterval(checkIPs);
2369
+ if (deferScreenReceived && screenId) {
2370
+ shareScreenStarted = true;
2371
+ updateShareScreenStarted(shareScreenStarted);
2372
+ }
2373
+ const [sockets_, ips_] = await connectIps({
2374
+ consume_sockets,
2375
+ remIP: roomRecvIPs,
2376
+ parameters,
2377
+ apiUserName,
2378
+ apiKey,
2379
+ apiToken
2380
+ });
2381
+ if (sockets_ && ips_) {
2382
+ updateConsume_sockets(sockets_);
2383
+ updateRoomRecvIPs(ips_);
2384
+ }
2385
+ membersReceived = true;
2386
+ updateMembersReceived(membersReceived);
2387
+ await sleep2({ ms: 250 });
2388
+ updateIsLoadingModalVisible(false);
2389
+ deferScreenReceived = false;
2390
+ updateDeferScreenReceived(deferScreenReceived);
2391
+ }
2392
+ }, 10);
2393
+ } else {
2394
+ const [sockets_, ips_] = await connectIps({
2395
+ consume_sockets,
2396
+ remIP: roomRecvIPs,
2397
+ parameters,
2398
+ apiUserName,
2399
+ apiKey,
2400
+ apiToken
2401
+ });
2402
+ if (sockets_ && ips_) {
2403
+ updateConsume_sockets(sockets_);
2404
+ updateRoomRecvIPs(ips_);
2405
+ }
2406
+ membersReceived = true;
2407
+ updateMembersReceived(membersReceived);
2408
+ if (deferScreenReceived && screenId) {
2409
+ shareScreenStarted = true;
2410
+ updateShareScreenStarted(shareScreenStarted);
2411
+ }
2412
+ await sleep2({ ms: 250 });
2413
+ updateIsLoadingModalVisible(false);
2414
+ deferScreenReceived = false;
2415
+ updateDeferScreenReceived(deferScreenReceived);
2416
+ }
2417
+ } else if (screenId) {
2418
+ const host = participants.find(
2419
+ (participant) => participant.ScreenID === screenId && participant.ScreenOn === true
2420
+ );
2421
+ if (deferScreenReceived && host) {
2422
+ shareScreenStarted = true;
2423
+ updateShareScreenStarted(shareScreenStarted);
2424
+ }
2425
+ }
2426
+ }
2427
+ if (onLocal && !membersReceived) {
2428
+ if (connectLocalIps) {
2429
+ await connectLocalIps({ socket, parameters });
2430
+ }
2431
+ await sleep2({ ms: 50 });
2432
+ updateIsLoadingModalVisible(false);
2433
+ }
2434
+ requestList = requestList.filter(
2435
+ (request) => participants.some((participant) => participant.id === request.id)
2436
+ );
2437
+ updateRequestList(requestList);
2438
+ coHost = coHoste;
2439
+ updateCoHost(coHost);
2440
+ coHostResponsibility = coHostRes;
2441
+ updateCoHostResponsibility(coHostResponsibility);
2442
+ if (!lock_screen && !firstAll) {
2443
+ await onScreenChanges({ parameters });
2444
+ if (meetingDisplayType !== "all") {
2445
+ firstAll = true;
2446
+ updateFirstAll(firstAll);
2447
+ }
2448
+ }
2449
+ try {
2450
+ if (membersReceived) {
2451
+ [audioSetting, videoSetting, screenshareSetting, chatSetting] = settings;
2452
+ updateAudioSetting(audioSetting);
2453
+ updateVideoSetting(videoSetting);
2454
+ updateScreenshareSetting(screenshareSetting);
2455
+ updateChatSetting(chatSetting);
2456
+ }
2457
+ } catch {
2458
+ }
2459
+ };
2460
+ const banParticipant = async ({
2461
+ name,
2462
+ parameters
2463
+ }) => {
2464
+ const {
2465
+ activeNames,
2466
+ dispActiveNames,
2467
+ participants,
2468
+ updateParticipants,
2469
+ reorderStreams
2470
+ } = parameters;
2471
+ if (activeNames.includes(name) || dispActiveNames.includes(name)) {
2472
+ updateParticipants(
2473
+ participants.filter((participant) => participant.name !== name)
2474
+ );
2475
+ await reorderStreams({ add: false, screenChanged: true, parameters });
2476
+ }
2477
+ };
2478
+ const controlMediaHost = async ({
2479
+ type,
2480
+ parameters
2481
+ }) => {
2482
+ const {
2483
+ updateAdminRestrictSetting,
2484
+ updateLocalStream,
2485
+ updateAudioAlreadyOn,
2486
+ updateLocalStreamScreen,
2487
+ updateLocalStreamVideo,
2488
+ updateScreenAlreadyOn,
2489
+ updateVideoAlreadyOn,
2490
+ updateChatAlreadyOn,
2491
+ onScreenChanges,
2492
+ stopShareScreen,
2493
+ disconnectSendTransportVideo,
2494
+ disconnectSendTransportAudio,
2495
+ disconnectSendTransportScreen
2496
+ } = parameters;
2497
+ const { localStream, localStreamScreen, localStreamVideo } = parameters.getUpdatedAllParams();
2498
+ const disableTrack = (stream, kind) => {
2499
+ const getTracks = kind === "audio" ? stream?.getAudioTracks : stream?.getVideoTracks;
2500
+ const tracks = typeof getTracks === "function" ? getTracks.call(stream) : stream?.tracks?.filter((track2) => track2.kind === kind) ?? [];
2501
+ const track = tracks && tracks[0];
2502
+ if (track) {
2503
+ track.enabled = false;
2504
+ return true;
2505
+ }
2506
+ return false;
2507
+ };
2508
+ try {
2509
+ updateAdminRestrictSetting(true);
2510
+ if (type === "audio") {
2511
+ disableTrack(localStream, "audio");
2512
+ updateLocalStream(localStream ?? null);
2513
+ await disconnectSendTransportAudio({ parameters });
2514
+ updateAudioAlreadyOn(false);
2515
+ } else if (type === "video") {
2516
+ disableTrack(localStream, "video");
2517
+ updateLocalStream(localStream ?? null);
2518
+ await disconnectSendTransportVideo({ parameters });
2519
+ await onScreenChanges({ changed: true, parameters });
2520
+ disableTrack(localStreamVideo, "video");
2521
+ updateLocalStreamVideo(localStreamVideo ?? null);
2522
+ await disconnectSendTransportVideo({ parameters });
2523
+ await onScreenChanges({ changed: true, parameters });
2524
+ updateVideoAlreadyOn(false);
2525
+ } else if (type === "screenshare") {
2526
+ disableTrack(localStreamScreen, "video");
2527
+ updateLocalStreamScreen(localStreamScreen ?? null);
2528
+ await disconnectSendTransportScreen({ parameters });
2529
+ await stopShareScreen({ parameters });
2530
+ updateScreenAlreadyOn(false);
2531
+ } else if (type === "chat") {
2532
+ updateChatAlreadyOn(false);
2533
+ } else if (type === "all") {
2534
+ disableTrack(localStream, "audio");
2535
+ updateLocalStream(localStream ?? null);
2536
+ await disconnectSendTransportAudio({ parameters });
2537
+ updateAudioAlreadyOn(false);
2538
+ disableTrack(localStreamScreen, "video");
2539
+ updateLocalStreamScreen(localStreamScreen ?? null);
2540
+ await disconnectSendTransportScreen({ parameters });
2541
+ await stopShareScreen({ parameters });
2542
+ updateScreenAlreadyOn(false);
2543
+ disableTrack(localStream, "video");
2544
+ updateLocalStream(localStream ?? null);
2545
+ await disconnectSendTransportVideo({ parameters });
2546
+ await onScreenChanges({ changed: true, parameters });
2547
+ disableTrack(localStreamVideo, "video");
2548
+ updateLocalStreamVideo(localStreamVideo ?? null);
2549
+ await disconnectSendTransportVideo({ parameters });
2550
+ await onScreenChanges({ changed: true, parameters });
2551
+ updateVideoAlreadyOn(false);
2552
+ }
2553
+ } catch (error) {
2554
+ console.error("Error in controlMediaHost:", error);
2555
+ }
2556
+ };
2557
+ const disconnect = async ({
2558
+ showAlert,
2559
+ redirectURL,
2560
+ onWeb
2561
+ }) => {
2562
+ if (onWeb && redirectURL && typeof window !== "undefined") {
2563
+ window.location.href = redirectURL;
2564
+ } else {
2565
+ showAlert?.({
2566
+ message: "You have been disconnected from the session.",
2567
+ type: "danger",
2568
+ duration: 2e3
2569
+ });
2570
+ }
2571
+ };
2572
+ async function disconnectUserSelf({
2573
+ member,
2574
+ roomName,
2575
+ socket,
2576
+ localSocket
2577
+ }) {
2578
+ socket.emit("disconnectUser", {
2579
+ member,
2580
+ roomName,
2581
+ ban: true
2582
+ });
2583
+ try {
2584
+ if (localSocket?.id) {
2585
+ localSocket.emit("disconnectUser", {
2586
+ member,
2587
+ roomName,
2588
+ ban: true
2589
+ });
2590
+ }
2591
+ } catch {
2592
+ }
2593
+ }
2594
+ const getDomains = async ({
2595
+ domains,
2596
+ alt_domains,
2597
+ apiUserName,
2598
+ apiKey,
2599
+ apiToken,
2600
+ parameters
2601
+ }) => {
2602
+ let { roomRecvIPs, consume_sockets, connectIps } = parameters;
2603
+ const ipsToConnect = [];
2604
+ try {
2605
+ consume_sockets = parameters.getUpdatedAllParams().consume_sockets;
2606
+ for (const domain of domains) {
2607
+ const ipToCheck = alt_domains[domain] || domain;
2608
+ if (!roomRecvIPs.includes(ipToCheck)) {
2609
+ ipsToConnect.push(ipToCheck);
2610
+ }
2611
+ }
2612
+ await connectIps({
2613
+ consume_sockets,
2614
+ remIP: ipsToConnect,
2615
+ parameters,
2616
+ apiUserName,
2617
+ apiKey,
2618
+ apiToken
2619
+ });
2620
+ } catch (error) {
2621
+ console.error("Error in getDomains: ", error);
2622
+ }
2623
+ };
2624
+ const meetingEnded = async ({
2625
+ showAlert,
2626
+ redirectURL,
2627
+ onWeb,
2628
+ eventType
2629
+ }) => {
2630
+ if (eventType !== "chat") {
2631
+ showAlert?.({
2632
+ message: "The event has ended. You will be redirected to the home page in 2 seconds.",
2633
+ type: "danger",
2634
+ duration: 2e3
2635
+ });
2636
+ }
2637
+ if (onWeb && redirectURL) {
2638
+ setTimeout(() => {
2639
+ window.location.href = redirectURL;
2640
+ }, 2e3);
2641
+ }
2642
+ };
2643
+ const meetingStillThere = async ({
2644
+ updateIsConfirmHereModalVisible
2645
+ }) => {
2646
+ updateIsConfirmHereModalVisible(true);
2647
+ };
2648
+ const panelistsUpdated = async ({
2649
+ data,
2650
+ updatePanelists: updatePanelists2
2651
+ }) => {
2652
+ try {
2653
+ const { panelists } = data;
2654
+ if (updatePanelists2) {
2655
+ updatePanelists2(
2656
+ panelists.map((panelist) => ({
2657
+ id: panelist.id,
2658
+ name: panelist.name,
2659
+ audioID: "",
2660
+ videoID: ""
2661
+ }))
2662
+ );
2663
+ }
2664
+ } catch (error) {
2665
+ console.error("Error handling panelistsUpdated:", error);
2666
+ }
2667
+ };
2668
+ const panelistFocusChanged = async ({
2669
+ data,
2670
+ updatePanelistsFocused,
2671
+ updateMuteOthersMic,
2672
+ updateMuteOthersCamera,
2673
+ updatePanelists: updatePanelists2,
2674
+ currentPanelistsFocused,
2675
+ currentPanelists,
2676
+ onScreenChanges
2677
+ }) => {
2678
+ try {
2679
+ const { focusEnabled, panelists, muteOthersMic, muteOthersCamera } = data;
2680
+ const focusChanged = currentPanelistsFocused !== void 0 && currentPanelistsFocused !== focusEnabled;
2681
+ const currentPanelistIds = (currentPanelists || []).map((panelist) => panelist.id).sort().join(",");
2682
+ const newPanelistIds = panelists.map((panelist) => panelist.id).sort().join(",");
2683
+ const panelistsChanged = currentPanelistIds !== newPanelistIds;
2684
+ updatePanelistsFocused?.(focusEnabled);
2685
+ updateMuteOthersMic?.(muteOthersMic);
2686
+ updateMuteOthersCamera?.(muteOthersCamera);
2687
+ if (updatePanelists2) {
2688
+ updatePanelists2(
2689
+ panelists.map((panelist) => ({
2690
+ id: panelist.id,
2691
+ name: panelist.name,
2692
+ audioID: "",
2693
+ videoID: ""
2694
+ }))
2695
+ );
2696
+ }
2697
+ if ((focusChanged || panelistsChanged) && onScreenChanges) {
2698
+ await onScreenChanges();
2699
+ }
2700
+ } catch (error) {
2701
+ console.error("Error handling panelistFocusChanged:", error);
2702
+ }
2703
+ };
2704
+ const panelistControlMedia = async ({
2705
+ data,
2706
+ showAlert,
2707
+ clickAudio,
2708
+ clickVideo,
2709
+ audioAlreadyOn,
2710
+ videoAlreadyOn
2711
+ }) => {
2712
+ try {
2713
+ const { type, action, reason } = data;
2714
+ if (action === "mute") {
2715
+ if (type === "audio" && audioAlreadyOn && clickAudio) {
2716
+ clickAudio();
2717
+ } else if (type === "video" && videoAlreadyOn && clickVideo) {
2718
+ clickVideo();
2719
+ }
2720
+ if (showAlert && reason) {
2721
+ showAlert({
2722
+ message: `Your ${type === "audio" ? "microphone" : "camera"} has been muted. ${reason}`,
2723
+ type: "info",
2724
+ duration: 3e3
2725
+ });
2726
+ }
2727
+ }
2728
+ } catch (error) {
2729
+ console.error("Error handling controlMedia:", error);
2730
+ }
2731
+ };
2732
+ const addedAsPanelist = async ({
2733
+ data,
2734
+ showAlert
2735
+ }) => {
2736
+ try {
2737
+ showAlert?.({
2738
+ message: data.message || "You have been added as a panelist",
2739
+ type: "success",
2740
+ duration: 3e3
2741
+ });
2742
+ } catch (error) {
2743
+ console.error("Error handling addedAsPanelist:", error);
2744
+ }
2745
+ };
2746
+ const removedFromPanelists = async ({
2747
+ data,
2748
+ showAlert
2749
+ }) => {
2750
+ try {
2751
+ showAlert?.({
2752
+ message: data.message || "You have been removed from panelists",
2753
+ type: "info",
2754
+ duration: 3e3
2755
+ });
2756
+ } catch (error) {
2757
+ console.error("Error handling removedFromPanelists:", error);
2758
+ }
2759
+ };
2760
+ const participantRequested = async ({
2761
+ userRequest,
2762
+ requestList,
2763
+ waitingRoomList,
2764
+ updateTotalReqWait,
2765
+ updateRequestList
2766
+ }) => {
2767
+ const hasMatchingRequest = requestList.some(
2768
+ (request) => request.id === userRequest.id && request.icon === userRequest.icon
2769
+ );
2770
+ const updatedRequestList = hasMatchingRequest ? requestList : [...requestList, userRequest];
2771
+ updateRequestList(updatedRequestList);
2772
+ updateTotalReqWait(updatedRequestList.length + waitingRoomList.length);
2773
+ };
2774
+ const permissionUpdated = async ({
2775
+ data,
2776
+ showAlert,
2777
+ updateIslevel
2778
+ }) => {
2779
+ try {
2780
+ const { newLevel, message } = data;
2781
+ updateIslevel?.(newLevel);
2782
+ if (showAlert && message) {
2783
+ showAlert({
2784
+ message,
2785
+ type: newLevel === "1" ? "success" : "info",
2786
+ duration: 3e3
2787
+ });
2788
+ }
2789
+ } catch (error) {
2790
+ console.error("Error handling permissionUpdated:", error);
2791
+ }
2792
+ };
2793
+ const permissionConfigUpdated = async ({
2794
+ data,
2795
+ updatePermissionConfig: updatePermissionConfig2
2796
+ }) => {
2797
+ try {
2798
+ updatePermissionConfig2?.(data.config);
2799
+ } catch (error) {
2800
+ console.error("Error handling permissionConfigUpdated:", error);
2801
+ }
2802
+ };
2803
+ const personJoined = async ({
2804
+ name,
2805
+ showAlert
2806
+ }) => {
2807
+ showAlert?.({
2808
+ message: `${name} joined the event.`,
2809
+ type: "success",
2810
+ duration: 3e3
2811
+ });
2812
+ };
2813
+ const producerMediaClosed = async ({
2814
+ producerId,
2815
+ kind,
2816
+ parameters
2817
+ }) => {
2818
+ const updatedParameters = parameters.getUpdatedAllParams();
2819
+ const {
2820
+ consumerTransports,
2821
+ updateConsumerTransports,
2822
+ hostLabel,
2823
+ shared,
2824
+ updateShared,
2825
+ updateShareScreenStarted,
2826
+ updateScreenId,
2827
+ updateShareEnded,
2828
+ closeAndResize,
2829
+ prepopulateUserMedia,
2830
+ reorderStreams
2831
+ } = updatedParameters;
2832
+ const producerToClose = consumerTransports.find(
2833
+ (transportData) => transportData.producerId === producerId
2834
+ );
2835
+ if (producerToClose) {
2836
+ try {
2837
+ await producerToClose.consumerTransport?.close();
2838
+ } catch (error) {
2839
+ console.error("Error closing consumer transport:", error);
2840
+ }
2841
+ try {
2842
+ producerToClose.consumer.close();
2843
+ } catch (error) {
2844
+ console.error("Error closing consumer:", error);
2845
+ }
2846
+ const updatedTransports = consumerTransports.filter(
2847
+ (transportData) => transportData.producerId !== producerId
2848
+ );
2849
+ updateConsumerTransports(updatedTransports);
2850
+ await closeAndResize({
2851
+ producerId,
2852
+ kind,
2853
+ parameters: updatedParameters
2854
+ });
2855
+ } else if (kind === "screenshare" || kind === "screen") {
2856
+ if (shared) {
2857
+ updateShared(false);
2858
+ } else {
2859
+ updateShareScreenStarted(false);
2860
+ updateScreenId("");
2861
+ }
2862
+ updateShareEnded(true);
2863
+ await prepopulateUserMedia({ name: hostLabel, parameters: updatedParameters });
2864
+ await reorderStreams({
2865
+ add: false,
2866
+ screenChanged: true,
2867
+ parameters: updatedParameters
2868
+ });
2869
+ }
2870
+ };
2871
+ const producerMediaPaused = async ({
2872
+ producerId,
2873
+ kind,
2874
+ name,
2875
+ parameters
2876
+ }) => {
2877
+ parameters = parameters.getUpdatedAllParams();
2878
+ let {
2879
+ activeSounds,
2880
+ meetingDisplayType,
2881
+ meetingVideoOptimized,
2882
+ participants,
2883
+ oldSoundIds,
2884
+ shared,
2885
+ shareScreenStarted,
2886
+ updateMainWindow,
2887
+ hostLabel,
2888
+ islevel,
2889
+ updateActiveSounds,
2890
+ updateUpdateMainWindow,
2891
+ reorderStreams,
2892
+ prepopulateUserMedia,
2893
+ reUpdateInter
2894
+ } = parameters;
2895
+ await Promise.all(
2896
+ participants.map(async (participant) => {
2897
+ if (participant.muted) {
2898
+ try {
2899
+ if (participant.islevel === "2" && !participant.videoID && !shared && !shareScreenStarted && islevel !== "2") {
2900
+ updateMainWindow = true;
2901
+ updateUpdateMainWindow(updateMainWindow);
2902
+ await prepopulateUserMedia({ name: hostLabel, parameters });
2903
+ updateMainWindow = false;
2904
+ updateUpdateMainWindow(updateMainWindow);
2905
+ }
2906
+ } catch {
2907
+ }
2908
+ if (shareScreenStarted || shared) {
2909
+ if (participant.name && activeSounds.includes(participant.name)) {
2910
+ activeSounds = activeSounds.filter(
2911
+ (audioStream) => audioStream !== participant.name
2912
+ );
2913
+ updateActiveSounds(activeSounds);
2914
+ }
2915
+ reUpdateInter({
2916
+ name: participant.name,
2917
+ add: false,
2918
+ force: true,
2919
+ parameters
2920
+ });
2921
+ }
2922
+ }
2923
+ })
2924
+ );
2925
+ if (meetingDisplayType === "media" || meetingDisplayType === "video" && !meetingVideoOptimized) {
2926
+ const participant = participants.find((item) => item.name === name);
2927
+ const hasVideo = participant?.videoID !== null && participant?.videoID !== "";
2928
+ if (!hasVideo && !(shareScreenStarted || shared)) {
2929
+ await reorderStreams({ add: false, screenChanged: true, parameters });
2930
+ }
2931
+ }
2932
+ if (kind === "audio") {
2933
+ try {
2934
+ const participant = participants.find((item) => item.audioID === producerId) || participants.find((item) => item.name === name);
2935
+ if (participant && (participant.name && oldSoundIds.includes(participant.name) || name && oldSoundIds.includes(name))) {
2936
+ reUpdateInter({
2937
+ name: participant.name,
2938
+ add: false,
2939
+ force: true,
2940
+ parameters
2941
+ });
2942
+ }
2943
+ } catch {
2944
+ }
2945
+ }
2946
+ };
2947
+ const producerMediaResumed = async ({
2948
+ name,
2949
+ parameters
2950
+ }) => {
2951
+ const {
2952
+ meetingDisplayType,
2953
+ participants,
2954
+ shared,
2955
+ shareScreenStarted,
2956
+ mainScreenFilled,
2957
+ hostLabel,
2958
+ updateUpdateMainWindow,
2959
+ reorderStreams,
2960
+ prepopulateUserMedia
2961
+ } = parameters;
2962
+ const participant = participants.find((item) => item.name === name);
2963
+ if (participant && !mainScreenFilled && participant.islevel === "2") {
2964
+ updateUpdateMainWindow(true);
2965
+ await prepopulateUserMedia({ name: hostLabel, parameters });
2966
+ updateUpdateMainWindow(false);
2967
+ }
2968
+ if (meetingDisplayType === "media" && participant) {
2969
+ const hasVideo = participant.videoID !== null && participant.videoID !== "";
2970
+ if (!hasVideo && !(shareScreenStarted || shared)) {
2971
+ await reorderStreams({ add: false, screenChanged: true, parameters });
2972
+ }
2973
+ }
2974
+ };
2975
+ const receiveMessage = async ({
2976
+ message,
2977
+ messages,
2978
+ participantsAll,
2979
+ member,
2980
+ eventType,
2981
+ islevel,
2982
+ coHost,
2983
+ updateMessages,
2984
+ updateShowMessagesBadge
2985
+ }) => {
2986
+ const { sender, receivers, message: content, timestamp, group } = message;
2987
+ const oldMessages = messages;
2988
+ messages = [...messages, { sender, receivers, message: content, timestamp, group }];
2989
+ if (eventType !== "broadcast" && eventType !== "chat") {
2990
+ messages = messages.filter(
2991
+ (msg) => participantsAll.some(
2992
+ (participant) => participant.name === msg.sender && !participant.isBanned
2993
+ )
2994
+ );
2995
+ } else {
2996
+ messages = messages.filter((msg) => {
2997
+ const participant = participantsAll.find((p2) => p2.name === msg.sender);
2998
+ return !participant || !participant.isBanned;
2999
+ });
3000
+ }
3001
+ updateMessages(messages);
3002
+ const oldGroupMessages = oldMessages.filter((msg) => msg.group);
3003
+ const oldDirectMessages = oldMessages.filter((msg) => !msg.group);
3004
+ const groupMessages = messages.filter((msg) => msg.group);
3005
+ const directMessages = messages.filter((msg) => !msg.group);
3006
+ if (eventType !== "broadcast" && eventType !== "chat") {
3007
+ if (oldGroupMessages.length !== groupMessages.length) {
3008
+ const newGroupMessages = groupMessages.filter(
3009
+ (msg) => !oldGroupMessages.some((oldMsg) => oldMsg.timestamp === msg.timestamp)
3010
+ );
3011
+ const relevantGroupMessages = newGroupMessages.filter(
3012
+ (msg) => msg.sender === member || msg.receivers.includes(member)
3013
+ );
3014
+ const selfSentGroupMessages = relevantGroupMessages.filter(
3015
+ (msg) => msg.sender === member
3016
+ );
3017
+ if (newGroupMessages.length > 0 && relevantGroupMessages.length > selfSentGroupMessages.length) {
3018
+ updateShowMessagesBadge(true);
3019
+ }
3020
+ }
3021
+ if (oldDirectMessages.length !== directMessages.length) {
3022
+ const newDirectMessages = directMessages.filter(
3023
+ (msg) => !oldDirectMessages.some((oldMsg) => oldMsg.timestamp === msg.timestamp)
3024
+ );
3025
+ const relevantDirectMessages = newDirectMessages.filter(
3026
+ (msg) => msg.sender === member || msg.receivers.includes(member)
3027
+ );
3028
+ const selfSentDirectMessages = relevantDirectMessages.filter(
3029
+ (msg) => msg.sender === member
3030
+ );
3031
+ const isPrivileged = islevel === "2" || coHost === member;
3032
+ const hasRelevantDirectMessages = isPrivileged ? newDirectMessages.length > 0 : relevantDirectMessages.length > 0;
3033
+ if (hasRelevantDirectMessages && newDirectMessages.length > selfSentDirectMessages.length) {
3034
+ updateShowMessagesBadge(true);
3035
+ }
3036
+ }
3037
+ }
3038
+ };
3039
+ const recordingNotice = async ({
3040
+ state,
3041
+ userRecordingParam,
3042
+ pauseCount,
3043
+ timeDone,
3044
+ parameters,
3045
+ soundPlayer
3046
+ }) => {
3047
+ let {
3048
+ islevel,
3049
+ userRecordingParams,
3050
+ pauseRecordCount,
3051
+ recordElapsedTime,
3052
+ recordStartTime,
3053
+ recordStarted,
3054
+ recordPaused,
3055
+ canLaunchRecord,
3056
+ stopLaunchRecord,
3057
+ recordStopped,
3058
+ isTimerRunning,
3059
+ canPauseResume,
3060
+ eventType,
3061
+ updateRecordingProgressTime,
3062
+ updateShowRecordButtons,
3063
+ updateUserRecordingParams,
3064
+ updateRecordingMediaOptions,
3065
+ updateRecordingAudioOptions,
3066
+ updateRecordingVideoOptions,
3067
+ updateRecordingVideoType,
3068
+ updateRecordingVideoOptimized,
3069
+ updateRecordingDisplayType,
3070
+ updateRecordingAddHLS,
3071
+ updateRecordingNameTags,
3072
+ updateRecordingBackgroundColor,
3073
+ updateRecordingNameTagsColor,
3074
+ updateRecordingOrientationVideo,
3075
+ updateRecordingAddText,
3076
+ updateRecordingCustomText,
3077
+ updateRecordingCustomTextPosition,
3078
+ updateRecordingCustomTextColor,
3079
+ updatePauseRecordCount,
3080
+ updateRecordElapsedTime,
3081
+ updateRecordStartTime,
3082
+ updateRecordStarted,
3083
+ updateRecordPaused,
3084
+ updateCanLaunchRecord,
3085
+ updateStopLaunchRecord,
3086
+ updateRecordStopped,
3087
+ updateIsTimerRunning,
3088
+ updateCanPauseResume,
3089
+ updateRecordState
3090
+ } = parameters;
3091
+ const playSound = async (soundUrl) => {
3092
+ await (soundPlayer ?? SoundPlayer)({ soundUrl });
3093
+ };
3094
+ try {
3095
+ if (islevel !== "2") {
3096
+ if (state === "pause") {
3097
+ updateRecordStarted(true);
3098
+ updateRecordPaused(true);
3099
+ updateRecordState("yellow");
3100
+ if (eventType !== "broadcast") {
3101
+ await playSound("https://www.mediasfu.com/sounds/record-paused.mp3");
3102
+ }
3103
+ } else if (state === "stop") {
3104
+ updateRecordStarted(true);
3105
+ updateRecordStopped(true);
3106
+ updateRecordState("green");
3107
+ if (eventType !== "broadcast") {
3108
+ await playSound("https://www.mediasfu.com/sounds/record-stopped.mp3");
3109
+ }
3110
+ } else {
3111
+ updateRecordState("red");
3112
+ updateRecordStarted(true);
3113
+ updateRecordPaused(false);
3114
+ if (eventType !== "broadcast") {
3115
+ await playSound("https://www.mediasfu.com/sounds/record-progress.mp3");
3116
+ }
3117
+ }
3118
+ } else {
3119
+ if (state === "pause") {
3120
+ updateRecordState("yellow");
3121
+ if (userRecordingParam) {
3122
+ userRecordingParams.mainSpecs = userRecordingParam.mainSpecs;
3123
+ userRecordingParams.dispSpecs = userRecordingParam.dispSpecs;
3124
+ userRecordingParams.textSpecs = userRecordingParam.textSpecs;
3125
+ updateUserRecordingParams(userRecordingParams);
3126
+ updateRecordingMediaOptions(userRecordingParams.mainSpecs.mediaOptions);
3127
+ updateRecordingAudioOptions(userRecordingParams.mainSpecs.audioOptions);
3128
+ updateRecordingVideoOptions(userRecordingParams.mainSpecs.videoOptions);
3129
+ updateRecordingVideoType(userRecordingParams.mainSpecs.videoType);
3130
+ updateRecordingVideoOptimized(userRecordingParams.mainSpecs.videoOptimized);
3131
+ updateRecordingDisplayType(userRecordingParams.mainSpecs.recordingDisplayType);
3132
+ updateRecordingAddHLS(userRecordingParams.mainSpecs.addHLS);
3133
+ updateRecordingNameTags(userRecordingParams.dispSpecs.nameTags);
3134
+ updateRecordingBackgroundColor(userRecordingParams.dispSpecs.backgroundColor);
3135
+ updateRecordingNameTagsColor(userRecordingParams.dispSpecs.nameTagsColor);
3136
+ updateRecordingOrientationVideo(userRecordingParams.dispSpecs.orientationVideo);
3137
+ updateRecordingAddText(userRecordingParams.textSpecs?.addText ?? false);
3138
+ updateRecordingCustomText(userRecordingParams.textSpecs?.customText ?? "");
3139
+ updateRecordingCustomTextPosition(
3140
+ userRecordingParams.textSpecs?.customTextPosition ?? ""
3141
+ );
3142
+ updateRecordingCustomTextColor(
3143
+ userRecordingParams.textSpecs?.customTextColor ?? ""
3144
+ );
3145
+ pauseRecordCount = pauseCount;
3146
+ updatePauseRecordCount(pauseRecordCount);
3147
+ recordElapsedTime = Math.floor(timeDone / 1e3);
3148
+ recordStartTime = Math.floor(Date.now() / 1e3) - recordElapsedTime;
3149
+ updateRecordStartTime(recordStartTime);
3150
+ updateRecordElapsedTime(recordElapsedTime);
3151
+ recordStarted = true;
3152
+ recordPaused = true;
3153
+ canLaunchRecord = false;
3154
+ recordStopped = false;
3155
+ updateRecordStarted(recordStarted);
3156
+ updateRecordPaused(recordPaused);
3157
+ updateCanLaunchRecord(canLaunchRecord);
3158
+ updateRecordStopped(recordStopped);
3159
+ updateShowRecordButtons(true);
3160
+ isTimerRunning = false;
3161
+ canPauseResume = true;
3162
+ updateIsTimerRunning(isTimerRunning);
3163
+ updateCanPauseResume(canPauseResume);
3164
+ updateRecordingProgressTime(formatElapsedTime(recordElapsedTime));
3165
+ }
3166
+ await playSound("https://www.mediasfu.com/sounds/record-paused.mp3");
3167
+ } else if (state === "stop") {
3168
+ recordStarted = true;
3169
+ recordStopped = true;
3170
+ canLaunchRecord = false;
3171
+ stopLaunchRecord = true;
3172
+ updateRecordStarted(recordStarted);
3173
+ updateRecordStopped(recordStopped);
3174
+ updateCanLaunchRecord(canLaunchRecord);
3175
+ updateStopLaunchRecord(stopLaunchRecord);
3176
+ updateShowRecordButtons(false);
3177
+ updateRecordState("green");
3178
+ await playSound("https://www.mediasfu.com/sounds/record-stopped.mp3");
3179
+ } else {
3180
+ updateRecordState("red");
3181
+ updateRecordStarted(true);
3182
+ updateRecordPaused(false);
3183
+ await playSound("https://www.mediasfu.com/sounds/record-progress.mp3");
3184
+ }
3185
+ }
3186
+ } catch (error) {
3187
+ console.log("Error in RecordingNotice: ", error);
3188
+ }
3189
+ };
3190
+ const formatElapsedTime = (recordElapsedTime) => {
3191
+ const hours = Math.floor(recordElapsedTime / 3600);
3192
+ const minutes = Math.floor(recordElapsedTime % 3600 / 60);
3193
+ const seconds = recordElapsedTime % 60;
3194
+ return `${padNumber(hours)}:${padNumber(minutes)}:${padNumber(seconds)}`;
3195
+ };
3196
+ const padNumber = (value) => value.toString().padStart(2, "0");
3197
+ const reInitiateRecording = async ({
3198
+ roomName,
3199
+ member,
3200
+ socket,
3201
+ adminRestrictSetting
3202
+ }) => {
3203
+ if (!adminRestrictSetting) {
3204
+ socket.emit(
3205
+ "startRecordIng",
3206
+ { roomName, member },
3207
+ ({ success }) => {
3208
+ }
3209
+ );
3210
+ }
3211
+ };
3212
+ const roomRecordParams = async ({
3213
+ recordParams,
3214
+ parameters
3215
+ }) => {
3216
+ const {
3217
+ updateRecordingAudioPausesLimit,
3218
+ updateRecordingAudioPausesCount,
3219
+ updateRecordingAudioSupport,
3220
+ updateRecordingAudioPeopleLimit,
3221
+ updateRecordingAudioParticipantsTimeLimit,
3222
+ updateRecordingVideoPausesCount,
3223
+ updateRecordingVideoPausesLimit,
3224
+ updateRecordingVideoSupport,
3225
+ updateRecordingVideoPeopleLimit,
3226
+ updateRecordingVideoParticipantsTimeLimit,
3227
+ updateRecordingAllParticipantsSupport,
3228
+ updateRecordingVideoParticipantsSupport,
3229
+ updateRecordingAllParticipantsFullRoomSupport,
3230
+ updateRecordingVideoParticipantsFullRoomSupport,
3231
+ updateRecordingPreferredOrientation,
3232
+ updateRecordingSupportForOtherOrientation,
3233
+ updateRecordingMultiFormatsSupport
3234
+ } = parameters;
3235
+ updateRecordingAudioPausesLimit(recordParams.recordingAudioPausesLimit);
3236
+ updateRecordingAudioPausesCount(recordParams.recordingAudioPausesCount);
3237
+ updateRecordingAudioSupport(recordParams.recordingAudioSupport);
3238
+ updateRecordingAudioPeopleLimit(recordParams.recordingAudioPeopleLimit);
3239
+ updateRecordingAudioParticipantsTimeLimit(
3240
+ recordParams.recordingAudioParticipantsTimeLimit
3241
+ );
3242
+ updateRecordingVideoPausesCount(recordParams.recordingVideoPausesCount);
3243
+ updateRecordingVideoPausesLimit(recordParams.recordingVideoPausesLimit);
3244
+ updateRecordingVideoSupport(recordParams.recordingVideoSupport);
3245
+ updateRecordingVideoPeopleLimit(recordParams.recordingVideoPeopleLimit);
3246
+ updateRecordingVideoParticipantsTimeLimit(
3247
+ recordParams.recordingVideoParticipantsTimeLimit
3248
+ );
3249
+ updateRecordingAllParticipantsSupport(
3250
+ recordParams.recordingAllParticipantsSupport
3251
+ );
3252
+ updateRecordingVideoParticipantsSupport(
3253
+ recordParams.recordingVideoParticipantsSupport
3254
+ );
3255
+ updateRecordingAllParticipantsFullRoomSupport(
3256
+ recordParams.recordingAllParticipantsFullRoomSupport
3257
+ );
3258
+ updateRecordingVideoParticipantsFullRoomSupport(
3259
+ recordParams.recordingVideoParticipantsFullRoomSupport
3260
+ );
3261
+ updateRecordingPreferredOrientation(
3262
+ recordParams.recordingPreferredOrientation
3263
+ );
3264
+ updateRecordingSupportForOtherOrientation(
3265
+ recordParams.recordingSupportForOtherOrientation
3266
+ );
3267
+ updateRecordingMultiFormatsSupport(recordParams.recordingMultiFormatsSupport);
3268
+ };
3269
+ const screenProducerId = ({
3270
+ producerId,
3271
+ screenId,
3272
+ membersReceived,
3273
+ participants,
3274
+ updateScreenId,
3275
+ updateShareScreenStarted,
3276
+ updateDeferScreenReceived
3277
+ }) => {
3278
+ const host = participants.find(
3279
+ (participant) => participant.ScreenID === screenId && participant.ScreenOn === true
3280
+ );
3281
+ if (host && membersReceived) {
3282
+ updateScreenId(producerId);
3283
+ updateShareScreenStarted(true);
3284
+ updateDeferScreenReceived(false);
3285
+ return;
3286
+ }
3287
+ updateScreenId(producerId);
3288
+ updateDeferScreenReceived(true);
3289
+ };
3290
+ const startRecords = async ({
3291
+ roomName,
3292
+ member,
3293
+ socket
3294
+ }) => {
3295
+ socket.emit(
3296
+ "startRecordIng",
3297
+ { roomName, member },
3298
+ ({ success }) => {
3299
+ }
3300
+ );
3301
+ };
3302
+ const stoppedRecording = async ({
3303
+ state,
3304
+ reason,
3305
+ showAlert
3306
+ }) => {
3307
+ try {
3308
+ if (state === "stop") {
3309
+ showAlert?.({
3310
+ message: `The recording has stopped - ${reason}.`,
3311
+ duration: 3e3,
3312
+ type: "danger"
3313
+ });
3314
+ }
3315
+ } catch (error) {
3316
+ console.log("Error in stoppedRecording: ", error);
3317
+ }
3318
+ };
3319
+ const translationRoomConfig = async ({
3320
+ data,
3321
+ updateTranslationConfig,
3322
+ updateTranslationSupported
3323
+ }) => {
3324
+ try {
3325
+ const { config } = data;
3326
+ updateTranslationSupported?.(config.supportTranslation);
3327
+ if (updateTranslationConfig && config.supportTranslation) {
3328
+ updateTranslationConfig(config);
3329
+ }
3330
+ } catch (error) {
3331
+ console.error("Error handling translation:roomConfig:", error);
3332
+ }
3333
+ };
3334
+ const translationConfigUpdated = async ({
3335
+ data,
3336
+ updateTranslationConfig,
3337
+ showAlert
3338
+ }) => {
3339
+ try {
3340
+ updateTranslationConfig?.(data.config);
3341
+ showAlert?.({
3342
+ message: "Translation settings updated by host",
3343
+ type: "info",
3344
+ duration: 2e3
3345
+ });
3346
+ } catch (error) {
3347
+ console.error("Error handling translation:configUpdated:", error);
3348
+ }
3349
+ };
3350
+ const translationLanguageSet = async ({
3351
+ data,
3352
+ updateMySpokenLanguage,
3353
+ updateMySpokenLanguageEnabled,
3354
+ showAlert
3355
+ }) => {
3356
+ try {
3357
+ if (data.success) {
3358
+ updateMySpokenLanguage?.(data.language);
3359
+ updateMySpokenLanguageEnabled?.(data.enabled);
3360
+ } else if (showAlert && data.error) {
3361
+ showAlert({
3362
+ message: data.error,
3363
+ type: "danger",
3364
+ duration: 3e3
3365
+ });
3366
+ }
3367
+ } catch (error) {
3368
+ console.error("Error handling translation:languageSet:", error);
3369
+ }
3370
+ };
3371
+ const translationSubscribed = async ({
3372
+ data,
3373
+ updateListenPreferences,
3374
+ updateTranslationProducerMap,
3375
+ startConsumingTranslation,
3376
+ showAlert
3377
+ }) => {
3378
+ try {
3379
+ const { speakerId, language, channelCreated, producerId, originalProducerId } = data;
3380
+ updateListenPreferences?.((prev) => {
3381
+ const next = new Map(prev);
3382
+ next.set(speakerId, language);
3383
+ return next;
3384
+ });
3385
+ if (producerId && originalProducerId && updateTranslationProducerMap) {
3386
+ updateTranslationProducerMap((prev) => ({
3387
+ ...prev,
3388
+ [originalProducerId]: {
3389
+ ...prev[originalProducerId] || {},
3390
+ [language]: producerId
3391
+ }
3392
+ }));
3393
+ }
3394
+ if (producerId && startConsumingTranslation) {
3395
+ await startConsumingTranslation(producerId, speakerId, language, originalProducerId);
3396
+ }
3397
+ if (showAlert && channelCreated) {
3398
+ showAlert({
3399
+ message: `Translation channel created for ${language}`,
3400
+ type: "success",
3401
+ duration: 2e3
3402
+ });
3403
+ }
3404
+ } catch (error) {
3405
+ console.error("Error handling translation:subscribed:", error);
3406
+ }
3407
+ };
3408
+ const translationUnsubscribed = async ({
3409
+ data,
3410
+ updateListenPreferences,
3411
+ stopConsumingTranslation
3412
+ }) => {
3413
+ try {
3414
+ updateListenPreferences?.((prev) => {
3415
+ const next = new Map(prev);
3416
+ next.delete(data.speakerId);
3417
+ return next;
3418
+ });
3419
+ if (stopConsumingTranslation) {
3420
+ await stopConsumingTranslation(data.speakerId, data.language);
3421
+ }
3422
+ } catch (error) {
3423
+ console.error("Error handling translation:unsubscribed:", error);
3424
+ }
3425
+ };
3426
+ const translationProducerReady = async ({
3427
+ data,
3428
+ updateTranslationProducerMap,
3429
+ pauseOriginalProducer
3430
+ }) => {
3431
+ try {
3432
+ updateTranslationProducerMap?.((prev) => ({
3433
+ ...prev,
3434
+ [data.originalProducerId]: {
3435
+ ...prev[data.originalProducerId] || {},
3436
+ [data.language]: data.producerId
3437
+ }
3438
+ }));
3439
+ if (pauseOriginalProducer) {
3440
+ await pauseOriginalProducer(data.originalProducerId);
3441
+ }
3442
+ } catch (error) {
3443
+ console.error("Error handling translation:producerReady:", error);
3444
+ }
3445
+ };
3446
+ const translationProducerClosed = async ({
3447
+ data,
3448
+ updateTranslationProducerMap,
3449
+ stopConsumingTranslation,
3450
+ resumeOriginalProducer,
3451
+ showAlert
3452
+ }) => {
3453
+ try {
3454
+ if (updateTranslationProducerMap) {
3455
+ updateTranslationProducerMap((prev) => {
3456
+ const next = { ...prev };
3457
+ for (const [originalProducerId, languageMap] of Object.entries(next)) {
3458
+ if (languageMap[data.language] === data.producerId) {
3459
+ delete languageMap[data.language];
3460
+ if (Object.keys(languageMap).length === 0) {
3461
+ delete next[originalProducerId];
3462
+ }
3463
+ }
3464
+ }
3465
+ return next;
3466
+ });
3467
+ }
3468
+ if (stopConsumingTranslation) {
3469
+ await stopConsumingTranslation(data.producerId);
3470
+ }
3471
+ if (resumeOriginalProducer) {
3472
+ await resumeOriginalProducer(data.speakerId);
3473
+ }
3474
+ if (showAlert && data.reason) {
3475
+ showAlert({
3476
+ message: `Translation stopped: ${data.reason}`,
3477
+ type: "info",
3478
+ duration: 2e3
3479
+ });
3480
+ }
3481
+ } catch (error) {
3482
+ console.error("Error handling translation:producerClosed:", error);
3483
+ }
3484
+ };
3485
+ const translationChannelsAvailable = async ({
3486
+ data,
3487
+ updateAvailableTranslationChannels,
3488
+ myDefaultListenLanguage,
3489
+ socket,
3490
+ roomName
3491
+ }) => {
3492
+ try {
3493
+ updateAvailableTranslationChannels?.(data.speakerId, data.languages, data.originalProducerId);
3494
+ if (myDefaultListenLanguage && data.languages.includes(myDefaultListenLanguage) && socket && roomName) {
3495
+ socket.emit("translation:subscribe", {
3496
+ roomName,
3497
+ speakerId: data.speakerId,
3498
+ language: myDefaultListenLanguage,
3499
+ originalProducerId: data.originalProducerId
3500
+ });
3501
+ }
3502
+ } catch (error) {
3503
+ console.error("Error handling translation:channelsAvailable:", error);
3504
+ }
3505
+ };
3506
+ const translationMemberState = async ({
3507
+ data,
3508
+ updateParticipantTranslationState
3509
+ }) => {
3510
+ try {
3511
+ updateParticipantTranslationState?.(data.memberId, data.state);
3512
+ } catch (error) {
3513
+ console.error("Error handling translation:memberState:", error);
3514
+ }
3515
+ };
3516
+ const translationError = async ({
3517
+ data,
3518
+ showAlert
3519
+ }) => {
3520
+ try {
3521
+ if (showAlert) {
3522
+ let message = data.error;
3523
+ switch (data.code) {
3524
+ case "max_channels":
3525
+ if (data.availableChannels && data.availableChannels.length > 0) {
3526
+ message = `Maximum ${data.maxChannels || 5} translation channels reached. Available: ${data.availableChannels.join(", ")}`;
3527
+ } else {
3528
+ message = data.message || "Maximum translation channels reached. Please wait for a slot to open.";
3529
+ }
3530
+ break;
3531
+ case "speaker_not_found":
3532
+ message = "Speaker not found or has left the meeting.";
3533
+ break;
3534
+ case "language_not_allowed":
3535
+ message = "This language is not available for translation in this room.";
3536
+ break;
3537
+ default:
3538
+ message = data.error || "Translation error occurred";
3539
+ }
3540
+ showAlert({
3541
+ message,
3542
+ type: "danger",
3543
+ duration: 5e3
3544
+ });
3545
+ }
3546
+ } catch (err) {
3547
+ console.error("Error handling translation:error:", err);
3548
+ }
3549
+ };
3550
+ const translationTranscript = async ({
3551
+ data,
3552
+ updateTranscripts,
3553
+ onTranscriptReceived,
3554
+ maxTranscripts = 100
3555
+ }) => {
3556
+ try {
3557
+ if (updateTranscripts) {
3558
+ updateTranscripts((prev) => {
3559
+ const next = [...prev, data];
3560
+ return next.length > maxTranscripts ? next.slice(-maxTranscripts) : next;
3561
+ });
3562
+ }
3563
+ onTranscriptReceived?.(data);
3564
+ } catch (err) {
3565
+ console.error("Error handling translation:transcript:", err);
3566
+ }
3567
+ };
3568
+ const translationSpeakerOutputChanged = async ({
3569
+ data,
3570
+ pauseOriginalProducer,
3571
+ resumeOriginalProducer,
3572
+ stopConsumingTranslationForSpeaker,
3573
+ updateSpeakerTranslationState,
3574
+ showAlert,
3575
+ listenerOverride
3576
+ }) => {
3577
+ try {
3578
+ updateSpeakerTranslationState?.(data.speakerId, data.outputLanguage, data.originalProducerId);
3579
+ const listenerWantsOriginal = listenerOverride?.wantOriginal === true;
3580
+ const listenerWantsDifferentLanguage = Boolean(
3581
+ listenerOverride?.preferredLanguage && listenerOverride.preferredLanguage.toLowerCase() !== data.outputLanguage?.toLowerCase()
3582
+ );
3583
+ if (listenerWantsOriginal) {
3584
+ showAlert?.({
3585
+ message: `${data.speakerName} is speaking in ${data.outputLanguage ? getLanguageName(data.outputLanguage) : "translated"} but you're hearing original`,
3586
+ type: "info",
3587
+ duration: 3e3
3588
+ });
3589
+ return;
3590
+ }
3591
+ if (listenerWantsDifferentLanguage) {
3592
+ if (pauseOriginalProducer && data.originalProducerId) {
3593
+ await pauseOriginalProducer(data.originalProducerId, data.speakerId);
3594
+ }
3595
+ return;
3596
+ }
3597
+ if (data.enabled && data.outputLanguage && data.originalProducerId) {
3598
+ if (pauseOriginalProducer) {
3599
+ await pauseOriginalProducer(data.originalProducerId, data.speakerId);
3600
+ }
3601
+ showAlert?.({
3602
+ message: `${data.speakerName} is now speaking in ${getLanguageName(data.outputLanguage)}`,
3603
+ type: "info",
3604
+ duration: 3e3
3605
+ });
3606
+ } else if (!data.enabled || !data.outputLanguage) {
3607
+ if (stopConsumingTranslationForSpeaker) {
3608
+ await stopConsumingTranslationForSpeaker(data.speakerId);
3609
+ }
3610
+ if (resumeOriginalProducer && data.originalProducerId) {
3611
+ await resumeOriginalProducer(data.originalProducerId, data.speakerId);
3612
+ }
3613
+ if (showAlert && !data.enabled) {
3614
+ showAlert({
3615
+ message: `${data.speakerName} returned to original language`,
3616
+ type: "info",
3617
+ duration: 3e3
3618
+ });
3619
+ }
3620
+ }
3621
+ } catch (err) {
3622
+ console.error("Error handling translation:speakerOutputChanged:", err);
3623
+ }
3624
+ };
3625
+ const updateMediaSettings = ({
3626
+ settings,
3627
+ updateAudioSetting,
3628
+ updateVideoSetting,
3629
+ updateScreenshareSetting,
3630
+ updateChatSetting
3631
+ }) => {
3632
+ const [audioSetting, videoSetting, screenshareSetting, chatSetting] = settings;
3633
+ updateAudioSetting(audioSetting);
3634
+ updateVideoSetting(videoSetting);
3635
+ updateScreenshareSetting(screenshareSetting);
3636
+ updateChatSetting(chatSetting);
3637
+ };
3638
+ const updateConsumingDomains = async ({
3639
+ domains,
3640
+ alt_domains,
3641
+ parameters,
3642
+ apiUserName,
3643
+ apiKey,
3644
+ apiToken
3645
+ }) => {
3646
+ let { participants, getDomains: getDomains2, consume_sockets, connectIps } = parameters;
3647
+ consume_sockets = parameters.getUpdatedAllParams().consume_sockets;
3648
+ try {
3649
+ if (participants.length > 0) {
3650
+ if (Object.keys(alt_domains).length > 0) {
3651
+ await getDomains2({
3652
+ domains,
3653
+ alt_domains,
3654
+ apiUserName,
3655
+ apiKey,
3656
+ apiToken,
3657
+ parameters
3658
+ });
3659
+ } else {
3660
+ await connectIps({
3661
+ consume_sockets,
3662
+ remIP: domains,
3663
+ parameters,
3664
+ apiUserName,
3665
+ apiKey,
3666
+ apiToken
3667
+ });
3668
+ }
3669
+ }
3670
+ } catch (error) {
3671
+ console.log("Error in updateConsumingDomains: ", error);
3672
+ }
3673
+ };
3674
+ const updatedCoHost = async ({
3675
+ coHost,
3676
+ coHostResponsibility,
3677
+ showAlert,
3678
+ eventType,
3679
+ islevel,
3680
+ member,
3681
+ youAreCoHost,
3682
+ updateCoHost,
3683
+ updateCoHostResponsibility,
3684
+ updateYouAreCoHost
3685
+ }) => {
3686
+ if (eventType !== "broadcast" && eventType !== "chat") {
3687
+ updateCoHost(coHost);
3688
+ updateCoHostResponsibility(coHostResponsibility);
3689
+ if (member === coHost) {
3690
+ if (!youAreCoHost) {
3691
+ updateYouAreCoHost(true);
3692
+ showAlert?.({
3693
+ message: "You are now a co-host.",
3694
+ type: "success",
3695
+ duration: 3e3
3696
+ });
3697
+ }
3698
+ } else {
3699
+ updateYouAreCoHost(false);
3700
+ }
3701
+ } else if (islevel !== "2") {
3702
+ updateYouAreCoHost(true);
3703
+ }
3704
+ };
3705
+ const userWaiting = async ({
3706
+ name,
3707
+ showAlert,
3708
+ totalReqWait,
3709
+ updateTotalReqWait
3710
+ }) => {
3711
+ showAlert?.({
3712
+ message: `${name} joined the waiting room.`,
3713
+ type: "success",
3714
+ duration: 3e3
3715
+ });
3716
+ updateTotalReqWait(totalReqWait + 1);
3717
+ };
3718
+ const cookies = new Cookies();
3719
+ const MAX_ATTEMPTS = 10;
3720
+ const RATE_LIMIT_DURATION = 3 * 60 * 60 * 1e3;
3721
+ const hasConnectedSocketId = (socket) => {
3722
+ if (!socket || typeof socket !== "object") {
3723
+ return false;
3724
+ }
3725
+ const candidate = socket;
3726
+ return typeof candidate.id === "string" && candidate.id.length > 0;
3727
+ };
3728
+ function validateAlphanumeric(str) {
3729
+ if (str.length === 0) return true;
3730
+ const alphanumericRegex = /^[a-zA-Z0-9]+$/;
3731
+ return alphanumericRegex.test(str);
3732
+ }
3733
+ function validateWelcomeInputs({
3734
+ name,
3735
+ secret,
3736
+ eventID,
3737
+ link
3738
+ }) {
3739
+ if (name.length === 0 || secret.length === 0 || eventID.length === 0 || link.length === 0) {
3740
+ return { valid: false, message: "Please fill all the fields." };
3741
+ }
3742
+ if (!validateAlphanumeric(name) || !validateAlphanumeric(secret) || !validateAlphanumeric(eventID) || !link.includes("mediasfu.com") || eventID.toLowerCase().startsWith("d")) {
3743
+ return { valid: false, message: "Please enter valid details." };
3744
+ }
3745
+ if (secret.length != 64 || name.length > 12 || name.length < 2 || eventID.length > 32 || eventID.length < 8 || link.length < 12) {
3746
+ return { valid: false, message: "Please enter valid details." };
3747
+ }
3748
+ return { valid: true };
3749
+ }
3750
+ async function handleWelcomeRequest({
3751
+ apiUserName,
3752
+ apiToken,
3753
+ link,
3754
+ userName,
3755
+ parameters
3756
+ }) {
3757
+ const {
3758
+ showAlert,
3759
+ updateIsLoadingModalVisible,
3760
+ connectSocket,
3761
+ updateSocket,
3762
+ updateValidated,
3763
+ updateApiUserName,
3764
+ updateApiToken,
3765
+ updateLink,
3766
+ updateRoomName,
3767
+ updateMember
3768
+ } = parameters;
3769
+ const TIMEOUT_DURATION = 1e4;
3770
+ let unsuccessfulAttempts = parseInt(cookies.get("unsuccessfulAttempts") || "0");
3771
+ let lastRequestTimestamp = parseInt(cookies.get("lastRequestTimestamp") || "0");
3772
+ if (unsuccessfulAttempts >= MAX_ATTEMPTS) {
3773
+ if (Date.now() - lastRequestTimestamp < RATE_LIMIT_DURATION) {
3774
+ showAlert?.({
3775
+ message: "Too many unsuccessful attempts. Please try again later.",
3776
+ type: "danger",
3777
+ duration: 3e3
3778
+ });
3779
+ cookies.set("lastRequestTimestamp", Date.now().toString());
3780
+ return;
3781
+ } else {
3782
+ unsuccessfulAttempts = 0;
3783
+ cookies.set("unsuccessfulAttempts", unsuccessfulAttempts.toString());
3784
+ cookies.set("lastRequestTimestamp", Date.now().toString());
3785
+ }
3786
+ }
3787
+ try {
3788
+ updateIsLoadingModalVisible(true);
3789
+ const socketPromise = connectSocket({
3790
+ apiUserName,
3791
+ apiKey: "",
3792
+ apiToken,
3793
+ link
3794
+ });
3795
+ const timeoutPromise = new Promise(
3796
+ (_, reject) => setTimeout(() => reject(new Error("Request timed out")), TIMEOUT_DURATION)
3797
+ );
3798
+ const socket = await Promise.race([socketPromise, timeoutPromise]);
3799
+ if (hasConnectedSocketId(socket)) {
3800
+ unsuccessfulAttempts = 0;
3801
+ cookies.set("unsuccessfulAttempts", unsuccessfulAttempts.toString());
3802
+ cookies.set("lastRequestTimestamp", Date.now().toString());
3803
+ updateSocket(socket);
3804
+ updateApiUserName(apiUserName);
3805
+ updateApiToken(apiToken);
3806
+ updateLink(link);
3807
+ updateRoomName(apiUserName);
3808
+ updateMember(userName);
3809
+ updateValidated(true);
3810
+ } else {
3811
+ unsuccessfulAttempts += 1;
3812
+ cookies.set("unsuccessfulAttempts", unsuccessfulAttempts.toString());
3813
+ cookies.set("lastRequestTimestamp", Date.now().toString());
3814
+ updateIsLoadingModalVisible(false);
3815
+ if (unsuccessfulAttempts >= MAX_ATTEMPTS) {
3816
+ showAlert?.({
3817
+ message: "Too many unsuccessful attempts. Please try again later.",
3818
+ type: "danger",
3819
+ duration: 3e3
3820
+ });
3821
+ } else {
3822
+ showAlert?.({
3823
+ message: "Invalid credentials.",
3824
+ type: "danger",
3825
+ duration: 3e3
3826
+ });
3827
+ }
3828
+ }
3829
+ } catch {
3830
+ showAlert?.({
3831
+ message: "Unable to connect. Check your credentials and try again.",
3832
+ type: "danger",
3833
+ duration: 3e3
3834
+ });
3835
+ unsuccessfulAttempts += 1;
3836
+ cookies.set("unsuccessfulAttempts", unsuccessfulAttempts.toString());
3837
+ cookies.set("lastRequestTimestamp", Date.now().toString());
3838
+ updateIsLoadingModalVisible(false);
3839
+ }
3840
+ }
3841
+ export {
3842
+ COMMON_LANGUAGE_CODES,
3843
+ MediaStream,
3844
+ MediaStreamTrack,
3845
+ Q as QnHDCons,
3846
+ u as QnHDConsNeu,
3847
+ m as QnHDConsPort,
3848
+ A as QnHDFrameRate,
3849
+ RTCView,
3850
+ SUPPORTED_LANGUAGE_CODES,
3851
+ SoundPlayer,
3852
+ TTS_PROVIDERS,
3853
+ f as aParams,
3854
+ addPanelist,
3855
+ addedAsPanelist,
3856
+ allMembers,
3857
+ allMembersRest,
3858
+ allWaitingRoomMembers,
3859
+ banParticipant,
3860
+ bulkUpdateParticipantPermissions,
3861
+ e as captureCanvasStream,
3862
+ checkLimitsAndMakeRequest,
3863
+ c as checkLimitsAndMakeRequestWithStorage,
3864
+ b as clickAudio,
3865
+ clickChat,
3866
+ d as clickScreenShare,
3867
+ controlMediaHost,
3868
+ createLiveSubtitle,
3869
+ createResponseJoinRoom,
3870
+ createRoomOnMediaSFU,
3871
+ disconnect,
3872
+ disconnectUserSelf,
3873
+ fetchLanguagesViaSocket,
3874
+ fetchVoicesViaSocket,
3875
+ l as fhdCons,
3876
+ y as fhdConsNeu,
3877
+ p as fhdConsPort,
3878
+ D as fhdFrameRate,
3879
+ focusPanelists,
3880
+ formatNumber,
3881
+ generateRandomMessages,
3882
+ generateRandomParticipants,
3883
+ generateRandomPolls,
3884
+ generateRandomRequestList,
3885
+ generateRandomWaitingRoomList,
3886
+ getAvailableVoices,
3887
+ getCommonLanguages,
3888
+ getDomains,
3889
+ getLanguageMetadata,
3890
+ getLanguageName,
3891
+ getLanguageNativeName,
3892
+ getOverlayPosition,
3893
+ getSubtitleForSpeaker,
3894
+ getSupportedLanguages,
3895
+ g as hParams,
3896
+ handleCreateRoom,
3897
+ handleJoinRoom,
3898
+ handleWelcomeRequest,
3899
+ k as hdCons,
3900
+ x as hdConsNeu,
3901
+ o as hdConsPort,
3902
+ C as hdFrameRate,
3903
+ h as hostRequestResponse,
3904
+ initialValuesState,
3905
+ isLanguageSupported,
3906
+ isSubtitleExpired,
3907
+ j as joinRoomOnMediaSFU,
3908
+ launchPanelists,
3909
+ launchPermissions,
3910
+ mediaDevices,
3911
+ meetingEnded,
3912
+ meetingStillThere,
3913
+ meetingTimeRemaining,
3914
+ normalizeLanguageCode,
3915
+ panelistControlMedia,
3916
+ panelistFocusChanged,
3917
+ panelistsUpdated,
3918
+ participantRequested,
3919
+ permissionConfigUpdated,
3920
+ permissionUpdated,
3921
+ personJoined,
3922
+ pollUpdated,
3923
+ producerMediaClosed,
3924
+ producerMediaPaused,
3925
+ producerMediaResumed,
3926
+ pruneExpiredSubtitles,
3927
+ q as qhdCons,
3928
+ z as qhdConsNeu,
3929
+ r as qhdConsPort,
3930
+ E as qhdFrameRate,
3931
+ reInitiateRecording,
3932
+ receiveMessage,
3933
+ recordingNotice,
3934
+ registerGlobals,
3935
+ removePanelist,
3936
+ removedFromPanelists,
3937
+ roomRecordParams,
3938
+ F as screenFrameRate,
3939
+ s as screenParams,
3940
+ screenProducerId,
3941
+ i as sdCons,
3942
+ w as sdConsNeu,
3943
+ n as sdConsPort,
3944
+ B as sdFrameRate,
3945
+ sleep,
3946
+ startMeetingProgressTimer,
3947
+ startRecords,
3948
+ stoppedRecording,
3949
+ t as timeLeftRecording,
3950
+ translationChannelsAvailable,
3951
+ translationConfigUpdated,
3952
+ translationError,
3953
+ translationLanguageSet,
3954
+ translationMemberState,
3955
+ translationProducerClosed,
3956
+ translationProducerReady,
3957
+ translationRoomConfig,
3958
+ translationSpeakerOutputChanged,
3959
+ translationSubscribed,
3960
+ translationTranscript,
3961
+ translationUnsubscribed,
3962
+ unfocusPanelists,
3963
+ updateConsumingDomains,
3964
+ updateLiveSubtitlesFromTranscript,
3965
+ updateMediaSettings,
3966
+ updatePanelists,
3967
+ updateParticipantPermission,
3968
+ updatePermissionConfig,
3969
+ updatedCoHost,
3970
+ userWaiting,
3971
+ v as vParams,
3972
+ v2 as validateAlphanumeric,
3973
+ validateAlphanumeric as validateWelcomeAlphanumeric,
3974
+ validateWelcomeInputs
3975
+ };
3976
+ //# sourceMappingURL=index.js.map