mediasfu-shared 1.0.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 (141) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +228 -0
  3. package/dist/index.cjs +7707 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.ts +7285 -0
  6. package/dist/index.js +7690 -0
  7. package/dist/index.js.map +1 -0
  8. package/package.json +78 -0
  9. package/src/ProducerClient/producerClientEmits/createDeviceClient.ts +68 -0
  10. package/src/consumers/addVideosGrid.ts +18 -0
  11. package/src/consumers/autoAdjust.ts +100 -0
  12. package/src/consumers/calculateRowsAndColumns.ts +51 -0
  13. package/src/consumers/changeVids.ts +753 -0
  14. package/src/consumers/checkGrid.ts +100 -0
  15. package/src/consumers/checkPermission.ts +89 -0
  16. package/src/consumers/checkScreenShare.ts +114 -0
  17. package/src/consumers/closeAndResize.ts +401 -0
  18. package/src/consumers/compareActiveNames.ts +122 -0
  19. package/src/consumers/compareScreenStates.ts +117 -0
  20. package/src/consumers/connectIps.ts +175 -0
  21. package/src/consumers/connectLocalIps.ts +103 -0
  22. package/src/consumers/connectRecvTransport.ts +158 -0
  23. package/src/consumers/connectSendTransport.ts +150 -0
  24. package/src/consumers/connectSendTransportAudio.ts +161 -0
  25. package/src/consumers/connectSendTransportScreen.ts +169 -0
  26. package/src/consumers/connectSendTransportVideo.ts +149 -0
  27. package/src/consumers/consumerResume.ts +25 -0
  28. package/src/consumers/controlMedia.ts +118 -0
  29. package/src/consumers/createSendTransport.ts +312 -0
  30. package/src/consumers/disconnectSendTransportAudio.ts +170 -0
  31. package/src/consumers/disconnectSendTransportScreen.ts +130 -0
  32. package/src/consumers/disconnectSendTransportVideo.ts +161 -0
  33. package/src/consumers/dispStreams.ts +694 -0
  34. package/src/consumers/generatePageContent.ts +118 -0
  35. package/src/consumers/getEstimate.ts +124 -0
  36. package/src/consumers/getPipedProducersAlt.ts +96 -0
  37. package/src/consumers/getProducersPiped.ts +89 -0
  38. package/src/consumers/getVideos.ts +107 -0
  39. package/src/consumers/mixStreams.ts +97 -0
  40. package/src/consumers/onScreenChanges.ts +106 -0
  41. package/src/consumers/prepopulateUserMedia.ts +18 -0
  42. package/src/consumers/processConsumerTransports.ts +157 -0
  43. package/src/consumers/processConsumerTransportsAudio.ts +121 -0
  44. package/src/consumers/rePort.ts +123 -0
  45. package/src/consumers/reUpdateInter.ts +289 -0
  46. package/src/consumers/readjust.ts +170 -0
  47. package/src/consumers/receiveAllPipedTransports.ts +77 -0
  48. package/src/consumers/receiveRoomMessages.ts +55 -0
  49. package/src/consumers/reorderStreams.ts +246 -0
  50. package/src/consumers/requestScreenShare.ts +103 -0
  51. package/src/consumers/resumePauseAudioStreams.ts +174 -0
  52. package/src/consumers/resumePauseStreams.ts +110 -0
  53. package/src/consumers/resumeSendTransportAudio.ts +143 -0
  54. package/src/consumers/signalNewConsumerTransport.ts +179 -0
  55. package/src/consumers/socketReceiveMethods/joinConsumeRoom.ts +130 -0
  56. package/src/consumers/socketReceiveMethods/newPipeProducer.ts +138 -0
  57. package/src/consumers/socketReceiveMethods/producerClosed.ts +102 -0
  58. package/src/consumers/startShareScreen.ts +124 -0
  59. package/src/consumers/stopShareScreen.ts +241 -0
  60. package/src/consumers/streamSuccessAudio.ts +297 -0
  61. package/src/consumers/streamSuccessAudioSwitch.ts +315 -0
  62. package/src/consumers/streamSuccessScreen.ts +255 -0
  63. package/src/consumers/streamSuccessVideo.ts +373 -0
  64. package/src/consumers/switchUserAudio.ts +140 -0
  65. package/src/consumers/switchUserVideo.ts +201 -0
  66. package/src/consumers/switchUserVideoAlt.ts +331 -0
  67. package/src/consumers/trigger.ts +250 -0
  68. package/src/consumers/updateMiniCardsGrid.ts +150 -0
  69. package/src/consumers/updateParticipantAudioDecibels.ts +56 -0
  70. package/src/index.ts +119 -0
  71. package/src/methods/background/launchBackground.ts +16 -0
  72. package/src/methods/breakoutRooms/breakoutRoomUpdated.ts +161 -0
  73. package/src/methods/breakoutRooms/handleStartBreakout.ts +96 -0
  74. package/src/methods/breakoutRooms/handleStopBreakout.ts +72 -0
  75. package/src/methods/breakoutRooms/index.ts +4 -0
  76. package/src/methods/breakoutRooms/launchBreakoutRooms.ts +31 -0
  77. package/src/methods/coHost/launchCoHost.ts +28 -0
  78. package/src/methods/coHostMethods/index.ts +2 -0
  79. package/src/methods/coHostMethods/modifyCoHostSettings.ts +94 -0
  80. package/src/methods/displaySettings/index.ts +1 -0
  81. package/src/methods/displaySettings/launchDisplaySettings.ts +31 -0
  82. package/src/methods/displaySettings/modifyDisplaySettings.ts +242 -0
  83. package/src/methods/exit/confirmExit.ts +60 -0
  84. package/src/methods/exit/index.ts +2 -0
  85. package/src/methods/exit/launchConfirmExit.ts +29 -0
  86. package/src/methods/index.ts +5 -0
  87. package/src/methods/mediaSettings/launchMediaSettings.ts +61 -0
  88. package/src/methods/menu/launchMenuModal.ts +28 -0
  89. package/src/methods/message/index.ts +1 -0
  90. package/src/methods/message/launchMessages.ts +27 -0
  91. package/src/methods/message/sendMessage.ts +175 -0
  92. package/src/methods/participants/index.ts +3 -0
  93. package/src/methods/participants/launchParticipants.ts +25 -0
  94. package/src/methods/participants/messageParticipants.ts +78 -0
  95. package/src/methods/participants/muteParticipants.ts +79 -0
  96. package/src/methods/participants/removeParticipants.ts +97 -0
  97. package/src/methods/polls/handleCreatePoll.ts +66 -0
  98. package/src/methods/polls/handleEndPoll.ts +64 -0
  99. package/src/methods/polls/handleVotePoll.ts +76 -0
  100. package/src/methods/polls/index.ts +3 -0
  101. package/src/methods/polls/launchPoll.ts +25 -0
  102. package/src/methods/prejoin/handleCreateRoom.ts +441 -0
  103. package/src/methods/prejoin/handleJoinRoom.ts +153 -0
  104. package/src/methods/prejoin/index.ts +14 -0
  105. package/src/methods/recording/checkPauseState.ts +57 -0
  106. package/src/methods/recording/checkResumeState.ts +42 -0
  107. package/src/methods/recording/confirmRecording.ts +241 -0
  108. package/src/methods/recording/launchRecording.ts +114 -0
  109. package/src/methods/recording/recordPauseTimer.ts +52 -0
  110. package/src/methods/recording/recordResumeTimer.ts +92 -0
  111. package/src/methods/recording/recordStartTimer.ts +106 -0
  112. package/src/methods/recording/recordUpdateTimer.ts +49 -0
  113. package/src/methods/recording/startRecording.ts +268 -0
  114. package/src/methods/recording/stopRecording.ts +124 -0
  115. package/src/methods/recording/updateRecording.ts +245 -0
  116. package/src/methods/requests/index.ts +1 -0
  117. package/src/methods/requests/launchRequests.ts +25 -0
  118. package/src/methods/requests/respondToRequests.ts +108 -0
  119. package/src/methods/settings/index.ts +2 -0
  120. package/src/methods/settings/launchSettings.ts +25 -0
  121. package/src/methods/settings/modifySettings.ts +99 -0
  122. package/src/methods/stream/clickVideo.ts +337 -0
  123. package/src/methods/stream/index.ts +3 -0
  124. package/src/methods/stream/switchAudio.ts +73 -0
  125. package/src/methods/stream/switchVideo.ts +148 -0
  126. package/src/methods/stream/switchVideoAlt.ts +152 -0
  127. package/src/methods/utils/checkLimitsAndMakeRequest.ts +103 -0
  128. package/src/methods/utils/validateAlphanumeric.ts +41 -0
  129. package/src/methods/waiting/index.ts +1 -0
  130. package/src/methods/waiting/launchWaiting.ts +26 -0
  131. package/src/methods/waiting/respondToWaiting.ts +82 -0
  132. package/src/methods/welcome/handleWelcomeRequest.ts +189 -0
  133. package/src/methods/welcome/index.ts +5 -0
  134. package/src/methods/whiteboard/handleStartWhiteboard.ts +65 -0
  135. package/src/methods/whiteboard/handleStopWhiteboard.ts +48 -0
  136. package/src/methods/whiteboard/index.ts +4 -0
  137. package/src/methods/whiteboard/launchConfigureWhiteboard.ts +29 -0
  138. package/src/producers/producerEmits/joinConRoom.ts +153 -0
  139. package/src/sockets/SocketManager.ts +232 -0
  140. package/src/types/shared-base-types.ts +752 -0
  141. package/src/types/types.ts +84 -0
