agora-appbuilder-core 4.0.0-spl.24 → 4.0.0-spl.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agora-appbuilder-core",
3
- "version": "4.0.0-spl.24",
3
+ "version": "4.0.0-spl.26",
4
4
  "description": "React Native template for RTE app builder",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -17,6 +17,7 @@
17
17
  "@sentry/react-native": "2.4.3",
18
18
  "@sentry/tracing": "6.2.1",
19
19
  "@supersami/rn-foreground-service": "^1.1.1",
20
+ "@types/lodash": "^4.17.6",
20
21
  "agora-react-native-rtm": "1.5.1",
21
22
  "agora-rtc-sdk-ng": "4.16.1",
22
23
  "agora-rtm-sdk": "1.5.1",
@@ -26,6 +27,7 @@
26
27
  "exponential-backoff": "3.1.0",
27
28
  "fetch-retry": "^5.0.6",
28
29
  "graphql": "15.5.0",
30
+ "lodash": "^4.17.21",
29
31
  "nanoevents": "7.0.1",
30
32
  "nanoid": "4.0.0",
31
33
  "nosleep.js": "0.12.0",
@@ -6110,6 +6112,11 @@
6110
6112
  "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
6111
6113
  "dev": true
6112
6114
  },
6115
+ "node_modules/@types/lodash": {
6116
+ "version": "4.17.6",
6117
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.6.tgz",
6118
+ "integrity": "sha512-OpXEVoCKSS3lQqjx9GGGOapBeuW5eUboYHRlHP9urXPX25IKZ6AnP5ZRxtVf63iieUbsHxLn8NQ5Nlftc6yzAA=="
6119
+ },
6113
6120
  "node_modules/@types/mime": {
6114
6121
  "version": "3.0.1",
6115
6122
  "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
@@ -34130,6 +34137,11 @@
34130
34137
  "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
34131
34138
  "dev": true
34132
34139
  },
