mediasfu-shared 1.0.1 → 1.0.3

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 (127) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +103 -222
  3. package/dist/index.cjs +7634 -2180
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.ts +4203 -273
  6. package/dist/index.js +7663 -2209
  7. package/dist/index.js.map +1 -1
  8. package/package.json +96 -78
  9. package/src/ProducerClient/producerClientEmits/joinRoomClient.ts +57 -0
  10. package/src/ProducerClient/producerClientEmits/updateRoomParametersClient.ts +401 -0
  11. package/src/consumers/addVideosGrid.ts +3 -2
  12. package/src/consumers/changeVids.ts +111 -41
  13. package/src/consumers/checkPermission.ts +35 -1
  14. package/src/consumers/connectIps.ts +3 -1
  15. package/src/consumers/connectLocalIps.ts +3 -1
  16. package/src/consumers/connectRecvTransport.ts +96 -1
  17. package/src/consumers/consumerResume.ts +2 -2
  18. package/src/consumers/dispStreams.ts +83 -37
  19. package/src/consumers/frameworkConsumerContract.ts +6 -0
  20. package/src/consumers/generatePageContent.ts +24 -10
  21. package/src/consumers/getPipedProducersAlt.ts +112 -16
  22. package/src/consumers/gridLayout/addVideosGrid.engine.ts +42 -0
  23. package/src/consumers/gridLayout/prepopulateUserMedia.engine.ts +444 -0
  24. package/src/consumers/mixStreams.ts +45 -14
  25. package/src/consumers/onScreenChanges.ts +25 -10
  26. package/src/consumers/prepopulateUserMedia.ts +3 -2
  27. package/src/consumers/processConsumerTransports.ts +68 -23
  28. package/src/consumers/processConsumerTransportsAudio.ts +146 -17
  29. package/src/consumers/reUpdateInter.ts +61 -21
  30. package/src/consumers/readjust.ts +30 -14
  31. package/src/consumers/reorderStreams.ts +76 -42
  32. package/src/consumers/resumePauseAudioStreams.ts +66 -17
  33. package/src/consumers/resumePauseStreams.ts +53 -10
  34. package/src/consumers/socketReceiveMethods/joinConsumeRoom.ts +8 -0
  35. package/src/consumers/socketReceiveMethods/newPipeProducer.ts +114 -0
  36. package/src/consumers/socketReceiveMethods/producerClosed.ts +13 -0
  37. package/src/consumers/streamSuccessScreen.ts +2 -2
  38. package/src/consumers/streamSuccessVideo.ts +5 -0
  39. package/src/consumers/translationConsumerSwitch.ts +321 -0
  40. package/src/index.ts +85 -1
  41. package/src/methods/coHostMethods/modifyCoHostSettings.ts +9 -9
  42. package/src/methods/displaySettings/modifyDisplaySettings.ts +5 -0
  43. package/src/methods/index.ts +66 -0
  44. package/src/methods/message/sendMessage.ts +12 -29
  45. package/src/methods/panelists/focusPanelists.ts +83 -0
  46. package/src/methods/panelists/index.ts +3 -0
  47. package/src/methods/panelists/launchPanelists.ts +13 -0
  48. package/src/methods/panelists/updatePanelists.ts +135 -0
  49. package/src/methods/permissions/index.ts +3 -0
  50. package/src/methods/permissions/launchPermissions.ts +13 -0
  51. package/src/methods/permissions/updateParticipantPermission.ts +127 -0
  52. package/src/methods/permissions/updatePermissionConfig.ts +52 -0
  53. package/src/methods/polls/pollUpdated.ts +88 -0
  54. package/src/methods/recording/confirmRecording.ts +15 -12
  55. package/src/methods/recording/recordResumeTimer.ts +2 -2
  56. package/src/methods/recording/recordStartTimer.ts +2 -2
  57. package/src/methods/recording/timeLeftRecording.ts +25 -0
  58. package/src/methods/requests/hostRequestResponse.ts +158 -0
  59. package/src/methods/settings/modifySettings.ts +17 -17
  60. package/src/methods/socketReceive/allMembers.ts +450 -0
  61. package/src/methods/socketReceive/allMembersRest.ts +480 -0
  62. package/src/methods/socketReceive/allWaitingRoomMembers.ts +35 -0
  63. package/src/methods/socketReceive/banParticipant.ts +73 -0
  64. package/src/methods/socketReceive/controlMediaHost.ts +280 -0
  65. package/src/methods/socketReceive/disconnect.ts +40 -0
  66. package/src/methods/socketReceive/disconnectUserSelf.ts +56 -0
  67. package/src/methods/socketReceive/getDomains.ts +112 -0
  68. package/src/methods/socketReceive/meetingEnded.ts +49 -0
  69. package/src/methods/socketReceive/meetingStillThere.ts +26 -0
  70. package/src/methods/socketReceive/panelistReceiveMethods.ts +195 -0
  71. package/src/methods/socketReceive/participantRequested.ts +48 -0
  72. package/src/methods/socketReceive/permissionReceiveMethods.ts +59 -0
  73. package/src/methods/socketReceive/personJoined.ts +35 -0
  74. package/src/methods/socketReceive/producerMediaClosed.ts +223 -0
  75. package/src/methods/socketReceive/producerMediaPaused.ts +267 -0
  76. package/src/methods/socketReceive/producerMediaResumed.ts +157 -0
  77. package/src/methods/socketReceive/reInitiateRecording.ts +53 -0
  78. package/src/methods/socketReceive/receiveMessage.ts +117 -0
  79. package/src/methods/socketReceive/recordingNotice.ts +286 -0
  80. package/src/methods/socketReceive/roomRecordParams.ts +122 -0
  81. package/src/methods/socketReceive/screenProducerId.ts +61 -0
  82. package/src/methods/socketReceive/startRecords.ts +46 -0
  83. package/src/methods/socketReceive/stoppedRecording.ts +44 -0
  84. package/src/methods/socketReceive/translationReceiveMethods.ts +581 -0
  85. package/src/methods/socketReceive/updateConsumingDomains.ts +128 -0
  86. package/src/methods/socketReceive/updateMediaSettings.ts +45 -0
  87. package/src/methods/socketReceive/updatedCoHost.ts +75 -0
  88. package/src/methods/socketReceive/userWaiting.ts +45 -0
  89. package/src/methods/stream/clickAudio.ts +380 -0
  90. package/src/methods/stream/clickChat.ts +36 -0
  91. package/src/methods/stream/clickScreenShare.ts +173 -0
  92. package/src/methods/stream/clickVideo.ts +28 -6
  93. package/src/methods/stream/index.ts +1 -0
  94. package/src/methods/utils/SoundPlayer.ts +31 -0
  95. package/src/methods/utils/checkLimitsAndMakeRequest.ts +156 -2
  96. package/src/methods/utils/createResponseJoinRoom.ts +47 -0
  97. package/src/methods/utils/createRoomOnMediaSFU.ts +160 -0
  98. package/src/methods/utils/formatNumber.ts +42 -0
  99. package/src/methods/utils/generateRandomMessages.ts +70 -0
  100. package/src/methods/utils/generateRandomParticipants.ts +100 -0
  101. package/src/methods/utils/generateRandomPolls.ts +43 -0
  102. package/src/methods/utils/generateRandomRequestList.ts +51 -0
  103. package/src/methods/utils/generateRandomWaitingRoomList.ts +17 -0
  104. package/src/methods/utils/getModalPosition.ts +23 -0
  105. package/src/methods/utils/getOverlayPosition.ts +37 -0
  106. package/src/methods/utils/initialValuesState.ts +405 -0
  107. package/src/methods/utils/joinRoomOnMediaSFU.ts +124 -0
  108. package/src/methods/utils/liveSubtitle.ts +107 -0
  109. package/src/methods/utils/meetingTimeRemaining.ts +33 -0
  110. package/src/methods/utils/meetingTimer/startMeetingProgressTimer.ts +72 -0
  111. package/src/methods/utils/producer/aParams.ts +10 -0
  112. package/src/methods/utils/producer/hParams.ts +26 -0
  113. package/src/methods/utils/producer/screenParams.ts +13 -0
  114. package/src/methods/utils/producer/vParams.ts +26 -0
  115. package/src/methods/utils/producer/videoCaptureConstraints.ts +65 -0
  116. package/src/methods/utils/resolveMediaSFURoomApi.ts +28 -0
  117. package/src/methods/utils/sleep.ts +24 -0
  118. package/src/methods/utils/translationLanguages.ts +308 -0
  119. package/src/methods/utils/webrtc.ts +44 -0
  120. package/src/methods/welcome/handleWelcomeRequest.ts +11 -2
  121. package/src/methods/welcome/index.ts +5 -1
  122. package/src/methods/whiteboard/captureCanvasStream.ts +128 -0
  123. package/src/producers/producerEmits/joinConRoom.ts +2 -2
  124. package/src/producers/producerEmits/joinLocalRoom.ts +240 -0
  125. package/src/producers/producerEmits/joinRoom.ts +129 -0
  126. package/src/types/shared-base-types.ts +14 -3
  127. package/src/types/types.ts +255 -0
