agora-appbuilder-core 4.0.0-spl.27 → 4.0.0-spl.28
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 +1 -1
- package/template/Gulpfile.js +0 -6
- package/template/customization-api/__tests__/module-boundaries.test.js +112 -0
- package/template/customization-api/app-state.ts +3 -4
- package/template/customization-api/core-contexts.ts +10 -0
- package/template/src/app-state/useLocalUserInfo.ts +1 -1
- package/template/src/components/chat-messages/useChatMessages.tsx +2 -2
- package/template/src/components/chat-notification/useChatNotification.tsx +1 -1
- package/template/src/components/chat-ui/useChatUIControl.tsx +1 -1
- package/template/src/components/meeting-info/useMeetingInfo.tsx +1 -1
- package/template/src/components/popups/InvitePopup.tsx +9 -2
- package/template/src/components/useUserPreference.tsx +2 -2
- package/template/src/components/useVideoCall.tsx +1 -1
- package/template/src/subComponents/recording/useRecording.tsx +2 -2
- package/template/src/utils/SdkMethodEvents.ts +2 -2
- package/template/src/utils/useGetMeetingPhrase.ts +44 -41
- package/template/src/utils/useLayout.tsx +1 -1
- package/template/src/utils/useSidePanel.tsx +1 -1
- package/template/src/assets/__generated__/CreateChannel.graphql.ts +0 -0
- package/template/src/assets/__generated__/JoinChannel.graphql.ts +0 -0
- package/template/src/assets/__generated__/logoutSession.graphql.ts +0 -0
- package/template/src/assets/__generated__/mutePSTN.graphql.ts +0 -0
- package/template/src/assets/__generated__/setNormal.graphql.ts +0 -0
- package/template/src/assets/__generated__/setPresenter.graphql.ts +0 -0
- package/template/src/assets/__generated__/share.graphql.ts +0 -0
- package/template/src/assets/__generated__/startRecordingSession.graphql.ts +0 -0
- package/template/src/assets/__generated__/stopRecordingSession.graphql.ts +0 -0
package/package.json
CHANGED
package/template/Gulpfile.js
CHANGED
|
@@ -48,8 +48,6 @@ const TS_DEFS_BUILD_PATH =
|
|
|
48
48
|
: process.env.TARGET === 'android'
|
|
49
49
|
? path.join(__dirname, '../Builds/ts-defs/android')
|
|
50
50
|
: path.join(__dirname, '../Builds/ts-defs/.electron');
|
|
51
|
-
const GraphqlFolderName = '__generated__';
|
|
52
|
-
const GraphqlFolderPath = `./src/assets/${GraphqlFolderName}`;
|
|
53
51
|
|
|
54
52
|
const debugFlag = process.argv.indexOf('--debug') !== -1;
|
|
55
53
|
|
|
@@ -191,9 +189,6 @@ declare module 'customization' {
|
|
|
191
189
|
generateNpmPackage: (cb) => {
|
|
192
190
|
runCli(`cd ${BUILD_PATH} && npm pack`, cb);
|
|
193
191
|
},
|
|
194
|
-
copyGqlFiles: (cb) => {
|
|
195
|
-
runCli(`cp -r ${GraphqlFolderPath} ${BUILD_PATH}`, cb);
|
|
196
|
-
},
|
|
197
192
|
};
|
|
198
193
|
|
|
199
194
|
const electron = {
|
|
@@ -366,7 +361,6 @@ module.exports.reactSdk = series(
|
|
|
366
361
|
reactSdk.generateSdkTypedefs,
|
|
367
362
|
reactSdk.bundleSdkTypedefs,
|
|
368
363
|
general.cleanTempFiles,
|
|
369
|
-
general.copyGqlFiles,
|
|
370
364
|
general.generateNpmPackage,
|
|
371
365
|
);
|
|
372
366
|
|
|
@@ -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 {
|
|
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
|
|
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
|
|
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);
|
|
@@ -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.
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
information visit https://appbuilder.agora.io.
|
|
10
10
|
*********************************************
|
|
11
11
|
*/
|
|
12
|
-
import
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
37
|
-
|
|
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
|
|
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;
|
|
@@ -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
|
|
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;
|
|
@@ -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
|
|
28
|
-
|
|
29
|
-
query
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
56
|
-
|
|
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
|
|
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
|
|
15
|
+
import createHook from '../../customization-implementation/createHook';
|
|
16
16
|
|
|
17
17
|
export interface SidePanelContextInterface {
|
|
18
18
|
sidePanel: SidePanelType;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|