@@ -0,0 +1,441 @@
1
+ import { Socket } from 'socket.io-client';
2
+ import type {
3
+ CreateMediaSFURoomOptions,
4
+ CreateRoomOnMediaSFUType,
5
+ RecordingParams,
6
+ MeetingRoomParams,
7
+ ResponseLocalConnectionData,
8
+ PreJoinPageParameters,
9
+ } from '../../types/types';
10
+ import { checkLimitsAndMakeRequest } from '../utils/checkLimitsAndMakeRequest';
11
+
12
+ /**
13
+ * Parameters for creating a local room
14
+ */
15
+ export interface CreateLocalRoomParameters {
16
+ eventID: string;
17
+ duration: number;
18
+ capacity: number;
19
+ userName: string;
20
+ scheduledDate: Date;
21
+ secureCode: string;
22
+ waitRoom?: boolean;
23
+ recordingParams?: RecordingParams;
24
+ eventRoomParams?: MeetingRoomParams;
25
+ videoPreference?: string | null;
26
+ audioPreference?: string | null;
27
+ audioOutputPreference?: string | null;
28
+ mediasfuURL?: string;
29
+ }
30
+
31
+ /**
32
+ * Options for creating a local room
33
+ */
34
+ export interface CreateLocalRoomOptions {
35
+ createData: CreateLocalRoomParameters;
36
+ link?: string;
37
+ }
38
+
39
+ /**
40
+ * Response from creating/joining a local room
41
+ */
42
+ export interface CreateJoinLocalRoomResponse {
43
+ success: boolean;
44
+ secret: string;
45
+ reason?: string;
46
+ url?: string;
47
+ }
48
+
49
+ /**
50
+ * Options for handleCreateRoom function
51
+ */
52
+ export interface HandleCreateRoomOptions {
53
+ payload: CreateMediaSFURoomOptions;
54
+ localLink?: string;
55
+ connectMediaSFU?: boolean;
56
+ apiUserName: string;
57
+ apiKey: string;
58
+ validate?: boolean;
59
+ parameters: PreJoinPageParameters;
60
+ initSocket?: Socket;
61
+ localData?: ResponseLocalConnectionData;
62
+ createMediaSFURoom: CreateRoomOnMediaSFUType;
63
+ }
64
+
65
+ /**
66
+ * Handles room creation with MediaSFU and/or local server
67
+ *
68
+ * @param {HandleCreateRoomOptions} options - Configuration for creating a room
69
+ * @returns {Promise<void>}
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * await handleCreateRoom({
74
+ * payload: {
75
+ * action: 'create',
76
+ * duration: 30,
77
+ * capacity: 10,
78
+ * eventType: 'conference',
79
+ * userName: 'John Doe',
80
+ * recordOnly: false,
81
+ * },
82
+ * apiUserName: 'user123',
83
+ * apiKey: 'key123',
84
+ * parameters,
85
+ * createMediaSFURoom,
86
+ * });
87
+ * ```
88
+ */
89
+ export async function handleCreateRoom({
90
+ payload,
91
+ localLink = '',
92
+ connectMediaSFU = true,
93
+ apiUserName,
94
+ apiKey,
95
+ validate = true,
96
+ parameters,
97
+ initSocket,
98
+ localData,
99
+ createMediaSFURoom,
100
+ }: HandleCreateRoomOptions): Promise<void> {
101
+ const {
102
+ updateIsLoadingModalVisible,
103
+ updateSocket,
104
+ updateApiUserName,
105
+ updateApiToken,
106
+ updateLink,
107
+ updateRoomName,
108
+ updateMember,
109
+ updateValidated,
110
+ showAlert,
111
+ } = parameters;
112
+
113
+ /**
114
+ * Creates a local room by emitting to the socket
115
+ */
116
+ const createLocalRoom = async ({
117
+ createData,
118
+ link = localLink,
119
+ }: CreateLocalRoomOptions) => {
120
+ initSocket?.emit('createRoom', createData, (response: CreateJoinLocalRoomResponse) => {
121
+ if (response.success) {
122
+ updateSocket(initSocket!);
123
+ updateApiUserName(localData?.apiUserName || '');
124
+ updateApiToken(response.secret);
125
+ updateLink(link);
126
+ updateRoomName(createData.eventID);
127
+ // local needs islevel updated from here
128
+ // we update member as `userName` + "_2" and split it in the room
129
+ updateMember(createData.userName + '_2');
130
+ updateIsLoadingModalVisible(false);
131
+ updateValidated(true);
132
+ } else {
133
+ updateIsLoadingModalVisible(false);
134
+ showAlert?.({
135
+ message: `Unable to create room. ${response.reason}`,
136
+ type: 'danger',
137
+ duration: 3000,
138
+ });
139
+ }
140
+ });
141
+ };
142
+
143
+ /**
144
+ * Creates a room on MediaSFU
145
+ */
146
+ const roomCreator = async ({
147
+ payload: createPayload,
148
+ apiUserName: userName,
149
+ apiKey: key,
150
+ validate: shouldValidate = true,
151
+ }: {
152
+ payload: CreateMediaSFURoomOptions;
153
+ apiUserName: string;
154
+ apiKey: string;
155
+ validate?: boolean;
156
+ }) => {
157
+ const response = await createMediaSFURoom({
158
+ payload: createPayload,
159
+ apiUserName: userName,
160
+ apiKey: key,
161
+ localLink: localLink,
162
+ });
163
+ if (response.success && response.data && 'roomName' in response.data) {
164
+ await checkLimitsAndMakeRequest({
165
+ apiUserName: response.data.roomName,
166
+ apiToken: response.data.secret,
167
+ link: response!.data.link,
168
+ userName: createPayload.userName,
169
+ parameters: parameters,
170
+ validate: shouldValidate,
171
+ });
172
+ return response;
173
+ } else {
174
+ updateIsLoadingModalVisible(false);
175
+ showAlert?.({
176
+ message: `Unable to create room. ${
177
+ response.data ? ('error' in response.data ? response.data.error : '') : ''
178
+ }`,
179
+ type: 'danger',
180
+ duration: 3000,
181
+ });
182
+ }
183
+ };
184
+
185
+ updateIsLoadingModalVisible(true);
186
+
187
+ if (localLink.length > 0) {
188
+ const secureCode =
189
+ Math.random().toString(30).substring(2, 14) +
190
+ Math.random().toString(30).substring(2, 14);
191
+ let eventID =
192
+ new Date().getTime().toString(30) +
193
+ new Date().getUTCMilliseconds() +
194
+ Math.floor(10 + Math.random() * 99).toString();
195
+ eventID = 'm' + eventID;
196
+ const eventRoomParams = localData?.meetingRoomParams_;
197
+ if (eventRoomParams && payload.eventType) {
198
+ eventRoomParams.type = payload.eventType;
199
+ }
200
+
201
+ const createData: CreateLocalRoomParameters = {
202
+ eventID: eventID,
203
+ duration: payload.duration,
204
+ capacity: payload.capacity,
205
+ userName: payload.userName,
206
+ scheduledDate: new Date(),
207
+ secureCode: secureCode,
208
+ waitRoom: false,
209
+ recordingParams: localData?.recordingParams_,
210
+ eventRoomParams: eventRoomParams,
211
+ videoPreference: null,
212
+ audioPreference: null,
213
+ audioOutputPreference: null,
214
+ mediasfuURL: '',
215
+ };
216
+
217
+ if (connectMediaSFU && initSocket && localData && localData.apiUserName && localData.apiKey) {
218
+ // Store references to prevent race conditions
219
+ const localApiUserName = localData.apiUserName;
220
+ const localApiKey = localData.apiKey;
221
+
222
+ // Build a unique identifier for this create request
223
+ const roomIdentifier = `local_create_${payload.userName}_${payload.duration}_${payload.capacity}`;
224
+ const pendingKey = `prejoin_pending_${roomIdentifier}`;
225
+ const PENDING_TIMEOUT = 30 * 1000; // 30 seconds
226
+
227
+ // Check pending status to prevent duplicate requests
228
+ try {
229
+ const pendingRequest = localStorage.getItem(pendingKey);
230
+ if (pendingRequest) {
231
+ const pendingData = JSON.parse(pendingRequest);
232
+ const timeSincePending = Date.now() - (pendingData?.timestamp ?? 0);
233
+ if (timeSincePending < PENDING_TIMEOUT) {
234
+ updateIsLoadingModalVisible(false);
235
+ showAlert?.({
236
+ message: 'Room creation already in progress',
237
+ type: 'danger',
238
+ duration: 3000,
239
+ });
240
+ return;
241
+ } else {
242
+ // Stale lock, clear it
243
+ try {
244
+ localStorage.removeItem(pendingKey);
245
+ } catch {
246
+ // Ignore localStorage errors
247
+ }
248
+ }
249
+ }
250
+ } catch {
251
+ // Ignore localStorage read/JSON errors
252
+ }
253
+
254
+ // Mark request as pending
255
+ try {
256
+ localStorage.setItem(
257
+ pendingKey,
258
+ JSON.stringify({
259
+ timestamp: Date.now(),
260
+ payload: {
261
+ action: 'create',
262
+ userName: payload.userName,
263
+ duration: payload.duration,
264
+ capacity: payload.capacity,
265
+ },
266
+ })
267
+ );
268
+
269
+ // Auto-clear the pending flag after timeout to avoid stale locks
270
+ setTimeout(() => {
271
+ try {
272
+ localStorage.removeItem(pendingKey);
273
+ } catch {
274
+ // Ignore localStorage errors
275
+ }
276
+ }, PENDING_TIMEOUT);
277
+ } catch {
278
+ // Ignore localStorage write errors
279
+ }
280
+
281
+ payload.recordOnly = true; // allow production to mediasfu only; no consumption
282
+
283
+ try {
284
+ const response = await roomCreator({
285
+ payload,
286
+ apiUserName: localApiUserName,
287
+ apiKey: localApiKey,
288
+ validate: false,
289
+ });
290
+
291
+ // Clear pending status on completion
292
+ try {
293
+ localStorage.removeItem(pendingKey);
294
+ } catch {
295
+ /* ignore */
296
+ }
297
+
298
+ if (response && response.success && response.data && 'roomName' in response.data) {
299
+ createData.eventID = response.data.roomName;
300
+ createData.secureCode = response.data.secureCode || '';
301
+ createData.mediasfuURL = response.data.publicURL;
302
+ await createLocalRoom({
303
+ createData: createData,
304
+ link: response.data.link,
305
+ });
306
+ } else {
307
+ updateIsLoadingModalVisible(false);
308
+ showAlert?.({
309
+ message: `Unable to create room on MediaSFU.`,
310
+ type: 'danger',
311
+ duration: 3000,
312
+ });
313
+ try {
314
+ updateSocket(initSocket);
315
+ await createLocalRoom({ createData: createData });
316
+ } catch (error) {
317
+ updateIsLoadingModalVisible(false);
318
+ showAlert?.({
319
+ message: `Unable to create room. ${error}`,
320
+ type: 'danger',
321
+ duration: 3000,
322
+ });
323
+ }
324
+ }
325
+ } catch (error) {
326
+ // Clear pending status on error
327
+ try {
328
+ localStorage.removeItem(pendingKey);
329
+ } catch {
330
+ /* ignore */
331
+ }
332
+ updateIsLoadingModalVisible(false);
333
+ showAlert?.({
334
+ message: `Unable to create room on MediaSFU. ${error}`,
335
+ type: 'danger',
336
+ duration: 3000,
337
+ });
338
+ }
339
+ } else {
340
+ try {
341
+ updateSocket(initSocket!);
342
+ await createLocalRoom({ createData: createData });
343
+ } catch (error) {
344
+ updateIsLoadingModalVisible(false);
345
+ showAlert?.({
346
+ message: `Unable to create room. ${error}`,
347
+ type: 'danger',
348
+ duration: 3000,
349
+ });
350
+ }
351
+ }
352
+ } else {
353
+ // Build a unique identifier for this create request (non-local)
354
+ const roomIdentifier = `mediasfu_create_${payload.userName}_${payload.duration}_${payload.capacity}`;
355
+ const pendingKey = `prejoin_pending_${roomIdentifier}`;
356
+ const PENDING_TIMEOUT = 30 * 1000; // 30 seconds
357
+
358
+ // Check pending status to prevent duplicate requests
359
+ try {
360
+ const pendingRequest = localStorage.getItem(pendingKey);
361
+ if (pendingRequest) {
362
+ const pendingData = JSON.parse(pendingRequest);
363
+ const timeSincePending = Date.now() - (pendingData?.timestamp ?? 0);
364
+ if (timeSincePending < PENDING_TIMEOUT) {
365
+ updateIsLoadingModalVisible(false);
366
+ showAlert?.({
367
+ message: 'Room creation already in progress',
368
+ type: 'danger',
369
+ duration: 3000,
370
+ });
371
+ return;
372
+ } else {
373
+ // Stale lock, clear it
374
+ try {
375
+ localStorage.removeItem(pendingKey);
376
+ } catch {
377
+ // Ignore localStorage errors
378
+ }
379
+ }
380
+ }
381
+ } catch {
382
+ // Ignore localStorage read/JSON errors
383
+ }
384
+
385
+ // Mark request as pending
386
+ try {
387
+ localStorage.setItem(
388
+ pendingKey,
389
+ JSON.stringify({
390
+ timestamp: Date.now(),
391
+ payload: {
392
+ action: 'create',
393
+ userName: payload.userName,
394
+ duration: payload.duration,
395
+ capacity: payload.capacity,
396
+ },
397
+ })
398
+ );
399
+
400
+ // Auto-clear the pending flag after timeout to avoid stale locks
401
+ setTimeout(() => {
402
+ try {
403
+ localStorage.removeItem(pendingKey);
404
+ } catch {
405
+ // Ignore localStorage errors
406
+ }
407
+ }, PENDING_TIMEOUT);
408
+ } catch {
409
+ // Ignore localStorage write errors
410
+ }
411
+
412
+ try {
413
+ await roomCreator({
414
+ payload,
415
+ apiUserName: apiUserName,
416
+ apiKey: apiKey,
417
+ validate: validate,
418
+ });
419
+
420
+ // Clear pending status on completion
421
+ try {
422
+ localStorage.removeItem(pendingKey);
423
+ } catch {
424
+ /* ignore */
425
+ }
426
+ } catch (error) {
427
+ // Clear pending status on error
428
+ try {
429
+ localStorage.removeItem(pendingKey);
430
+ } catch {
431
+ /* ignore */
432
+ }
433
+ updateIsLoadingModalVisible(false);
434
+ showAlert?.({
435
+ message: `Unable to create room. ${error}`,
436
+ type: 'danger',
437
+ duration: 3000,
438
+ });
439
+ }
440
+ }
441
+ }
@@ -0,0 +1,153 @@
1
+ import { Socket } from 'socket.io-client';
2
+ import type {
3
+ JoinMediaSFURoomOptions,
4
+ JoinRoomOnMediaSFUType,
5
+ PreJoinPageParameters,
6
+ } from '../../types/types';
7
+ import { checkLimitsAndMakeRequest } from '../utils/checkLimitsAndMakeRequest';
8
+ import type { CreateJoinLocalRoomResponse } from './handleCreateRoom';
9
+
10
+ /**
11
+ * Parameters for joining a local event room
12
+ */
13
+ export interface JoinLocalEventRoomParameters {
14
+ eventID: string;
15
+ userName: string;
16
+ secureCode?: string;
17
+ videoPreference?: string | null;
18
+ audioPreference?: string | null;
19
+ audioOutputPreference?: string | null;
20
+ }
21
+
22
+ /**
23
+ * Options for joining a local event room
24
+ */
25
+ export interface JoinLocalEventRoomOptions {
26
+ joinData: JoinLocalEventRoomParameters;
27
+ link?: string;
28
+ }
29
+
30
+ /**
31
+ * Options for handleJoinRoom function
32
+ */
33
+ export interface HandleJoinRoomOptions {
34
+ payload: JoinMediaSFURoomOptions;
35
+ localLink?: string;
36
+ apiUserName: string;
37
+ apiKey: string;
38
+ parameters: PreJoinPageParameters;
39
+ initSocket?: Socket;
40
+ localData?: any;
41
+ joinMediaSFURoom: JoinRoomOnMediaSFUType;
42
+ }
43
+
44
+ /**
45
+ * Handles joining an existing room on MediaSFU or local server
46
+ *
47
+ * @param {HandleJoinRoomOptions} options - Configuration for joining a room
48
+ * @returns {Promise<void>}
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * await handleJoinRoom({
53
+ * payload: {
54
+ * action: 'join',
55
+ * meetingID: 'room123',
56
+ * userName: 'John Doe',
57
+ * },
58
+ * apiUserName: 'user123',
59
+ * apiKey: 'key123',
60
+ * parameters,
61
+ * joinMediaSFURoom,
62
+ * });
63
+ * ```
64
+ */
65
+ export async function handleJoinRoom({
66
+ payload,
67
+ localLink = '',
68
+ apiUserName,
69
+ apiKey,
70
+ parameters,
71
+ initSocket,
72
+ localData,
73
+ joinMediaSFURoom,
74
+ }: HandleJoinRoomOptions): Promise<void> {
75
+ const {
76
+ updateIsLoadingModalVisible,
77
+ updateSocket,
78
+ updateApiUserName,
79
+ updateApiToken,
80
+ updateLink,
81
+ updateRoomName,
82
+ updateMember,
83
+ updateValidated,
84
+ showAlert,
85
+ } = parameters;
86
+
87
+ /**
88
+ * Joins a local room by emitting to the socket
89
+ */
90
+ const joinLocalRoom = async ({ joinData, link = localLink }: JoinLocalEventRoomOptions) => {
91
+ initSocket?.emit('joinEventRoom', joinData, (response: CreateJoinLocalRoomResponse) => {
92
+ if (response.success) {
93
+ updateSocket(initSocket!);
94
+ updateApiUserName(localData?.apiUserName || '');
95
+ updateApiToken(response.secret);
96
+ updateLink(link);
97
+ updateRoomName(joinData.eventID);
98
+ updateMember(joinData.userName);
99
+ updateIsLoadingModalVisible(false);
100
+ updateValidated(true);
101
+ } else {
102
+ updateIsLoadingModalVisible(false);
103
+ showAlert?.({
104
+ message: `Unable to join room. ${response.reason}`,
105
+ type: 'danger',
106
+ duration: 3000,
107
+ });
108
+ }
109
+ });
110
+ };
111
+
112
+ if (localLink.length > 0 && !localLink.includes('mediasfu.com')) {
113
+ const joinData: JoinLocalEventRoomParameters = {
114
+ eventID: payload.meetingID,
115
+ userName: payload.userName,
116
+ secureCode: '',
117
+ videoPreference: null,
118
+ audioPreference: null,
119
+ audioOutputPreference: null,
120
+ };
121
+
122
+ await joinLocalRoom({ joinData: joinData });
123
+ return;
124
+ }
125
+
126
+ updateIsLoadingModalVisible(true);
127
+
128
+ const response = await joinMediaSFURoom({
129
+ payload,
130
+ apiUserName: apiUserName,
131
+ apiKey: apiKey,
132
+ localLink: localLink,
133
+ });
134
+
135
+ if (response.success && response.data && 'roomName' in response.data) {
136
+ await checkLimitsAndMakeRequest({
137
+ apiUserName: response.data.roomName,
138
+ apiToken: response.data.secret,
139
+ link: response.data.link,
140
+ userName: payload.userName,
141
+ parameters: parameters,
142
+ });
143
+ } else {
144
+ updateIsLoadingModalVisible(false);
145
+ showAlert?.({
146
+ message: `Unable to join room. ${
147
+ response.data ? ('error' in response.data ? response.data.error : '') : ''
148
+ }`,
149
+ type: 'danger',
150
+ duration: 3000,
151
+ });
152
+ }
153
+ }
@@ -0,0 +1,14 @@
1
+ export { handleCreateRoom } from './handleCreateRoom';
2
+ export type {
3
+ HandleCreateRoomOptions,
4
+ CreateLocalRoomParameters,
5
+ CreateLocalRoomOptions,
6
+ CreateJoinLocalRoomResponse,
7
+ } from './handleCreateRoom';
8
+
9
+ export { handleJoinRoom } from './handleJoinRoom';
10
+ export type {
11
+ HandleJoinRoomOptions,
12
+ JoinLocalEventRoomParameters,
13
+ JoinLocalEventRoomOptions,
14
+ } from './handleJoinRoom';
@@ -0,0 +1,57 @@
1
+ import type { ShowAlert } from '../../types/types'
2
+
3
+ export interface CheckPauseStateOptions {
4
+ recordingMediaOptions: string
5
+ recordingVideoPausesLimit: number
6
+ recordingAudioPausesLimit: number
7
+ pauseRecordCount: number
8
+ showAlert?: ShowAlert
9
+ }
10
+
11
+ export type CheckPauseStateType = (options: CheckPauseStateOptions) => Promise<boolean>
12
+
13
+ /**
14
+ * Checks if the recording can be paused based on the current pause count and the allowed pause limits.
15
+ *
16
+ * @param {Object} options - The options for checking the pause state.
17
+ * @param {string} options.recordingMediaOptions - The type of media being recorded ("video" or "audio").
18
+ * @param {number} options.recordingVideoPausesLimit - The maximum number of pauses allowed for video recordings.
19
+ * @param {number} options.recordingAudioPausesLimit - The maximum number of pauses allowed for audio recordings.
20
+ * @param {number} options.pauseRecordCount - The current count of pauses that have been made.
21
+ * @param {Function} options.showAlert - Function to show an alert message if the pause limit is reached.
22
+ *
23
+ * @returns {Promise<boolean>} - Resolves to `true` if the recording can be paused, otherwise `false`.
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * const canPause = await checkPauseState({
28
+ * recordingMediaOptions: 'audio',
29
+ * recordingVideoPausesLimit: 3,
30
+ * recordingAudioPausesLimit: 5,
31
+ * pauseRecordCount: 4,
32
+ * showAlert: ({ message }) => console.log(message),
33
+ * })
34
+ * ```
35
+ */
36
+ export const checkPauseState: CheckPauseStateType = async ({
37
+ recordingMediaOptions,
38
+ recordingVideoPausesLimit,
39
+ recordingAudioPausesLimit,
40
+ pauseRecordCount,
41
+ showAlert,
42
+ }) => {
43
+ const refLimit = recordingMediaOptions === 'video'
44
+ ? recordingVideoPausesLimit
45
+ : recordingAudioPausesLimit
46
+
47
+ if (pauseRecordCount < refLimit) {
48
+ return true
49
+ }
50
+
51
+ showAlert?.({
52
+ message: 'You have reached the limit of pauses - you can choose to stop recording.',
53
+ type: 'danger',
54
+ duration: 3000,
55
+ })
56
+ return false
57
+ }
@@ -0,0 +1,42 @@
1
+ export interface CheckResumeStateOptions {
2
+ recordingMediaOptions: string
3
+ recordingVideoPausesLimit: number
4
+ recordingAudioPausesLimit: number
5
+ pauseRecordCount: number
6
+ }
7
+
8
+ export type CheckResumeStateType = (options: CheckResumeStateOptions) => Promise<boolean>
9
+
10
+ /**
11
+ * Checks if the recording can be resumed based on the media type and pause limits.
12
+ *
13
+ * @param {Object} options - The options for checking resume state.
14
+ * @param {string} options.recordingMediaOptions - The type of media being recorded ("video" or "audio").
15
+ * @param {number} options.recordingVideoPausesLimit - The maximum number of pauses allowed for video recording.
16
+ * @param {number} options.recordingAudioPausesLimit - The maximum number of pauses allowed for audio recording.
17
+ * @param {number} options.pauseRecordCount - The current number of pauses that have occurred.
18
+ *
19
+ * @returns {Promise<boolean>} - Resolves to `true` if the recording can be resumed, otherwise `false`.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const canResume = await checkResumeState({
24
+ * recordingMediaOptions: 'video',
25
+ * recordingVideoPausesLimit: 3,
26
+ * recordingAudioPausesLimit: 5,
27
+ * pauseRecordCount: 2,
28
+ * })
29
+ * ```
30
+ */
31
+ export const checkResumeState: CheckResumeStateType = async ({
32
+ recordingMediaOptions,
33
+ recordingVideoPausesLimit,
34
+ recordingAudioPausesLimit,
35
+ pauseRecordCount,
36
+ }) => {
37
+ const refLimit = recordingMediaOptions === 'video'
38
+ ? recordingVideoPausesLimit
39
+ : recordingAudioPausesLimit
40
+
41
+ return pauseRecordCount <= refLimit
42
+ }