agora-appbuilder-core 2.0.0 → 2.0.1
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 +3 -2
- package/template/_package-lock.json +22850 -0
- package/template/agora-rn-uikit/.git/HEAD +1 -1
- package/template/agora-rn-uikit/.git/index +0 -0
- package/template/agora-rn-uikit/.git/logs/HEAD +2 -3
- package/template/agora-rn-uikit/.git/logs/refs/heads/ab-dev-auto +1 -1
- package/template/agora-rn-uikit/.git/logs/refs/heads/master +1 -1
- package/template/agora-rn-uikit/.git/logs/refs/remotes/origin/HEAD +1 -1
- package/template/agora-rn-uikit/.git/objects/pack/pack-f379286d0537eb68377220b4929979324b8d5d1c.idx +0 -0
- package/template/agora-rn-uikit/.git/objects/pack/{pack-19a65e0782e617d79275088a06e668496d6e2d73.pack → pack-f379286d0537eb68377220b4929979324b8d5d1c.pack} +0 -0
- package/template/agora-rn-uikit/.git/packed-refs +3 -2
- package/template/agora-rn-uikit/.git/refs/heads/ab-dev-auto +1 -1
- package/template/agora-rn-uikit/package.json +1 -0
- package/template/agora-rn-uikit/src/AgoraUIKit.tsx +8 -8
- package/template/agora-rn-uikit/src/{LocalUserContext.tsx → Contexts/LocalUserContext.tsx} +1 -1
- package/template/agora-rn-uikit/src/{MaxUidContext.tsx → Contexts/MaxUidContext.tsx} +0 -0
- package/template/agora-rn-uikit/src/{MinUidContext.tsx → Contexts/MinUidContext.tsx} +0 -0
- package/template/agora-rn-uikit/src/{PropsContext.tsx → Contexts/PropsContext.tsx} +34 -16
- package/template/agora-rn-uikit/src/{RtcContext.tsx → Contexts/RtcContext.tsx} +12 -21
- package/template/agora-rn-uikit/src/Controls/BtnTemplate.tsx +25 -15
- package/template/agora-rn-uikit/src/Controls/Icons.ts +53 -3
- package/template/agora-rn-uikit/src/Controls/ImageIcon.tsx +53 -0
- package/template/agora-rn-uikit/src/Controls/Local/EndCall.tsx +4 -3
- package/template/agora-rn-uikit/src/Controls/Local/FullScreen.tsx +3 -3
- package/template/agora-rn-uikit/src/Controls/Local/LocalAudioMute.tsx +58 -14
- package/template/agora-rn-uikit/src/Controls/Local/LocalVideoMute.tsx +60 -14
- package/template/agora-rn-uikit/src/Controls/Local/Recording.tsx +2 -2
- package/template/agora-rn-uikit/src/Controls/Local/Screenshare.tsx +2 -2
- package/template/agora-rn-uikit/src/Controls/Local/SwitchCamera.tsx +9 -9
- package/template/agora-rn-uikit/src/Controls/LocalControls.tsx +20 -17
- package/template/agora-rn-uikit/src/Controls/Remote/RemoteAudioMute.tsx +8 -8
- package/template/agora-rn-uikit/src/Controls/Remote/RemoteSwap.tsx +3 -3
- package/template/agora-rn-uikit/src/Controls/Remote/RemoteVideoMute.tsx +13 -8
- package/template/agora-rn-uikit/src/Controls/RemoteControls.tsx +1 -2
- package/template/agora-rn-uikit/src/Reducer/LocalMuteAudio.ts +20 -0
- package/template/agora-rn-uikit/src/Reducer/LocalMuteVideo.ts +20 -0
- package/template/agora-rn-uikit/src/Reducer/RemoteAudioStateChanged.ts +26 -0
- package/template/agora-rn-uikit/src/Reducer/RemoteVideoStateChanged.ts +26 -0
- package/template/agora-rn-uikit/src/Reducer/UpdateDualStreamMode.ts +46 -0
- package/template/agora-rn-uikit/src/Reducer/UserJoined.ts +47 -0
- package/template/agora-rn-uikit/src/Reducer/UserMuteRemoteAudio.ts +20 -0
- package/template/agora-rn-uikit/src/Reducer/UserMuteRemoteVideo.ts +20 -0
- package/template/agora-rn-uikit/src/Reducer/UserOffline.ts +21 -0
- package/template/agora-rn-uikit/src/Reducer/index.ts +9 -0
- package/template/agora-rn-uikit/src/Rtc/Create.tsx +138 -0
- package/template/agora-rn-uikit/src/Rtc/Join.tsx +100 -0
- package/template/agora-rn-uikit/src/RtcConfigure.tsx +197 -0
- package/template/agora-rn-uikit/src/Style.ts +3 -3
- package/template/agora-rn-uikit/src/Utils/actionTypeGuard.tsx +9 -0
- package/template/agora-rn-uikit/src/{events.ts → Utils/events.ts} +0 -0
- package/template/agora-rn-uikit/src/{permission.ts → Utils/permission.ts} +0 -0
- package/template/agora-rn-uikit/src/{quality.tsx → Utils/quality.tsx} +0 -0
- package/template/agora-rn-uikit/src/{MaxVideoView.native.tsx → Views/MaxVideoView.native.tsx} +3 -4
- package/template/agora-rn-uikit/src/{MaxVideoView.tsx → Views/MaxVideoView.tsx} +3 -4
- package/template/agora-rn-uikit/src/Views/MinVideoView.tsx +86 -0
- package/template/agora-rn-uikit/src/index.ts +67 -0
- package/template/bridge/rtc/webNg/RtcEngine.ts +23 -6
- package/template/package-lock.json +22850 -0
- package/template/package.json +6 -5
- package/template/src/assets/icons.ts +35 -6
- package/template/src/atoms/SecondaryButton.tsx +6 -5
- package/template/src/atoms/TextInput.tsx +6 -1
- package/template/src/components/Chat.tsx +50 -21
- package/template/src/components/ChatContext.ts +22 -1
- package/template/src/components/Controls.native.tsx +2 -2
- package/template/src/components/Controls.tsx +2 -2
- package/template/src/components/DeviceConfigure.tsx +1 -1
- package/template/src/components/GridVideo.tsx +69 -31
- package/template/src/components/Navbar.tsx +136 -113
- package/template/src/components/NetworkQualityContext.tsx +134 -0
- package/template/src/components/ParticipantsView.tsx +105 -49
- package/template/src/components/PinnedVideo.tsx +112 -71
- package/template/src/components/Precall.native.tsx +20 -9
- package/template/src/components/Precall.tsx +35 -32
- package/template/src/components/RTMConfigure.tsx +331 -181
- package/template/src/components/RTMEvents.tsx +84 -0
- package/template/src/components/Settings.tsx +19 -16
- package/template/src/components/Share.tsx +131 -62
- package/template/src/hooks/useImageDelay.tsx +28 -0
- package/template/src/pages/Create.tsx +9 -3
- package/template/src/pages/VideoCall.tsx +124 -98
- package/template/src/subComponents/ChatContainer.tsx +40 -28
- package/template/src/subComponents/CopyJoinInfo.tsx +9 -12
- package/template/src/subComponents/LocalAudioMute.tsx +9 -9
- package/template/src/subComponents/LocalVideoMute.tsx +9 -9
- package/template/src/subComponents/NetworkQualityPill.tsx +161 -0
- package/template/src/subComponents/Recording.tsx +12 -16
- package/template/src/subComponents/RemoteAudioMute.tsx +23 -27
- package/template/src/subComponents/RemoteEndCall.tsx +7 -15
- package/template/src/subComponents/RemoteVideoMute.tsx +15 -28
- package/template/src/subComponents/ScreenShareNotice.tsx +61 -0
- package/template/src/subComponents/ScreenshareButton.tsx +74 -75
- package/template/src/subComponents/SwitchCamera.tsx +5 -2
- package/template/src/subComponents/TextWithTooltip.native.tsx +128 -0
- package/template/src/subComponents/TextWithTooltip.tsx +44 -0
- package/template/src/subComponents/toastConfig.tsx +2 -2
- package/template/src/utils/isSafariBrowser.tsx +22 -0
- package/template/agora-rn-uikit/.git/objects/pack/pack-19a65e0782e617d79275088a06e668496d6e2d73.idx +0 -0
- package/template/agora-rn-uikit/Components.js +0 -35
- package/template/agora-rn-uikit/Contexts.js +0 -7
- package/template/agora-rn-uikit/index.js +0 -12
- package/template/agora-rn-uikit/src/MinVideoView.tsx +0 -87
- package/template/agora-rn-uikit/src/RTCConfigure.tsx +0 -520
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import React, {useState, useEffect, useContext, useRef, FC} from 'react';
|
|
2
|
+
import RtcEngine, {
|
|
3
|
+
VideoEncoderConfiguration,
|
|
4
|
+
AreaCode,
|
|
5
|
+
} from 'react-native-agora';
|
|
6
|
+
import {Platform} from 'react-native';
|
|
7
|
+
import requestCameraAndAudioPermission from '../Utils/permission';
|
|
8
|
+
import {DispatchType} from '../Contexts/RtcContext';
|
|
9
|
+
import PropsContext, {ToggleState} from '../Contexts/PropsContext';
|
|
10
|
+
import quality from '../Utils/quality';
|
|
11
|
+
|
|
12
|
+
const Create = ({
|
|
13
|
+
dispatch,
|
|
14
|
+
children,
|
|
15
|
+
}: {
|
|
16
|
+
dispatch: DispatchType;
|
|
17
|
+
children: (engine: React.MutableRefObject<RtcEngine>) => JSX.Element;
|
|
18
|
+
}) => {
|
|
19
|
+
const [ready, setReady] = useState(false);
|
|
20
|
+
const {callbacks, rtcProps} = useContext(PropsContext);
|
|
21
|
+
let engine = useRef<RtcEngine>({} as RtcEngine);
|
|
22
|
+
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
async function init() {
|
|
25
|
+
if (Platform.OS === 'android') {
|
|
26
|
+
//Request required permissions from Android
|
|
27
|
+
await requestCameraAndAudioPermission();
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
if (Platform.OS === 'android' || Platform.OS === 'ios') {
|
|
31
|
+
engine.current = await RtcEngine.createWithAreaCode(
|
|
32
|
+
rtcProps.appId,
|
|
33
|
+
// eslint-disable-next-line no-bitwise
|
|
34
|
+
AreaCode.GLOB ^ AreaCode.CN,
|
|
35
|
+
);
|
|
36
|
+
} else {
|
|
37
|
+
engine.current = await RtcEngine.create(rtcProps.appId);
|
|
38
|
+
}
|
|
39
|
+
if (rtcProps.profile) {
|
|
40
|
+
if (Platform.OS === 'web') {
|
|
41
|
+
// move this to bridge?
|
|
42
|
+
// @ts-ignore
|
|
43
|
+
await engine.current.setVideoProfile(rtcProps.profile);
|
|
44
|
+
} else {
|
|
45
|
+
const config: VideoEncoderConfiguration = quality[rtcProps.profile];
|
|
46
|
+
await engine.current.setVideoEncoderConfiguration({
|
|
47
|
+
...config,
|
|
48
|
+
bitrate: 0,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
await engine.current.enableVideo();
|
|
54
|
+
} catch (e) {
|
|
55
|
+
dispatch({
|
|
56
|
+
type: 'LocalMuteAudio',
|
|
57
|
+
value: [ToggleState.disabled],
|
|
58
|
+
});
|
|
59
|
+
dispatch({
|
|
60
|
+
type: 'LocalMuteVideo',
|
|
61
|
+
value: [ToggleState.disabled],
|
|
62
|
+
});
|
|
63
|
+
console.error('No devices', e);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
engine.current.addListener(
|
|
67
|
+
'JoinChannelSuccess',
|
|
68
|
+
async (channel, uid, elapsed) => {
|
|
69
|
+
//Invoke the callback
|
|
70
|
+
console.log('UIkit enabling dual stream', rtcProps.dual);
|
|
71
|
+
if (rtcProps.dual) {
|
|
72
|
+
console.log('UIkit enabled dual stream');
|
|
73
|
+
await engine.current!.enableDualStreamMode(rtcProps.dual);
|
|
74
|
+
// await engine.current.setRemoteSubscribeFallbackOption(1);
|
|
75
|
+
}
|
|
76
|
+
callbacks?.JoinChannelSuccess &&
|
|
77
|
+
callbacks.JoinChannelSuccess(channel, uid, elapsed);
|
|
78
|
+
},
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
engine.current.addListener('UserJoined', (...args) => {
|
|
82
|
+
//Get current peer IDs
|
|
83
|
+
dispatch({
|
|
84
|
+
type: 'UserJoined',
|
|
85
|
+
value: args,
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
engine.current.addListener('UserOffline', (...args) => {
|
|
90
|
+
//If user leaves
|
|
91
|
+
dispatch({
|
|
92
|
+
type: 'UserOffline',
|
|
93
|
+
value: args,
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
engine.current.addListener('RemoteAudioStateChanged', (...args) => {
|
|
98
|
+
// console.log('RemoteAudioStateChanged', args);
|
|
99
|
+
|
|
100
|
+
dispatch({
|
|
101
|
+
type: 'RemoteAudioStateChanged',
|
|
102
|
+
value: args,
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
engine.current.addListener('Error', (e) => {
|
|
107
|
+
console.log('Error: ', e);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
engine.current.addListener('RemoteVideoStateChanged', (...args) => {
|
|
111
|
+
// console.log('RemoteVideoStateChanged', args);
|
|
112
|
+
|
|
113
|
+
dispatch({
|
|
114
|
+
type: 'RemoteVideoStateChanged',
|
|
115
|
+
value: args,
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
setReady(true);
|
|
119
|
+
} catch (e) {
|
|
120
|
+
console.error(e);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
init();
|
|
124
|
+
return () => {
|
|
125
|
+
engine.current!.destroy();
|
|
126
|
+
};
|
|
127
|
+
}, []);
|
|
128
|
+
return (
|
|
129
|
+
<>
|
|
130
|
+
{
|
|
131
|
+
// Render children once RTCEngine has been initialized
|
|
132
|
+
ready && engine ? children(engine) : <></>
|
|
133
|
+
}
|
|
134
|
+
</>
|
|
135
|
+
);
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
export default Create;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import React, {useEffect, useContext, useRef} from 'react';
|
|
2
|
+
import RtcEngine from 'react-native-agora';
|
|
3
|
+
import {UidStateInterface, DispatchType} from '../Contexts/RtcContext';
|
|
4
|
+
import PropsContext, {ToggleState} from '../Contexts/PropsContext';
|
|
5
|
+
import {Platform} from 'react-native';
|
|
6
|
+
|
|
7
|
+
const Join: React.FC<{
|
|
8
|
+
precall: boolean;
|
|
9
|
+
engineRef: React.MutableRefObject<RtcEngine>;
|
|
10
|
+
uidState: UidStateInterface;
|
|
11
|
+
dispatch: DispatchType;
|
|
12
|
+
}> = ({children, precall, engineRef, uidState, dispatch}) => {
|
|
13
|
+
let joinState = useRef(false);
|
|
14
|
+
const {rtcProps} = useContext(PropsContext);
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const engine = engineRef.current;
|
|
18
|
+
async function leave() {
|
|
19
|
+
try {
|
|
20
|
+
console.log('Leaving channel');
|
|
21
|
+
engine.leaveChannel();
|
|
22
|
+
joinState.current = false;
|
|
23
|
+
} catch (err) {
|
|
24
|
+
console.error('Cannot leave the channel:', err);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const videoState = uidState.max[0].video;
|
|
28
|
+
async function join() {
|
|
29
|
+
if (
|
|
30
|
+
rtcProps.encryption &&
|
|
31
|
+
rtcProps.encryption.key &&
|
|
32
|
+
rtcProps.encryption.mode
|
|
33
|
+
) {
|
|
34
|
+
console.log('using channel encryption', rtcProps.encryption);
|
|
35
|
+
await engine.enableEncryption(true, {
|
|
36
|
+
encryptionKey: rtcProps.encryption.key,
|
|
37
|
+
encryptionMode: rtcProps.encryption.mode,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
if (videoState === ToggleState.enabled && Platform.OS === 'ios') {
|
|
41
|
+
dispatch({
|
|
42
|
+
type: 'LocalMuteVideo',
|
|
43
|
+
value: [ToggleState.disabling],
|
|
44
|
+
});
|
|
45
|
+
await engine.muteLocalVideoStream(true);
|
|
46
|
+
dispatch({
|
|
47
|
+
type: 'LocalMuteVideo',
|
|
48
|
+
value: [ToggleState.disabled],
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
await engine.joinChannel(
|
|
52
|
+
rtcProps.token || null,
|
|
53
|
+
rtcProps.channel,
|
|
54
|
+
null,
|
|
55
|
+
rtcProps.uid || 0,
|
|
56
|
+
);
|
|
57
|
+
if (videoState === ToggleState.enabled && Platform.OS === 'ios') {
|
|
58
|
+
dispatch({
|
|
59
|
+
type: 'LocalMuteVideo',
|
|
60
|
+
value: [ToggleState.enabling],
|
|
61
|
+
});
|
|
62
|
+
await engine.muteLocalVideoStream(false);
|
|
63
|
+
dispatch({
|
|
64
|
+
type: 'LocalMuteVideo',
|
|
65
|
+
value: [ToggleState.enabled],
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async function init() {
|
|
70
|
+
if (!precall) {
|
|
71
|
+
if (!joinState.current) {
|
|
72
|
+
await join();
|
|
73
|
+
joinState.current = true;
|
|
74
|
+
} else {
|
|
75
|
+
await leave();
|
|
76
|
+
await join();
|
|
77
|
+
}
|
|
78
|
+
console.log('Attempted join: ', rtcProps.channel);
|
|
79
|
+
} else {
|
|
80
|
+
console.log('In precall - waiting to join');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
init();
|
|
84
|
+
return () => {
|
|
85
|
+
if (!precall) {
|
|
86
|
+
leave();
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}, [
|
|
90
|
+
rtcProps.channel,
|
|
91
|
+
rtcProps.uid,
|
|
92
|
+
rtcProps.token,
|
|
93
|
+
precall,
|
|
94
|
+
rtcProps.encryption,
|
|
95
|
+
]);
|
|
96
|
+
|
|
97
|
+
return <>{children}</>;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export default Join;
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import React, {useState, useReducer, useContext, useCallback} from 'react';
|
|
2
|
+
import {
|
|
3
|
+
RtcProvider,
|
|
4
|
+
UidStateInterface,
|
|
5
|
+
DispatchType,
|
|
6
|
+
ActionType,
|
|
7
|
+
} from './Contexts/RtcContext';
|
|
8
|
+
import PropsContext, {
|
|
9
|
+
ToggleState,
|
|
10
|
+
UidInterface,
|
|
11
|
+
RtcPropsInterface,
|
|
12
|
+
CallbacksInterface,
|
|
13
|
+
DualStreamMode,
|
|
14
|
+
} from './Contexts/PropsContext';
|
|
15
|
+
import {MinUidProvider} from './Contexts/MinUidContext';
|
|
16
|
+
import {MaxUidProvider} from './Contexts/MaxUidContext';
|
|
17
|
+
import {actionTypeGuard} from './Utils/actionTypeGuard';
|
|
18
|
+
|
|
19
|
+
import {
|
|
20
|
+
LocalMuteAudio,
|
|
21
|
+
LocalMuteVideo,
|
|
22
|
+
RemoteAudioStateChanged,
|
|
23
|
+
RemoteVideoStateChanged,
|
|
24
|
+
UpdateDualStreamMode,
|
|
25
|
+
UserJoined,
|
|
26
|
+
UserMuteRemoteAudio,
|
|
27
|
+
UserMuteRemoteVideo,
|
|
28
|
+
UserOffline,
|
|
29
|
+
} from './Reducer';
|
|
30
|
+
import Create from './Rtc/Create';
|
|
31
|
+
import Join from './Rtc/Join';
|
|
32
|
+
|
|
33
|
+
const initialLocalState: UidStateInterface = {
|
|
34
|
+
min: [],
|
|
35
|
+
max: [
|
|
36
|
+
{
|
|
37
|
+
uid: 'local',
|
|
38
|
+
audio: ToggleState.enabled,
|
|
39
|
+
video: ToggleState.enabled,
|
|
40
|
+
streamType: 'high',
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const RtcConfigure: React.FC<Partial<RtcPropsInterface>> = (props) => {
|
|
46
|
+
const {callbacks, rtcProps} = useContext(PropsContext);
|
|
47
|
+
let [dualStreamMode, setDualStreamMode] = useState<DualStreamMode>(
|
|
48
|
+
rtcProps?.initialDualStreamMode || DualStreamMode.DYNAMIC,
|
|
49
|
+
);
|
|
50
|
+
const [initialState, setInitialState] = React.useState(
|
|
51
|
+
JSON.parse(JSON.stringify(initialLocalState)),
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
React.useEffect(() => {
|
|
55
|
+
setInitialState(JSON.parse(JSON.stringify(initialLocalState)));
|
|
56
|
+
}, []);
|
|
57
|
+
|
|
58
|
+
const reducer = (
|
|
59
|
+
state: UidStateInterface,
|
|
60
|
+
action: ActionType<keyof CallbacksInterface>,
|
|
61
|
+
) => {
|
|
62
|
+
let stateUpdate = {},
|
|
63
|
+
uids = [...state.max, ...state.min].map((u: UidInterface) => u.uid);
|
|
64
|
+
|
|
65
|
+
switch (action.type) {
|
|
66
|
+
case 'UpdateDualStreamMode':
|
|
67
|
+
if (actionTypeGuard(action, action.type)) {
|
|
68
|
+
stateUpdate = UpdateDualStreamMode(state, action);
|
|
69
|
+
}
|
|
70
|
+
break;
|
|
71
|
+
case 'UserJoined':
|
|
72
|
+
if (actionTypeGuard(action, action.type)) {
|
|
73
|
+
stateUpdate = UserJoined(state, action, dualStreamMode, uids);
|
|
74
|
+
}
|
|
75
|
+
break;
|
|
76
|
+
case 'UserOffline':
|
|
77
|
+
if (actionTypeGuard(action, action.type)) {
|
|
78
|
+
stateUpdate = UserOffline(state, action);
|
|
79
|
+
}
|
|
80
|
+
break;
|
|
81
|
+
case 'SwapVideo':
|
|
82
|
+
if (actionTypeGuard(action, action.type)) {
|
|
83
|
+
stateUpdate = swapVideo(state, action.value[0]);
|
|
84
|
+
}
|
|
85
|
+
break;
|
|
86
|
+
case 'UserMuteRemoteAudio':
|
|
87
|
+
if (actionTypeGuard(action, action.type)) {
|
|
88
|
+
stateUpdate = UserMuteRemoteAudio(state, action);
|
|
89
|
+
}
|
|
90
|
+
break;
|
|
91
|
+
case 'UserMuteRemoteVideo':
|
|
92
|
+
if (actionTypeGuard(action, action.type)) {
|
|
93
|
+
stateUpdate = UserMuteRemoteVideo(state, action);
|
|
94
|
+
}
|
|
95
|
+
break;
|
|
96
|
+
case 'LocalMuteAudio':
|
|
97
|
+
if (actionTypeGuard(action, action.type)) {
|
|
98
|
+
stateUpdate = LocalMuteAudio(state, action);
|
|
99
|
+
}
|
|
100
|
+
break;
|
|
101
|
+
case 'LocalMuteVideo':
|
|
102
|
+
if (actionTypeGuard(action, action.type)) {
|
|
103
|
+
stateUpdate = LocalMuteVideo(state, action);
|
|
104
|
+
}
|
|
105
|
+
break;
|
|
106
|
+
case 'RemoteAudioStateChanged':
|
|
107
|
+
if (actionTypeGuard(action, action.type)) {
|
|
108
|
+
stateUpdate = RemoteAudioStateChanged(state, action);
|
|
109
|
+
}
|
|
110
|
+
break;
|
|
111
|
+
case 'RemoteVideoStateChanged':
|
|
112
|
+
if (actionTypeGuard(action, action.type)) {
|
|
113
|
+
stateUpdate = RemoteVideoStateChanged(state, action);
|
|
114
|
+
}
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// TODO: remove Handle event listeners
|
|
119
|
+
|
|
120
|
+
if (callbacks && callbacks[action.type]) {
|
|
121
|
+
// @ts-ignore
|
|
122
|
+
callbacks[action.type].apply(null, action.value);
|
|
123
|
+
console.log('callback executed');
|
|
124
|
+
} else {
|
|
125
|
+
// console.log('callback not found', action.type);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// console.log(state, action, stateUpdate);
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
...state,
|
|
132
|
+
...stateUpdate,
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const swapVideo = useCallback(
|
|
137
|
+
(state: UidStateInterface, ele: UidInterface) => {
|
|
138
|
+
let newState: UidStateInterface = {
|
|
139
|
+
min: [],
|
|
140
|
+
max: [],
|
|
141
|
+
};
|
|
142
|
+
// Remove the minimized element which is being swapped out
|
|
143
|
+
newState.min = state.min.filter((e) => e !== ele);
|
|
144
|
+
|
|
145
|
+
let maxEle = state.max[0]; // Element which is currently maximized
|
|
146
|
+
let minEle = ele;
|
|
147
|
+
|
|
148
|
+
if (dualStreamMode === DualStreamMode.DYNAMIC) {
|
|
149
|
+
maxEle.streamType = 'low'; // set stream quality to low
|
|
150
|
+
minEle.streamType = 'high'; // set stream quality to high
|
|
151
|
+
|
|
152
|
+
// No need to modify the streamType if the mode is not dynamic
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (maxEle.uid === 'local') {
|
|
156
|
+
newState.min.unshift(maxEle);
|
|
157
|
+
} else {
|
|
158
|
+
newState.min.push(maxEle);
|
|
159
|
+
}
|
|
160
|
+
newState.max = [minEle];
|
|
161
|
+
|
|
162
|
+
return newState;
|
|
163
|
+
},
|
|
164
|
+
[dualStreamMode],
|
|
165
|
+
);
|
|
166
|
+
const [uidState, dispatch]: [UidStateInterface, DispatchType] = useReducer(
|
|
167
|
+
reducer,
|
|
168
|
+
initialState,
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
return (
|
|
172
|
+
<Create dispatch={dispatch}>
|
|
173
|
+
{(engineRef) => (
|
|
174
|
+
<Join
|
|
175
|
+
precall={!rtcProps.callActive}
|
|
176
|
+
engineRef={engineRef}
|
|
177
|
+
uidState={uidState}
|
|
178
|
+
dispatch={dispatch}>
|
|
179
|
+
<RtcProvider
|
|
180
|
+
value={{
|
|
181
|
+
RtcEngine: engineRef.current,
|
|
182
|
+
dispatch,
|
|
183
|
+
setDualStreamMode,
|
|
184
|
+
}}>
|
|
185
|
+
<MaxUidProvider value={uidState.max}>
|
|
186
|
+
<MinUidProvider value={uidState.min}>
|
|
187
|
+
{props.children}
|
|
188
|
+
</MinUidProvider>
|
|
189
|
+
</MaxUidProvider>
|
|
190
|
+
</RtcProvider>
|
|
191
|
+
</Join>
|
|
192
|
+
)}
|
|
193
|
+
</Create>
|
|
194
|
+
);
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
export default RtcConfigure;
|
|
@@ -36,7 +36,7 @@ export default StyleSheet.create({
|
|
|
36
36
|
},
|
|
37
37
|
minContainer: {
|
|
38
38
|
position: 'absolute',
|
|
39
|
-
top:
|
|
39
|
+
top: 15,
|
|
40
40
|
left: 0,
|
|
41
41
|
padding: 0,
|
|
42
42
|
margin: 0,
|
|
@@ -44,7 +44,7 @@ export default StyleSheet.create({
|
|
|
44
44
|
},
|
|
45
45
|
Controls: {
|
|
46
46
|
position: 'absolute',
|
|
47
|
-
|
|
47
|
+
top: dimensions.height - 120,
|
|
48
48
|
left: 0,
|
|
49
49
|
width: dimensions.width,
|
|
50
50
|
height: 70,
|
|
@@ -92,7 +92,7 @@ export default StyleSheet.create({
|
|
|
92
92
|
remoteBtnContainer: {
|
|
93
93
|
width: '100%',
|
|
94
94
|
display: 'flex',
|
|
95
|
-
|
|
95
|
+
marginTop: 50,
|
|
96
96
|
flexDirection: 'row',
|
|
97
97
|
justifyContent: 'center',
|
|
98
98
|
alignSelf: 'center',
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import {CallbacksInterface} from '../Contexts/PropsContext';
|
|
2
|
+
import {ActionType} from '../Contexts/RtcContext';
|
|
3
|
+
|
|
4
|
+
export function actionTypeGuard<T extends keyof CallbacksInterface>(
|
|
5
|
+
_act: ActionType<keyof CallbacksInterface>,
|
|
6
|
+
_type: T,
|
|
7
|
+
): _act is ActionType<T> {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/template/agora-rn-uikit/src/{MaxVideoView.native.tsx → Views/MaxVideoView.native.tsx}
RENAMED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import React, {useContext} from 'react';
|
|
2
2
|
import {RtcLocalView, RtcRemoteView, VideoRenderMode} from 'react-native-agora';
|
|
3
|
-
import styles from '
|
|
4
|
-
import PropsContext from '
|
|
5
|
-
import {
|
|
6
|
-
import {View, Text, Image} from 'react-native';
|
|
3
|
+
import styles from '../Style';
|
|
4
|
+
import PropsContext, {UidInterface} from '../Contexts/PropsContext';
|
|
5
|
+
import {View} from 'react-native';
|
|
7
6
|
|
|
8
7
|
const LocalView = RtcLocalView.SurfaceView;
|
|
9
8
|
const RemoteView = RtcRemoteView.SurfaceView;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import React, {useContext} from 'react';
|
|
2
2
|
import {RtcLocalView, RtcRemoteView, VideoRenderMode} from 'react-native-agora';
|
|
3
|
-
import styles from '
|
|
4
|
-
import PropsContext from '
|
|
5
|
-
import {
|
|
6
|
-
import {View, Text, Image} from 'react-native';
|
|
3
|
+
import styles from '../Style';
|
|
4
|
+
import PropsContext, {UidInterface} from '../Contexts/PropsContext';
|
|
5
|
+
import {View} from 'react-native';
|
|
7
6
|
|
|
8
7
|
const LocalView = RtcLocalView.SurfaceView;
|
|
9
8
|
const RemoteView = RtcRemoteView.SurfaceView;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import React, {useState, useContext} from 'react';
|
|
2
|
+
import {View, TouchableOpacity, Image} from 'react-native';
|
|
3
|
+
import {RtcLocalView, RtcRemoteView, VideoRenderMode} from 'react-native-agora';
|
|
4
|
+
import styles from '../Style';
|
|
5
|
+
import icons from '../Controls/Icons';
|
|
6
|
+
import RemoteControls from '../Controls/RemoteControls';
|
|
7
|
+
import PropsContext, {UidInterface} from '../Contexts/PropsContext';
|
|
8
|
+
|
|
9
|
+
const LocalView = RtcLocalView.SurfaceView;
|
|
10
|
+
const RemoteView = RtcRemoteView.SurfaceView;
|
|
11
|
+
|
|
12
|
+
interface MinViewInterface {
|
|
13
|
+
user: UidInterface;
|
|
14
|
+
color?: string;
|
|
15
|
+
showOverlay?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const MinVideoView: React.FC<MinViewInterface> = (props) => {
|
|
19
|
+
const [overlay, setOverlay] = useState(false);
|
|
20
|
+
const {styleProps} = useContext(PropsContext);
|
|
21
|
+
const {minViewStyles, theme, remoteBtnStyles} = styleProps || {};
|
|
22
|
+
const {minCloseBtnStyles} = remoteBtnStyles || {};
|
|
23
|
+
const {showOverlay} = props || {};
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<View style={{margin: 5}}>
|
|
27
|
+
{showOverlay ? (
|
|
28
|
+
<TouchableOpacity onPress={() => setOverlay(true)}>
|
|
29
|
+
{props.user.uid === 'local' ? (
|
|
30
|
+
props.user.video ? (
|
|
31
|
+
<LocalView
|
|
32
|
+
style={{...styles.minView, ...(minViewStyles as object)}}
|
|
33
|
+
renderMode={VideoRenderMode.Hidden}
|
|
34
|
+
zOrderMediaOverlay={true}
|
|
35
|
+
/>
|
|
36
|
+
) : (
|
|
37
|
+
<View style={{flex: 1, backgroundColor: '#f0f', ...styles.minView, ...(minViewStyles as object)}} />
|
|
38
|
+
)
|
|
39
|
+
) : (
|
|
40
|
+
<RemoteView
|
|
41
|
+
style={{...styles.minView, ...(minViewStyles as object)}}
|
|
42
|
+
uid={props.user.uid as number}
|
|
43
|
+
renderMode={VideoRenderMode.Hidden}
|
|
44
|
+
zOrderMediaOverlay={true}
|
|
45
|
+
/>
|
|
46
|
+
)}
|
|
47
|
+
</TouchableOpacity>
|
|
48
|
+
) : props.user.uid === 'local' ? (
|
|
49
|
+
<LocalView
|
|
50
|
+
style={{...styles.minView, ...(minViewStyles as object)}}
|
|
51
|
+
renderMode={VideoRenderMode.Hidden}
|
|
52
|
+
zOrderMediaOverlay={true}
|
|
53
|
+
/>
|
|
54
|
+
) : (
|
|
55
|
+
<RemoteView
|
|
56
|
+
style={{...styles.minView, ...(minViewStyles as object)}}
|
|
57
|
+
uid={props.user.uid as number}
|
|
58
|
+
renderMode={VideoRenderMode.Hidden}
|
|
59
|
+
zOrderMediaOverlay={true}
|
|
60
|
+
/>
|
|
61
|
+
)}
|
|
62
|
+
|
|
63
|
+
{overlay && showOverlay ? (
|
|
64
|
+
<View style={styles.minOverlay}>
|
|
65
|
+
<TouchableOpacity
|
|
66
|
+
style={{...styles.minCloseBtn, ...(minCloseBtnStyles as object)}}
|
|
67
|
+
onPress={() => setOverlay(!overlay)}>
|
|
68
|
+
<Image
|
|
69
|
+
style={{
|
|
70
|
+
width: 25,
|
|
71
|
+
height: 25,
|
|
72
|
+
tintColor: theme || props.color || '#fff',
|
|
73
|
+
}}
|
|
74
|
+
source={{uri: icons.close}}
|
|
75
|
+
/>
|
|
76
|
+
</TouchableOpacity>
|
|
77
|
+
<RemoteControls showRemoteSwap={true} user={props.user} />
|
|
78
|
+
</View>
|
|
79
|
+
) : (
|
|
80
|
+
<></>
|
|
81
|
+
)}
|
|
82
|
+
</View>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export default MinVideoView;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export {default as default} from './AgoraUIKit';
|
|
2
|
+
export {default as RtcConfigure} from './RtcConfigure';
|
|
3
|
+
|
|
4
|
+
export {default as MaxVideoView} from './Views/MaxVideoView';
|
|
5
|
+
export {default as MinVideoView} from './Views/MinVideoView';
|
|
6
|
+
|
|
7
|
+
export {
|
|
8
|
+
default as LocalUserContext,
|
|
9
|
+
LocalConsumer,
|
|
10
|
+
LocalProvider,
|
|
11
|
+
LocalContext,
|
|
12
|
+
} from './Contexts/LocalUserContext';
|
|
13
|
+
export {
|
|
14
|
+
default as MaxUidContext,
|
|
15
|
+
MaxUidConsumer,
|
|
16
|
+
MaxUidProvider,
|
|
17
|
+
} from './Contexts/MaxUidContext';
|
|
18
|
+
export {
|
|
19
|
+
default as MinUidContext,
|
|
20
|
+
MinUidConsumer,
|
|
21
|
+
MinUidProvider,
|
|
22
|
+
} from './Contexts/MinUidContext';
|
|
23
|
+
|
|
24
|
+
export {
|
|
25
|
+
default as PropsContext,
|
|
26
|
+
PropsConsumer,
|
|
27
|
+
PropsProvider,
|
|
28
|
+
} from './Contexts/PropsContext';
|
|
29
|
+
|
|
30
|
+
export {DualStreamMode} from './Contexts/PropsContext';
|
|
31
|
+
|
|
32
|
+
export type {
|
|
33
|
+
UidInterface,
|
|
34
|
+
ToggleState,
|
|
35
|
+
RtcPropsInterface,
|
|
36
|
+
CallbacksInterface,
|
|
37
|
+
CustomCallbacksInterface,
|
|
38
|
+
PropsInterface,
|
|
39
|
+
} from './Contexts/PropsContext';
|
|
40
|
+
|
|
41
|
+
export {
|
|
42
|
+
default as RtcContext,
|
|
43
|
+
RtcConsumer,
|
|
44
|
+
RtcProvider,
|
|
45
|
+
} from './Contexts/RtcContext';
|
|
46
|
+
export type {
|
|
47
|
+
RtcContextInterface,
|
|
48
|
+
DispatchType,
|
|
49
|
+
UidStateInterface,
|
|
50
|
+
ActionInterface,
|
|
51
|
+
ActionType,
|
|
52
|
+
} from './Contexts/RtcContext';
|
|
53
|
+
|
|
54
|
+
export {default as BtnTemplate} from './Controls/BtnTemplate';
|
|
55
|
+
export {default as Endcall} from './Controls/Local/EndCall';
|
|
56
|
+
export {default as FullScreen} from './Controls/Local/FullScreen';
|
|
57
|
+
export {default as LocalAudioMute} from './Controls/Local/LocalAudioMute';
|
|
58
|
+
export {default as LocalVideoMute} from './Controls/Local/LocalVideoMute';
|
|
59
|
+
export {default as SwitchCamera} from './Controls/Local/SwitchCamera';
|
|
60
|
+
export {default as Controls} from './Controls/LocalControls';
|
|
61
|
+
|
|
62
|
+
export {default as RemoteAudioMute} from './Controls/Remote/RemoteAudioMute';
|
|
63
|
+
export {default as RemoteSwap} from './Controls/Remote/RemoteSwap';
|
|
64
|
+
export {default as RemoteVideoMute} from './Controls/Remote/RemoteVideoMute';
|
|
65
|
+
export {default as RemoteControls} from './Controls/RemoteControls';
|
|
66
|
+
|
|
67
|
+
export {default as ImageIcon} from './Controls/ImageIcon';
|