34140
+ "@types/lodash": {
34141
+ "version": "4.17.6",
34142
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.6.tgz",
34143
+ "integrity": "sha512-OpXEVoCKSS3lQqjx9GGGOapBeuW5eUboYHRlHP9urXPX25IKZ6AnP5ZRxtVf63iieUbsHxLn8NQ5Nlftc6yzAA=="
34144
+ },
34133
34145
  "@types/mime": {
34134
34146
  "version": "3.0.1",
34135
34147
  "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
@@ -0,0 +1,112 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const babel = require('@babel/core');
4
+
5
+ const templateRoot = path.resolve(__dirname, '../..');
6
+
7
+ const compile = (relativePath) => {
8
+ const filename = path.join(templateRoot, relativePath);
9
+
10
+ return babel.transformSync(fs.readFileSync(filename, 'utf8'), {
11
+ babelrc: false,
12
+ configFile: false,
13
+ filename,
14
+ presets: [
15
+ '@babel/preset-react',
16
+ [
17
+ '@babel/preset-typescript',
18
+ {
19
+ allExtensions: true,
20
+ isTSX: true,
21
+ },
22
+ ],
23
+ [
24
+ '@babel/preset-env',
25
+ {
26
+ targets: {
27
+ node: 'current',
28
+ },
29
+ },
30
+ ],
31
+ ],
32
+ }).code;
33
+ };
34
+
35
+ const runtimeDependencies = (compiledCode) =>
36
+ Array.from(compiledCode.matchAll(/require\(["']([^"']+)["']\)/g), (match) =>
37
+ match[1],
38
+ );
39
+
40
+ describe('web module boundaries', () => {
41
+ test('SDK method events do not load the DeviceConfigure React component', () => {
42
+ const dependencies = runtimeDependencies(
43
+ compile('src/utils/SdkMethodEvents.ts'),
44
+ );
45
+
46
+ expect(dependencies).not.toContain('../components/DeviceConfigure');
47
+ });
48
+
49
+ test('customization app state delegates core hook creation to a leaf module', () => {
50
+ const dependencies = runtimeDependencies(
51
+ compile('customization-api/app-state.ts'),
52
+ );
53
+
54
+ expect(dependencies).not.toContain('../agora-rn-uikit');
55
+ expect(dependencies).toContain('./core-contexts');
56
+ });
57
+
58
+ test.each([
59
+ 'src/app-state/useLocalUserInfo.ts',
60
+ 'src/subComponents/recording/useRecording.tsx',
61
+ 'src/components/chat-messages/useChatMessages.tsx',
62
+ 'src/components/useUserPreference.tsx',
63
+ ])('%s does not load the public customization API barrel', (filename) => {
64
+ const dependencies = runtimeDependencies(compile(filename));
65
+
66
+ expect(dependencies).not.toContain('customization-api');
67
+ });
68
+
69
+ test.each([
70
+ [
71
+ 'src/components/meeting-info/useMeetingInfo.tsx',
72
+ '../../../customization-implementation/createHook',
73
+ ],
74
+ [
75
+ 'src/subComponents/recording/useRecording.tsx',
76
+ '../../../customization-implementation/createHook',
77
+ ],
78
+ [
79
+ 'src/components/chat-ui/useChatUIControl.tsx',
80
+ '../../../customization-implementation/createHook',
81
+ ],
82
+ [
83
+ 'src/components/chat-notification/useChatNotification.tsx',
84
+ '../../../customization-implementation/createHook',
85
+ ],
86
+ [
87
+ 'src/components/chat-messages/useChatMessages.tsx',
88
+ '../../../customization-implementation/createHook',
89
+ ],
90
+ [
91
+ 'src/components/useUserPreference.tsx',
92
+ '../../customization-implementation/createHook',
93
+ ],
94
+ [
95
+ 'src/utils/useLayout.tsx',
96
+ '../../customization-implementation/createHook',
97
+ ],
98
+ [
99
+ 'src/utils/useSidePanel.tsx',
100
+ '../../customization-implementation/createHook',
101
+ ],
102
+ ])(
103
+ '%s imports createHook without loading the customization implementation barrel',
104
+ (filename, createHookPath) => {
105
+ const dependencies = runtimeDependencies(compile(filename));
106
+
107
+ expect(dependencies).not.toContain('customization-implementation');
108
+ expect(dependencies).toContain(createHookPath);
109
+ },
110
+ );
111
+
112
+ });
@@ -1,8 +1,7 @@
1
1
  /**
2
2
  * Core contexts
3
3
  */
4
- import {createHook} from 'customization-implementation';
5
- import {RtcContext, RenderContext} from '../agora-rn-uikit';
4
+ import {useRtc, useRender} from './core-contexts';
6
5
 
7
6
  // commented for v1 release
8
7
  //import {default as DeviceContext} from '../src/components/DeviceContext';
@@ -10,11 +9,11 @@ import {RtcContext, RenderContext} from '../agora-rn-uikit';
10
9
  /**
11
10
  * The RTC app state exposes the internal RtcEngine object as well as dispatch interface to perform various actions.
12
11
  */
13
- export const useRtc = createHook(RtcContext);
12
+ export {useRtc};
14
13
  /**
15
14
  * The Render app state governs the information necessary to render each user content view displayed in the videocall screen.
16
15
  */
17
- export const useRender = createHook(RenderContext);
16
+ export {useRender};
18
17
 
19
18
  export {useLocalUserInfo} from '../src/app-state/useLocalUserInfo';
20
19
 
@@ -0,0 +1,10 @@
1
+ import createHook from '../customization-implementation/createHook';
2
+ import RtcContext from '../agora-rn-uikit/src/Contexts/RtcContext';
3
+ import RenderContext from '../agora-rn-uikit/src/Contexts/RenderContext';
4
+
5
+ /**
6
+ * Core hooks live in a dependency-free module so internal application code can
7
+ * consume them without evaluating the public customization API barrel.
8
+ */
9
+ export const useRtc = createHook(RtcContext);
10
+ export const useRender = createHook(RenderContext);
@@ -17,6 +17,7 @@
17
17
  "@sentry/react-native": "2.4.3",
18
18
  "@sentry/tracing": "6.2.1",
19
19
  "@supersami/rn-foreground-service": "^1.1.1",
20
+ "@types/lodash": "^4.17.6",
20
21
  "agora-react-native-rtm": "1.5.1",
21
22
  "agora-rtc-sdk-ng": "4.16.1",
22
23
  "agora-rtm-sdk": "1.5.1",
@@ -26,6 +27,7 @@
26
27
  "exponential-backoff": "3.1.0",
27
28
  "fetch-retry": "^5.0.6",
28
29
  "graphql": "15.5.0",
30
+ "lodash": "^4.17.21",
29
31
  "nanoevents": "7.0.1",
30
32
  "nanoid": "4.0.0",
31
33
  "nosleep.js": "0.12.0",
@@ -6110,6 +6112,11 @@
6110
6112
  "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
6111
6113
  "dev": true
6112
6114
  },