@@ -0,0 +1,45 @@
1
+ import type { Settings } from '../../types/types';
2
+
3
+ export interface UpdateMediaSettingsOptions {
4
+ settings: Settings;
5
+ updateAudioSetting: (value: string) => void;
6
+ updateVideoSetting: (value: string) => void;
7
+ updateScreenshareSetting: (value: string) => void;
8
+ updateChatSetting: (value: string) => void;
9
+ }
10
+
11
+ export type UpdateMediaSettingsType = (
12
+ options: UpdateMediaSettingsOptions,
13
+ ) => void;
14
+
15
+ /**
16
+ * Expands the shared `Settings` tuple into individual media setting updaters.
17
+ *
18
+ * @param {UpdateMediaSettingsOptions} options - Settings tuple and update callbacks.
19
+ * @returns {void} Updates state synchronously.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * updateMediaSettings({
24
+ * settings: ['allow', 'allow', 'deny', 'allow'],
25
+ * updateAudioSetting: setAudioSetting,
26
+ * updateVideoSetting: setVideoSetting,
27
+ * updateScreenshareSetting: setScreenshareSetting,
28
+ * updateChatSetting: setChatSetting,
29
+ * });
30
+ * ```
31
+ */
32
+ export const updateMediaSettings = ({
33
+ settings,
34
+ updateAudioSetting,
35
+ updateVideoSetting,
36
+ updateScreenshareSetting,
37
+ updateChatSetting,
38
+ }: UpdateMediaSettingsOptions): void => {
39
+ const [audioSetting, videoSetting, screenshareSetting, chatSetting] = settings;
40
+
41
+ updateAudioSetting(audioSetting);
42
+ updateVideoSetting(videoSetting);
43
+ updateScreenshareSetting(screenshareSetting);
44
+ updateChatSetting(chatSetting);
45
+ };
@@ -0,0 +1,75 @@
1
+ import type {
2
+ CoHostResponsibility,
3
+ EventType,
4
+ ShowAlert,
5
+ } from '../../types/types';
6
+
7
+ export interface UpdatedCoHostOptions {
8
+ coHost: string;
9
+ coHostResponsibility: CoHostResponsibility[];
10
+ showAlert?: ShowAlert;
11
+ eventType: EventType;
12
+ islevel: string;
13
+ member: string;
14
+ youAreCoHost: boolean;
15
+ updateCoHost: (coHost: string) => void;
16
+ updateCoHostResponsibility: (responsibility: CoHostResponsibility[]) => void;
17
+ updateYouAreCoHost: (youAreCoHost: boolean) => void;
18
+ }
19
+
20
+ export type UpdatedCoHostType = (options: UpdatedCoHostOptions) => Promise<void>;
21
+
22
+ /**
23
+ * Synchronizes co-host assignment state and optionally alerts the newly assigned co-host.
24
+ *
25
+ * @param {UpdatedCoHostOptions} options - Co-host payload and state setters.
26
+ * @returns {Promise<void>} Resolves after co-host state is synchronized.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * await updatedCoHost({
31
+ * coHost: 'user123',
32
+ * coHostResponsibility: responsibilities,
33
+ * eventType: 'conference',
34
+ * islevel: '1',
35
+ * member: 'user123',
36
+ * youAreCoHost: false,
37
+ * updateCoHost: setCoHost,
38
+ * updateCoHostResponsibility: setCoHostResponsibility,
39
+ * updateYouAreCoHost: setYouAreCoHost,
40
+ * showAlert,
41
+ * });
42
+ * ```
43
+ */
44
+ export const updatedCoHost = async ({
45
+ coHost,
46
+ coHostResponsibility,
47
+ showAlert,
48
+ eventType,
49
+ islevel,
50
+ member,
51
+ youAreCoHost,
52
+ updateCoHost,
53
+ updateCoHostResponsibility,
54
+ updateYouAreCoHost,
55
+ }: UpdatedCoHostOptions): Promise<void> => {
56
+ if (eventType !== 'broadcast' && eventType !== 'chat') {
57
+ updateCoHost(coHost);
58
+ updateCoHostResponsibility(coHostResponsibility);
59
+
60
+ if (member === coHost) {
61
+ if (!youAreCoHost) {
62
+ updateYouAreCoHost(true);
63
+ showAlert?.({
64
+ message: 'You are now a co-host.',
65
+ type: 'success',
66
+ duration: 3000,
67
+ });
68
+ }
69
+ } else {
70
+ updateYouAreCoHost(false);
71
+ }
72
+ } else if (islevel !== '2') {
73
+ updateYouAreCoHost(true);
74
+ }
75
+ };
@@ -0,0 +1,45 @@
1
+ import type { ShowAlert } from '../../types/types';
2
+
3
+ export interface UserWaitingOptions {
4
+ name: string;
5
+ showAlert?: ShowAlert;
6
+ totalReqWait: number;
7
+ updateTotalReqWait: (total: number) => void;
8
+ }
9
+
10
+ export type UserWaitingType = (options: UserWaitingOptions) => Promise<void>;
11
+
12
+ /**
13
+ * Handles a participant joining the waiting room by notifying the UI and bumping the pending total.
14
+ *
15
+ * @param {UserWaitingOptions} options - Waiting-room notification settings.
16
+ * @param {string} options.name - Participant name shown in the alert.
17
+ * @param {ShowAlert} [options.showAlert] - Optional alert presenter.
18
+ * @param {number} options.totalReqWait - Current combined waiting/request count.
19
+ * @param {(total: number) => void} options.updateTotalReqWait - Updates the combined waiting/request count.
20
+ * @returns {Promise<void>} Resolves after state updates complete.
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * await userWaiting({
25
+ * name: 'Ada',
26
+ * totalReqWait: 2,
27
+ * updateTotalReqWait: setTotalReqWait,
28
+ * showAlert: ({ message }) => console.log(message),
29
+ * });
30
+ * ```
31
+ */
32
+ export const userWaiting = async ({
33
+ name,
34
+ showAlert,
35
+ totalReqWait,
36
+ updateTotalReqWait,
37
+ }: UserWaitingOptions): Promise<void> => {
38
+ showAlert?.({
39
+ message: `${name} joined the waiting room.`,
40
+ type: 'success',
41
+ duration: 3000,
42
+ });
43
+
44
+ updateTotalReqWait(totalReqWait + 1);
45
+ };
@@ -0,0 +1,380 @@
1
+ import { Socket } from 'socket.io-client';
2
+ import {
3
+ CheckPermissionType,
4
+ DisconnectSendTransportAudioParameters,
5
+ DisconnectSendTransportAudioType,
6
+ Participant,
7
+ RequestPermissionAudioType,
8
+ ResumeSendTransportAudioParameters,
9
+ ResumeSendTransportAudioType,
10
+ ShowAlert,
11
+ StreamSuccessAudioParameters,
12
+ StreamSuccessAudioType,
13
+ } from '../../types/types';
14
+ import type { PermissionConfig } from '../permissions/updatePermissionConfig';
15
+
16
+ export interface ClickAudioParameters
17
+ extends DisconnectSendTransportAudioParameters,
18
+ ResumeSendTransportAudioParameters,
19
+ StreamSuccessAudioParameters {
20
+ checkMediaPermission: boolean;
21
+ hasAudioPermission: boolean;
22
+ audioPaused: boolean;
23
+ audioAlreadyOn: boolean;
24
+ audioOnlyRoom: boolean;
25
+ recordStarted: boolean;
26
+ recordResumed: boolean;
27
+ recordPaused: boolean;
28
+ recordStopped: boolean;
29
+ recordingMediaOptions: string;
30
+ islevel: string;
31
+ youAreCoHost: boolean;
32
+ adminRestrictSetting: boolean;
33
+ audioRequestState: string | null;
34
+ audioRequestTime: number;
35
+ member: string;
36
+ socket: Socket;
37
+ localSocket?: Socket;
38
+ roomName: string;
39
+ userDefaultAudioInputDevice: string;
40
+ micAction: boolean;
41
+ localStream: MediaStream | null;
42
+ audioSetting: string;
43
+ videoSetting: string;
44
+ screenshareSetting: string;
45
+ chatSetting: string;
46
+ permissionConfig?: PermissionConfig | null;
47
+ updateRequestIntervalSeconds: number;
48
+ participants: Participant[];
49
+ mediaDevices: MediaDevices;
50
+ transportCreated: boolean;
51
+ transportCreatedAudio: boolean;
52
+ supportFlexRoom?: boolean;
53
+ supportMaxRoom?: boolean;
54
+
55
+ updateAudioAlreadyOn: (status: boolean) => void;
56
+ updateAudioRequestState: (state: string | null) => void;
57
+ updateAudioPaused: (status: boolean) => void;
58
+ updateLocalStream: (stream: MediaStream | null) => void;
59
+ updateParticipants: (participants: Participant[]) => void;
60
+ updateTransportCreated: (status: boolean) => void;
61
+ updateTransportCreatedAudio: (status: boolean) => void;
62
+ updateMicAction: (action: boolean) => void;
63
+ showAlert?: ShowAlert;
64
+
65
+ checkPermission: CheckPermissionType;
66
+ streamSuccessAudio: StreamSuccessAudioType;
67
+ disconnectSendTransportAudio: DisconnectSendTransportAudioType;
68
+ requestPermissionAudio: RequestPermissionAudioType;
69
+ resumeSendTransportAudio: ResumeSendTransportAudioType;
70
+
71
+ getUpdatedAllParams: () => ClickAudioParameters;
72
+ [key: string]: any;
73
+ }
74
+
75
+ export interface ClickAudioOptions {
76
+ parameters: ClickAudioParameters;
77
+ }
78
+
79
+ export type ClickAudioType = (options: ClickAudioOptions) => Promise<void>;
80
+
81
+ /**
82
+ * Handles microphone toggle flow for a participant.
83
+ *
84
+ * This helper enforces host permission rules, request cooldowns, recording
85
+ * constraints, and transport resume/disconnect behavior before updating the
86
+ * caller's local media state.
87
+ *
88
+ * @param options Function options containing the full runtime parameter bag.
89
+ * @returns A promise that resolves after the microphone action has been processed.
90
+ */
91
+ export const clickAudio = async ({ parameters }: ClickAudioOptions): Promise<void> => {
92
+ let {
93
+ checkMediaPermission,
94
+ hasAudioPermission,
95
+ audioPaused,
96
+ audioAlreadyOn,
97
+ audioOnlyRoom,
98
+ recordStarted,
99
+ recordResumed,
100
+ recordPaused,
101
+ recordStopped,
102
+ recordingMediaOptions,
103
+ islevel,
104
+ youAreCoHost,
105
+ adminRestrictSetting,
106
+ audioRequestState,
107
+ audioRequestTime,
108
+ member,
109
+ socket,
110
+ localSocket,
111
+ roomName,
112
+ userDefaultAudioInputDevice,
113
+ micAction,
114
+ localStream,
115
+ audioSetting,
116
+ videoSetting,
117
+ screenshareSetting,
118
+ chatSetting,
119
+ updateRequestIntervalSeconds,
120
+ participants,
121
+ mediaDevices,
122
+ showAlert,
123
+ transportCreated,
124
+ transportCreatedAudio,
125
+
126
+ updateAudioAlreadyOn,
127
+ updateAudioRequestState,
128
+ updateAudioPaused,
129
+ updateLocalStream,
130
+ updateParticipants,
131
+ updateTransportCreated,
132
+ updateTransportCreatedAudio,
133
+ updateMicAction,
134
+
135
+ checkPermission,
136
+ streamSuccessAudio,
137
+ requestPermissionAudio,
138
+ resumeSendTransportAudio,
139
+ disconnectSendTransportAudio,
140
+ } = parameters;
141
+
142
+ if (audioOnlyRoom) {
143
+ showAlert?.({
144
+ message: 'You cannot turn on your camera in an audio-only event.',
145
+ type: 'danger',
146
+ duration: 3000,
147
+ });
148
+ return;
149
+ }
150
+
151
+ if (audioAlreadyOn) {
152
+ if (islevel === '2' && (recordStarted || recordResumed)) {
153
+ if (!(recordPaused || recordStopped)) {
154
+ if (recordingMediaOptions === 'audio') {
155
+ showAlert?.({
156
+ message: 'You cannot turn off your audio while recording, please pause or stop recording first.',
157
+ type: 'danger',
158
+ duration: 3000,
159
+ });
160
+ return;
161
+ }
162
+ }
163
+ }
164
+
165
+ audioAlreadyOn = false;
166
+ updateAudioAlreadyOn(audioAlreadyOn);
167
+ if (localStream && localStream.getAudioTracks().length > 0) {
168
+ localStream.getAudioTracks()[0].enabled = false;
169
+ updateLocalStream(localStream);
170
+ }
171
+ await disconnectSendTransportAudio({ parameters });
172
+ audioPaused = true;
173
+ updateAudioPaused(audioPaused);
174
+ } else {
175
+ if (adminRestrictSetting) {
176
+ showAlert?.({
177
+ message: 'You cannot turn on your microphone. Access denied by host.',
178
+ type: 'danger',
179
+ duration: 3000,
180
+ });
181
+ return;
182
+ }
183
+
184
+ const supportMaxRoom = parameters.supportMaxRoom;
185
+ const supportFlexRoom = parameters.supportFlexRoom;
186
+ if ((supportMaxRoom || supportFlexRoom) && islevel !== '2') {
187
+ try {
188
+ const checkResult = await new Promise<{
189
+ allowed: boolean;
190
+ reason?: string;
191
+ producingCount?: number;
192
+ producerLimit?: number;
193
+ }>((resolve) => {
194
+ socket.emit(
195
+ 'checkProduce',
196
+ { kind: 'audio' },
197
+ (response: {
198
+ allowed: boolean;
199
+ reason?: string;
200
+ producingCount?: number;
201
+ producerLimit?: number;
202
+ }) => {
203
+ resolve(response || { allowed: false, reason: 'No response from server' });
204
+ },
205
+ );
206
+
207
+ setTimeout(() => resolve({ allowed: true }), 5000);
208
+ });
209
+
210
+ if (!checkResult.allowed) {
211
+ showAlert?.({
212
+ message:
213
+ checkResult.reason ||
214
+ `Audio producer limit reached (${checkResult.producingCount}/${checkResult.producerLimit}).`,
215
+ type: 'danger',
216
+ duration: 3000,
217
+ });
218
+ return;
219
+ }
220
+ } catch (error) {
221
+ console.warn('Failed to check producer limit:', error);
222
+ }
223
+ }
224
+
225
+ const panelistsFocused = parameters.panelistsFocused;
226
+ const muteOthersMic = parameters.muteOthersMic;
227
+ const panelists = parameters.panelists;
228
+
229
+ if (panelistsFocused && muteOthersMic && islevel !== '2') {
230
+ const isPanelist =
231
+ panelists?.some((panelist: { name: string }) => panelist.name === member) || false;
232
+
233
+ if (!isPanelist) {
234
+ showAlert?.({
235
+ message:
236
+ 'You cannot turn on your microphone. Only panelists can unmute while focus mode is active.',
237
+ type: 'danger',
238
+ duration: 3000,
239
+ });
240
+ return;
241
+ }
242
+ }
243
+
244
+ let response = 2;
245
+ if (!micAction && islevel !== '2' && !youAreCoHost) {
246
+ response = await checkPermission({
247
+ permissionType: 'audioSetting',
248
+ audioSetting,
249
+ videoSetting,
250
+ screenshareSetting,
251
+ chatSetting,
252
+ permissionConfig: parameters.permissionConfig,
253
+ participantLevel: islevel,
254
+ });
255
+ } else {
256
+ response = 0;
257
+ }
258
+
259
+ switch (response) {
260
+ case 1: {
261
+ if (audioRequestState === 'pending') {
262
+ showAlert?.({
263
+ message: 'A request is pending. Please wait for the host to respond.',
264
+ type: 'danger',
265
+ duration: 3000,
266
+ });
267
+ return;
268
+ }
269
+
270
+ if (
271
+ audioRequestState === 'rejected' &&
272
+ Date.now() - audioRequestTime < updateRequestIntervalSeconds * 1000
273
+ ) {
274
+ showAlert?.({
275
+ message: `A request was rejected. Please wait for ${updateRequestIntervalSeconds} seconds before sending another request.`,
276
+ type: 'danger',
277
+ duration: 3000,
278
+ });
279
+ return;
280
+ }
281
+
282
+ showAlert?.({
283
+ message: 'Request sent to host.',
284
+ type: 'success',
285
+ duration: 3000,
286
+ });
287
+
288
+ audioRequestState = 'pending';
289
+ updateAudioRequestState(audioRequestState);
290
+
291
+ const userRequest = {
292
+ id: socket.id,
293
+ name: member,
294
+ icon: 'fa-microphone',
295
+ };
296
+ socket.emit('participantRequest', { userRequest, roomName });
297
+ break;
298
+ }
299
+
300
+ case 2:
301
+ showAlert?.({
302
+ message: 'You cannot turn on your microphone. Access denied by host.',
303
+ type: 'danger',
304
+ duration: 3000,
305
+ });
306
+ break;
307
+
308
+ case 0:
309
+ if (audioPaused) {
310
+ if (localStream && localStream.getAudioTracks().length > 0) {
311
+ localStream.getAudioTracks()[0].enabled = true;
312
+ }
313
+ updateAudioAlreadyOn(true);
314
+ await resumeSendTransportAudio({ parameters });
315
+ socket.emit('resumeProducerAudio', { mediaTag: 'audio', roomName });
316
+
317
+ try {
318
+ if (localSocket && localSocket.id) {
319
+ localSocket.emit('resumeProducerAudio', { mediaTag: 'audio', roomName });
320
+ }
321
+ } catch (error) {
322
+ console.log('Error in resumeProducerAudio', error);
323
+ }
324
+
325
+ updateLocalStream(localStream);
326
+
327
+ if (micAction === true) {
328
+ micAction = false;
329
+ updateMicAction(micAction);
330
+ }
331
+
332
+ participants.forEach((participant) => {
333
+ if (participant.socketId === socket.id && participant.name === member) {
334
+ participant.muted = false;
335
+ }
336
+ });
337
+ updateParticipants(participants);
338
+
339
+ transportCreated = true;
340
+ updateTransportCreated(transportCreated);
341
+
342
+ transportCreatedAudio = true;
343
+ updateTransportCreatedAudio(transportCreatedAudio);
344
+ } else {
345
+ if (!hasAudioPermission && checkMediaPermission) {
346
+ const statusMic = await requestPermissionAudio();
347
+ if (statusMic !== 'granted') {
348
+ showAlert?.({
349
+ message:
350
+ 'Allow access to your microphone or check if your microphone is not being used by another application.',
351
+ type: 'danger',
352
+ duration: 3000,
353
+ });
354
+ return;
355
+ }
356
+ }
357
+
358
+ const mediaConstraints = userDefaultAudioInputDevice
359
+ ? { audio: { deviceId: userDefaultAudioInputDevice }, video: false }
360
+ : { audio: true, video: false };
361
+
362
+ try {
363
+ const stream = await mediaDevices.getUserMedia(mediaConstraints);
364
+ await streamSuccessAudio({ stream, parameters });
365
+ } catch (error) {
366
+ console.error(error);
367
+ showAlert?.({
368
+ message:
369
+ 'Allow access to your microphone or check if your microphone is not being used by another application.',
370
+ type: 'danger',
371
+ duration: 3000,
372
+ });
373
+ }
374
+ }
375
+ break;
376
+
377
+ default:
378
+ }
379
+ }
380
+ };
@@ -0,0 +1,36 @@
1
+ import type { ShowAlert } from '../../types/types';
2
+
3
+ export interface ClickChatOptions {
4
+ isMessagesModalVisible: boolean;
5
+ updateIsMessagesModalVisible: (isVisible: boolean) => void;
6
+ chatSetting: string;
7
+ islevel: string;
8
+ showAlert?: ShowAlert;
9
+ }
10
+
11
+ export type ClickChatType = (options: ClickChatOptions) => Promise<void>;
12
+
13
+ export const clickChat = async ({
14
+ isMessagesModalVisible,
15
+ updateIsMessagesModalVisible,
16
+ chatSetting,
17
+ islevel,
18
+ showAlert,
19
+ }: ClickChatOptions): Promise<void> => {
20
+ if (isMessagesModalVisible) {
21
+ updateIsMessagesModalVisible(false);
22
+ return;
23
+ }
24
+
25
+ if (chatSetting !== 'allow' && islevel !== '2') {
26
+ updateIsMessagesModalVisible(false);
27
+ showAlert?.({
28
+ message: 'Chat is disabled for this event.',
29
+ type: 'danger',
30
+ duration: 3000,
31
+ });
32
+ return;
33
+ }
34
+
35
+ updateIsMessagesModalVisible(true);
36
+ };