6115
+ "node_modules/@types/lodash": {
6116
+ "version": "4.17.6",
6117
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.6.tgz",
6118
+ "integrity": "sha512-OpXEVoCKSS3lQqjx9GGGOapBeuW5eUboYHRlHP9urXPX25IKZ6AnP5ZRxtVf63iieUbsHxLn8NQ5Nlftc6yzAA=="
6119
+ },
6113
6120
  "node_modules/@types/mime": {
6114
6121
  "version": "3.0.1",
6115
6122
  "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
@@ -34130,6 +34137,11 @@
34130
34137
  "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
34131
34138
  "dev": true
34132
34139
  },
34140
+ "@types/lodash": {
34141
+ "version": "4.17.6",
34142
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.6.tgz",
34143
+ "integrity": "sha512-OpXEVoCKSS3lQqjx9GGGOapBeuW5eUboYHRlHP9urXPX25IKZ6AnP5ZRxtVf63iieUbsHxLn8NQ5Nlftc6yzAA=="
34144
+ },
34133
34145
  "@types/mime": {
34134
34146
  "version": "3.0.1",
34135
34147
  "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
@@ -57,6 +57,7 @@
57
57
  "@sentry/react-native": "2.4.3",
58
58
  "@sentry/tracing": "6.2.1",
59
59
  "@supersami/rn-foreground-service": "^1.1.1",
60
+ "@types/lodash": "^4.17.6",
60
61
  "agora-react-native-rtm": "1.5.1",
61
62
  "agora-rtc-sdk-ng": "4.16.1",
62
63
  "agora-rtm-sdk": "1.5.1",
@@ -66,6 +67,7 @@
66
67
  "exponential-backoff": "3.1.0",
67
68
  "fetch-retry": "^5.0.6",
68
69
  "graphql": "15.5.0",
70
+ "lodash": "^4.17.21",
69
71
  "nanoevents": "7.0.1",
70
72
  "nanoid": "4.0.0",
71
73
  "nosleep.js": "0.12.0",
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, {useEffect} from 'react';
2
2
  import {
3
3
  CustomizationApiInterface,
4
4
  customize,
@@ -39,6 +39,7 @@ export interface AppBuilderSdkApiInterface {
39
39
  createCustomization: (
40
40
  customization: CustomizationApiInterface,
41
41
  ) => CustomizationApiInterface;
42
+ clearState: (stateKey: 'join' | 'all') => Promise<void>;
42
43
  customEvents: typeof customEvents;
43
44
  on: <T extends keyof userEventsMapInterface>(
44
45
  userEventName: T,
@@ -81,6 +82,15 @@ export const AppBuilderSdkApi: AppBuilderSdkApiInterface = {
81
82
  muteVideo: async (state) => {
82
83
  return await SDKMethodEventsManager.emit('muteVideo', state);
83
84
  },
85
+ clearState: async (stateKey) => {
86
+ switch (stateKey) {
87
+ case 'all':
88
+ case 'join':
89
+ return await SDKMethodEventsManager.emit('clearState', stateKey);
90
+ default:
91
+ throw new Error('Invalid identifier');
92
+ }
93
+ },
84
94
  createCustomization: customize,
85
95
  on: (userEventName, cb) => {
86
96
  console.log('SDKEvents: Event Registered', userEventName);
@@ -1,5 +1,5 @@
1
1
  import {useLocalUid} from '../../agora-rn-uikit';
2
- import {useRender} from 'customization-api';
2
+ import {useRender} from '../../customization-api/core-contexts';
3
3
 
4
4
  /**
5
5
  * The LocalUserInfo app state contains the local user information like uid, audio and video mute states etc.
@@ -8,6 +8,7 @@ import {
8
8
  } from './meeting-info/useMeetingInfo';
9
9
  import {CustomizationApiInterface} from 'customization-api';
10
10
  import {Unsubscribe} from 'nanoevents';
11
+ import {cloneDeep} from 'lodash';
11
12
 
12
13
  type extractPromises<T extends (...p: any) => any> = {
13
14
  res: Parameters<T>[0];
@@ -57,8 +58,8 @@ type SdkApiContextInterface = {
57
58
  onMuteAudio: (callback: _InternalSDKMethodEventsMap['muteAudio']) => void;
58
59
  onMuteVideo: (callback: _InternalSDKMethodEventsMap['muteVideo']) => void;
59
60
  clearState: (
60
- key: keyof _InternalSDKMethodEventsMap | 'enterRoom',
61
- param?: any,
61
+ key: keyof _InternalSDKMethodEventsMap | 'enterRoom' | 'all',
62
+ hard?: boolean,
62
63
  ) => void;
63
64
  };
64
65
 
@@ -80,7 +81,7 @@ const defaultMuteAllParticipantsListener = ((res, _, param) => {
80
81
  res();
81
82
  }) as _InternalSDKMethodEventsMap['muteAllParticipants'];
82
83
 
83
- const SdkApiInitState: SdkApiContextInterface = {
84
+ const SdkApiDefaultState: SdkApiContextInterface = {
84
85
  enterRoom: {
85
86
  set: () => {},
86
87
  },
@@ -100,6 +101,19 @@ const SdkApiInitState: SdkApiContextInterface = {
100
101
  onMuteAudio: (_) => {},
101
102
  clearState: () => {},
102
103
  };
104
+ const SdkApiInitState: SdkApiContextInterface = cloneDeep(SdkApiDefaultState);
105
+
106
+ export const clearStateGlobal = (
107
+ state: keyof SdkApiContextInterface | 'all',
108
+ ) => {
109
+ if (state === 'all') {
110
+ for (const key in SdkApiInitState)
111
+ SdkApiInitState[key] = cloneDeep(SdkApiDefaultState[key]);
112
+ } else {
113
+ //@ts-expect-error
114
+ SdkApiInitState[state] = cloneDeep(SdkApiDefaultState[state]);
115
+ }
116
+ };
103
117
 
104
118
  export const READ_ONLY_SdkApiInitState = SdkApiInitState;
105
119
 
@@ -111,9 +125,10 @@ export const SdkApiContext =
111
125
  let moduleEventsUnsub: any[] = [];
112
126
 
113
127
  type commonEventHandlers = {
114
- [K in keyof Omit<_InternalSDKMethodEventsMap, 'muteVideo' | 'muteAudio'>]?: (
115
- setter: (p: SdkApiContextInterface[K]) => void,
116
- ) => Unsubscribe;
128
+ [K in keyof Omit<
129
+ _InternalSDKMethodEventsMap,
130
+ 'muteVideo' | 'muteAudio' | 'flushQueue'
131
+ >]?: (setter: (p: SdkApiContextInterface[K]) => void) => Unsubscribe;
117
132
  };
118
133
 
119
134
  const commonEventHandlers: commonEventHandlers = {
@@ -209,6 +224,10 @@ const registerListener = () => {
209
224
  ),
210
225
  SDKMethodEventsManager.on('muteVideo', defaultMuteListener),
211
226
  SDKMethodEventsManager.on('muteAudio', defaultMuteListener),
227
+ SDKMethodEventsManager.on('clearState', (res, _, queue) => {
228
+ clearStateGlobal(queue);
229
+ res();
230
+ }),
212
231
  ];
213
232
  };
214
233
 
@@ -261,26 +280,31 @@ const SdkApiContextProvider: React.FC = (props) => {
261
280
  muteAudioListener.current = value;
262
281
  };
263
282
 
264
- const clearState: SdkApiContextInterface['clearState'] = (key) => {
283
+ const clearState: SdkApiContextInterface['clearState'] = (key, hard) => {
284
+ let fallthrough = false;
265
285
  switch (key) {
286
+ case 'all':
287
+ fallthrough = true;
266
288
  case 'join':
267
- setJoinState(SdkApiInitState.join);
268
- break;
289
+ setJoinState(hard ? SdkApiDefaultState.join : SdkApiInitState.join);
290
+ if (!fallthrough) break;
269
291
  case 'enterRoom':
270
292
  setEnterRoom(null);
271
- break;
293
+ if (!fallthrough) break;
272
294
  case 'customize':
273
- setUserCustomization(SdkApiInitState.customize);
274
- break;
295
+ setUserCustomization(
296
+ hard ? SdkApiDefaultState.customize : SdkApiInitState.customize,
297
+ );
298
+ if (!fallthrough) break;
275
299
  case 'microphoneDevice':
276
300
  setMicrophoneDeviceState({});
277
- break;
301
+ if (!fallthrough) break;
278
302
  case 'speakerDevice':
279
303
  setSpeakerDeviceState({});
280
- break;
304
+ if (!fallthrough) break;
281
305
  case 'cameraDevice':
282
306
  setCameraDeviceState({});
283
- break;
307
+ if (!fallthrough) break;
284
308
  case 'muteAllParticipants':
285
309
  setMuteAllParticipantsState((current) => {
286
310
  return {
@@ -288,12 +312,13 @@ const SdkApiContextProvider: React.FC = (props) => {
288
312
  promise: undefined,
289
313
  };
290
314
  });
315
+ if (!fallthrough) break;
291
316
  case 'muteVideo':
292
317
  setMuteVideoListener(defaultMuteListener);
293
- break;
318
+ if (!fallthrough) break;
294
319
  case 'muteAudio':
295
320
  setMuteVideoListener(defaultMuteListener);
296
- break;
321
+ if (!fallthrough) break;
297
322
  }
298
323
  };
299
324
 
@@ -353,6 +378,11 @@ const SdkApiContextProvider: React.FC = (props) => {
353
378
  SDKMethodEventsManager.on('muteAudio', (...args) => {
354
379
  muteAudioListener.current(...args);
355
380
  }),
381
+ SDKMethodEventsManager.on('clearState', (res, _, queue) => {
382
+ clearStateGlobal(queue);
383
+ clearState(queue, true);
384
+ res();
385
+ }),
356
386
  ];
357
387
 
358
388
  return () => {
@@ -9,9 +9,9 @@
9
9
  information visit https://appbuilder.agora.io.
10
10
  *********************************************
11
11
  */
12
- import {createHook} from 'customization-implementation';
12
+ import createHook from '../../../customization-implementation/createHook';
13
13
  import React, {useState, useEffect, useRef} from 'react';
14
- import {useRender, useRtc} from 'customization-api';
14
+ import {useRender, useRtc} from '../../../customization-api/core-contexts';
15
15
  import {SidePanelType} from '../../subComponents/SidePanelEnum';
16
16
  import {useLocalUid, UidType, RenderInterface} from '../../../agora-rn-uikit';
17
17
  import events, {EventPersistLevel} from '../../rtm-events-api';
@@ -9,7 +9,7 @@
9
9
  information visit https://appbuilder.agora.io.
10
10
  *********************************************
11
11
  */
12
- import {createHook} from 'customization-implementation';
12
+ import createHook from '../../../customization-implementation/createHook';
13
13
  import React, {SetStateAction, useState, useEffect} from 'react';
14
14
 
15
15
  export interface individualUnreadMessageCount {
@@ -9,7 +9,7 @@
9
9
  information visit https://appbuilder.agora.io.
10
10
  *********************************************
11
11
  */
12
- import {createHook} from 'customization-implementation';
12
+ import createHook from '../../../customization-implementation/createHook';
13
13
  import React, {SetStateAction, useState} from 'react';
14
14
  import {UidType} from '../../../agora-rn-uikit';
15
15
 
@@ -10,7 +10,7 @@
10
10
  *********************************************
11
11
  */
12
12
  import React, {createContext} from 'react';
13
- import {createHook} from 'customization-implementation';
13
+ import createHook from '../../../customization-implementation/createHook';
14
14
  import {UidType} from '../../../agora-rn-uikit';
15
15
  export interface MeetingInfoContextInterface {
16
16
  isJoinDataFetched?: boolean;
@@ -25,6 +25,7 @@ import {isMobileUA, useIsDesktop} from '../../utils/common';
25
25
  import {useVideoCall} from '../useVideoCall';
26
26
  import {useParams} from '../Router';
27
27
  import useGetMeetingPhrase from '../../utils/useGetMeetingPhrase';
28
+ import {SDK_MEETING_TAG} from '../SdkApiContext';
28
29
 
29
30
  const InvitePopup = () => {
30
31
  const {setShowInvitePopup, showInvitePopup} = useVideoCall();
@@ -33,8 +34,14 @@ const InvitePopup = () => {
33
34
  const {phrase} = useParams<{phrase: string}>();
34
35
  const getMeeting = useGetMeetingPhrase();
35
36
  useEffect(() => {
36
- getMeeting(phrase);
37
- }, [phrase]);
37
+ if (!phrase || phrase === SDK_MEETING_TAG) {
38
+ return;
39
+ }
40
+
41
+ getMeeting(phrase).catch((error) => {
42
+ console.error('Unable to load invite information', error);
43
+ });
44
+ }, [getMeeting, phrase]);
38
45
  return (
39
46
  <Popup
40
47
  modalVisible={showInvitePopup}
@@ -16,9 +16,9 @@ import StorageContext from './StorageContext';
16
16
  import events, {EventPersistLevel} from '../rtm-events-api';
17
17
  import {EventNames} from '../rtm-events';
18
18
  import useLocalScreenShareUid from '../utils/useLocalShareScreenUid';
19
- import {createHook} from 'customization-implementation';
19
+ import createHook from '../../customization-implementation/createHook';
20
20
  import ChatContext from './ChatContext';
21
- import {useRtc} from 'customization-api';
21
+ import {useRtc} from '../../customization-api/core-contexts';
22
22
 
23
23
  interface UserPreferenceContextInterface {
24
24
  displayName: string;
@@ -73,7 +73,7 @@ const VideoCallProvider = (props: VideoCallProviderProps) => {
73
73
  setShowLayoutOption,
74
74
  }}>
75
75
  <StopRecordingPopup />
76
- <InvitePopup />
76
+ {showInvitePopup ? <InvitePopup /> : null}
77
77
  {props.children}
78
78
  </VideoCallContext.Provider>
79
79
  );
@@ -21,14 +21,14 @@ import {gql, useMutation} from '@apollo/client';
21
21
  import {useParams} from '../../components/Router';
22
22
  import {PropsContext} from '../../../agora-rn-uikit';
23
23
  import Toast from '../../../react-native-toast-message';
24
- import {createHook} from 'customization-implementation';
24
+ import createHook from '../../../customization-implementation/createHook';
25
25
  import {useString} from '../../utils/useString';
26
26
  import ChatContext from '../../components/ChatContext';
27
27
  import events, {EventPersistLevel} from '../../rtm-events-api';
28
28
  import {EventActions, EventNames} from '../../rtm-events';
29
29
  import useRecordingLayoutQuery from './useRecordingLayoutQuery';
30
30
  import {useScreenContext} from '../../components/contexts/ScreenShareContext';
31
- import {useRender} from 'customization-api';
31
+ import {useRender} from '../../../customization-api/core-contexts';
32
32
  import {trimText} from '../../utils/common';
33
33
 
34
34
  export interface RecordingContextInterface {
@@ -1,9 +1,9 @@
1
1
  import {createNanoEvents, Emitter} from 'nanoevents';
2
- import {
2
+ import type {
3
3
  CustomizationApiInterface,
4
4
  MeetingInfoContextInterface,
5
5
  } from 'customization-api';
6
- import {deviceId} from '../components/DeviceConfigure';
6
+ import type {deviceId} from '../components/DeviceConfigure';
7
7
 
8
8
  export interface SdkMethodEvents {
9
9
  customize: (customization: CustomizationApiInterface) => void;
@@ -14,9 +14,12 @@ export interface SdkMethodEvents {
14
14
  microphoneDevice: (deviceId: deviceId) => void;
15
15
  speakerDevice: (deviceId: deviceId) => void;
16
16
  cameraDevice: (deviceId: deviceId) => void;
17
- muteAllParticipants: (mute: boolean | ((currentMute: boolean) => boolean)) => void;
17
+ muteAllParticipants: (
18
+ mute: boolean | ((currentMute: boolean) => boolean),
19
+ ) => void;
18
20
  muteAudio: (mute: boolean | ((currentMute: boolean) => boolean)) => void;
19
21
  muteVideo: (mute: boolean | ((currentMute: boolean) => boolean)) => void;
22
+ clearState: (state: 'join' | 'all') => void;
20
23
  }
21
24
 
22
25
  type EventParameterHelper<T extends keyof SdkMethodEvents> = Parameters<
@@ -61,8 +64,22 @@ class SDKMethodEvents {
61
64
  event: T,
62
65
  ...params: EventParameterHelper<T>
63
66
  ) {
64
- if (this.emitCache[event]) {
65
- throw new Error(`Event: ${event} already in callstack`);
67
+ if (event === 'clearState') {
68
+ const param = params[0];
69
+ switch (param) {
70
+ case 'join':
71
+ case 'clearState':
72
+ delete this.emitCache[param];
73
+ delete this.emitCacheDisabled[param];
74
+ break;
75
+ case 'all':
76
+ this.reset();
77
+ default:
78
+ }
79
+ } else {
80
+ if (this.emitCache[event]) {
81
+ throw new Error(`Event: ${event} already in callstack`);
82
+ }
66
83
  }
67
84
 
68
85
  const result = await new Promise<EventReturnTypeHelper<T>>((res, rej) => {
@@ -92,6 +109,11 @@ class SDKMethodEvents {
92
109
  this.emitCacheDisabled[event] = true;
93
110
  return unsub;
94
111
  }
112
+
113
+ reset() {
114
+ this.emitCache = {};
115
+ this.emitCacheDisabled = {};
116
+ }
95
117
  }
96
118
 
97
119
  const SDKMethodEventsManager = new SDKMethodEvents();
@@ -1,4 +1,4 @@
1
- import {useContext} from 'react';
1
+ import {useCallback, useContext} from 'react';
2
2
  import {gql} from '@apollo/client';
3
3
  import {MeetingInfoContextInterface} from '../components/meeting-info/useMeetingInfo';
4
4
  import {useSetMeetingInfo} from '../components/meeting-info/useSetMeetingInfo';
@@ -24,48 +24,51 @@ const SHARE = gql`
24
24
  export default function useGetMeetingPhrase() {
25
25
  const {setMeetingInfo} = useSetMeetingInfo();
26
26
  const {client} = useContext(GraphQLContext);
27
- return async (phrase: string) => {
28
- const response = await client.query({
29
- query: SHARE,
30
- variables: {
31
- passphrase: phrase,
32
- },
33
- });
34
- if (response.error) {
35
- throw response.error;
36
- } else {
37
- try {
38
- if (response && response.data) {
39
- let data = response.data;
40
- let meetingInfo: Partial<MeetingInfoContextInterface['data']> = {
41
- roomId: {attendee: ''},
42
- };
43
- if (data?.share?.passphrase?.view) {
44
- meetingInfo.roomId.attendee = data.share.passphrase.view;
45
- }
46
- if (data?.share?.passphrase?.host) {
47
- meetingInfo.roomId.host = data.share.passphrase.host;
48
- }
49
- if (data?.share?.pstn) {
50
- meetingInfo.pstn = {
51
- number: data.share.pstn.number,
52
- pin: data.share.pstn.dtmf,
27
+ return useCallback(
28
+ async (phrase: string) => {
29
+ const response = await client.query({
30
+ query: SHARE,
31
+ variables: {
32
+ passphrase: phrase,
33
+ },
34
+ });
35
+ if (response.error) {
36
+ throw response.error;
37
+ } else {
38
+ try {
39
+ if (response && response.data) {
40
+ let data = response.data;
41
+ let meetingInfo: Partial<MeetingInfoContextInterface['data']> = {
42
+ roomId: {attendee: ''},
53
43
  };
44
+ if (data?.share?.passphrase?.view) {
45
+ meetingInfo.roomId.attendee = data.share.passphrase.view;
46
+ }
47
+ if (data?.share?.passphrase?.host) {
48
+ meetingInfo.roomId.host = data.share.passphrase.host;
49
+ }
50
+ if (data?.share?.pstn) {
51
+ meetingInfo.pstn = {
52
+ number: data.share.pstn.number,
53
+ pin: data.share.pstn.dtmf,
54
+ };
55
+ }
56
+ setMeetingInfo((prevState) => {
57
+ return {
58
+ ...prevState,
59
+ data: {
60
+ ...prevState.data,
61
+ roomId: meetingInfo.roomId,
62
+ pstn: meetingInfo?.pstn,
63
+ },
64
+ };
65
+ });
54
66
  }
55
- setMeetingInfo((prevState) => {
56
- return {
57
- ...prevState,
58
- data: {
59
- ...prevState.data,
60
- roomId: meetingInfo.roomId,
61
- pstn: meetingInfo?.pstn,
62
- },
63
- };
64
- });
67
+ } catch (error) {
68
+ throw new Error('An error occurred in parsing the channel data.');
65
69
  }
66
- } catch (error) {
67
- throw new Error('An error occurred in parsing the channel data.');
68
70
  }
69
- }
70
- };
71
+ },
72
+ [client, setMeetingInfo],
73
+ );
71
74
  }
@@ -11,7 +11,7 @@
11
11
  */
12
12
 
13
13
  import React, {SetStateAction} from 'react';
14
- import {createHook} from 'customization-implementation';
14
+ import createHook from '../../customization-implementation/createHook';
15
15
 
16
16
  export interface LayoutContextInterface {
17
17
  currentLayout: string;
@@ -12,7 +12,7 @@
12
12
 
13
13
  import React, {SetStateAction} from 'react';
14
14
  import {SidePanelType} from '../subComponents/SidePanelEnum';
15
- import {createHook} from 'customization-implementation';
15
+ import createHook from '../../customization-implementation/createHook';
16
16
 
17
17
  export interface SidePanelContextInterface {
18
18
  sidePanel: SidePanelType;