agora-appbuilder-core 2.0.1 → 2.0.3-rc2
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/Readme.md +2 -1
- package/package.json +1 -1
- package/template/_package-lock.json +8853 -8806
- package/template/agora-rn-uikit/.git/index +0 -0
- package/template/agora-rn-uikit/.git/logs/HEAD +2 -2
- 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-2a0122bf5a3199f941e5a52535f43881623f752c.idx +0 -0
- package/template/agora-rn-uikit/.git/objects/pack/{pack-f379286d0537eb68377220b4929979324b8d5d1c.pack → pack-2a0122bf5a3199f941e5a52535f43881623f752c.pack} +0 -0
- package/template/agora-rn-uikit/.git/packed-refs +4 -2
- package/template/agora-rn-uikit/.git/refs/heads/ab-dev-auto +1 -1
- package/template/agora-rn-uikit/src/Contexts/PropsContext.tsx +21 -0
- package/template/agora-rn-uikit/src/Controls/BtnTemplate.tsx +22 -14
- package/template/agora-rn-uikit/src/Controls/ImageIcon.tsx +17 -13
- package/template/agora-rn-uikit/src/Controls/types.ts +4 -0
- package/template/agora-rn-uikit/src/Rtc/Create.tsx +117 -19
- package/template/agora-rn-uikit/src/RtcConfigure.tsx +24 -13
- package/template/{src/utils/isSafariBrowser.tsx → agora-rn-uikit/src/Utils/isSafariBrowser.ts} +3 -0
- package/template/{src → agora-rn-uikit/src}/hooks/useImageDelay.tsx +5 -2
- package/template/agora-rn-uikit/src/index.ts +2 -0
- package/template/bridge/rtc/webNg/RtcEngine.ts +73 -70
- package/template/bridge/rtc/webNg/Types.ts +59 -5
- package/template/bridge/rtm/web/Types.ts +13 -0
- package/template/bridge/rtm/web/index.ts +78 -1
- package/template/global.d.ts +2 -0
- package/template/package-lock.json +8853 -8806
- package/template/package.json +3 -4
- package/template/react-native-toast-message/src/components/base/styles.js +4 -2
- package/template/src/assets/icons.ts +41 -28
- package/template/src/components/Chat.tsx +70 -184
- package/template/src/components/ChatContext.ts +13 -2
- package/template/src/components/Controls.native.tsx +37 -76
- package/template/src/components/Controls.tsx +50 -158
- package/template/src/components/DeviceConfigure.native.tsx +5 -1
- package/template/src/components/DeviceConfigure.tsx +38 -20
- package/template/src/components/Navbar.tsx +185 -226
- package/template/src/components/ParticipantsView.tsx +176 -184
- package/template/src/components/Precall.native.tsx +83 -69
- package/template/src/components/Precall.tsx +174 -191
- package/template/src/components/RTMConfigure.tsx +264 -78
- package/template/src/components/SettingsView.tsx +9 -19
- package/template/src/components/livestream/LiveStreamContext.tsx +411 -0
- package/template/src/components/livestream/Types.ts +69 -0
- package/template/src/components/livestream/index.ts +9 -0
- package/template/src/components/livestream/views/LiveStreamControls.tsx +27 -0
- package/template/src/components/participants/AllAudienceParticipants.tsx +53 -0
- package/template/src/components/participants/AllHostParticipants.tsx +65 -0
- package/template/src/components/participants/MeParticipant.tsx +37 -0
- package/template/src/components/participants/ParticipantName.tsx +47 -0
- package/template/src/components/participants/ParticipantSectionTitle.tsx +29 -0
- package/template/src/components/participants/RemoteParticipants.tsx +69 -0
- package/template/src/components/participants/ScreenshareParticipants.tsx +28 -0
- package/template/src/components/participants/context/ParticipantContext.tsx +97 -0
- package/template/src/components/styles.ts +13 -0
- package/template/src/pages/Create.tsx +25 -14
- package/template/src/pages/VideoCall.tsx +197 -159
- package/template/src/subComponents/ChatBubble.tsx +4 -1
- package/template/src/subComponents/ChatContainer.tsx +44 -20
- package/template/src/subComponents/ChatInput.tsx +4 -12
- package/template/src/subComponents/Checkbox.native.tsx +6 -5
- package/template/src/subComponents/Checkbox.tsx +1 -0
- package/template/src/subComponents/Recording.tsx +23 -9
- package/template/src/subComponents/RemoteVideoMute.tsx +2 -3
- package/template/src/subComponents/SelectDevice.tsx +70 -35
- package/template/src/subComponents/chat/ChatParticipants.tsx +121 -0
- package/template/src/subComponents/livestream/ApprovedLiveStreamControlsView.tsx +23 -0
- package/template/src/subComponents/livestream/CurrentLiveStreamRequestsView.tsx +70 -0
- package/template/src/subComponents/livestream/controls/LocalRaiseHand.tsx +57 -0
- package/template/src/subComponents/livestream/controls/RemoteLiveStreamApprovedRequestRecall.tsx +24 -0
- package/template/src/subComponents/livestream/controls/RemoteLiveStreamRequestApprove.tsx +38 -0
- package/template/src/subComponents/livestream/controls/RemoteLiveStreamRequestReject.tsx +37 -0
- package/template/src/subComponents/livestream/index.ts +18 -0
- package/template/src/subComponents/screenshare/ScreenshareButton.tsx +80 -0
- package/template/src/subComponents/screenshare/ScreenshareConfigure.native.tsx +24 -0
- package/template/src/subComponents/screenshare/ScreenshareConfigure.tsx +200 -0
- package/template/src/subComponents/screenshare/ScreenshareContext.tsx +21 -0
- package/template/src/utils/index.tsx +48 -0
- package/template/agora-rn-uikit/.git/objects/pack/pack-f379286d0537eb68377220b4929979324b8d5d1c.idx +0 -0
|
Binary file
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
0000000000000000000000000000000000000000 7f9cd41e1bf3ea1b110e2706c7e4c5a921230647 nitte93 <nitte.tiwari1993@gmail.com>
|
|
2
|
-
7f9cd41e1bf3ea1b110e2706c7e4c5a921230647
|
|
1
|
+
0000000000000000000000000000000000000000 7f9cd41e1bf3ea1b110e2706c7e4c5a921230647 nitte93 <nitte.tiwari1993@gmail.com> 1648625876 +0530 clone: from https://github.com/AgoraIO-Community/ReactNative-UIKit
|
|
2
|
+
7f9cd41e1bf3ea1b110e2706c7e4c5a921230647 bdb1c4d92e97621ce53b0f1120956832f7617af9 nitte93 <nitte.tiwari1993@gmail.com> 1648625876 +0530 checkout: moving from master to ab-dev-auto
|
|
@@ -1 +1 @@
|
|
|
1
|
-
0000000000000000000000000000000000000000
|
|
1
|
+
0000000000000000000000000000000000000000 bdb1c4d92e97621ce53b0f1120956832f7617af9 nitte93 <nitte.tiwari1993@gmail.com> 1648625876 +0530 branch: Created from refs/remotes/origin/ab-dev-auto
|
|
@@ -1 +1 @@
|
|
|
1
|
-
0000000000000000000000000000000000000000 7f9cd41e1bf3ea1b110e2706c7e4c5a921230647 nitte93 <nitte.tiwari1993@gmail.com>
|
|
1
|
+
0000000000000000000000000000000000000000 7f9cd41e1bf3ea1b110e2706c7e4c5a921230647 nitte93 <nitte.tiwari1993@gmail.com> 1648625876 +0530 clone: from https://github.com/AgoraIO-Community/ReactNative-UIKit
|
|
@@ -1 +1 @@
|
|
|
1
|
-
0000000000000000000000000000000000000000 7f9cd41e1bf3ea1b110e2706c7e4c5a921230647 nitte93 <nitte.tiwari1993@gmail.com>
|
|
1
|
+
0000000000000000000000000000000000000000 7f9cd41e1bf3ea1b110e2706c7e4c5a921230647 nitte93 <nitte.tiwari1993@gmail.com> 1648625876 +0530 clone: from https://github.com/AgoraIO-Community/ReactNative-UIKit
|
package/template/agora-rn-uikit/.git/objects/pack/pack-2a0122bf5a3199f941e5a52535f43881623f752c.idx
ADDED
|
Binary file
|
|
Binary file
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# pack-refs with: peeled fully-peeled sorted
|
|
2
|
-
|
|
2
|
+
bdb1c4d92e97621ce53b0f1120956832f7617af9 refs/remotes/origin/ab-dev-auto
|
|
3
3
|
fd59daf4876e4eb142856957f9450ef5175f4e0f refs/remotes/origin/app-builder
|
|
4
4
|
c60cde905c722aeaf8f25aeed2910a7b4d532cfa refs/remotes/origin/app-builder-dev
|
|
5
5
|
83064dc5031b9a88a170c6b91ee725ad072eadb1 refs/remotes/origin/bugfix/camera-green-light-on-precall
|
|
6
6
|
5d4f38ae0a89b20275e2497a4e8f43b0ca2830e4 refs/remotes/origin/dev
|
|
7
7
|
4ec093e51924049e37d247d867a5482a9376a8cf refs/remotes/origin/docs
|
|
8
8
|
002960cf34f06ffd3e905e6de9865460f02bd910 refs/remotes/origin/feat/icon-tint
|
|
9
|
-
|
|
9
|
+
c7d21d289c4e930f57cbe3a2eefbbfc0d9741c6f refs/remotes/origin/feature/fpe-internationlization
|
|
10
|
+
bfdb92d89cf66d270bed81748c39330846532d07 refs/remotes/origin/feature/life_cycle_events
|
|
11
|
+
7c60e844f617d9c0faf6aa968fdf16b16d0e59ce refs/remotes/origin/feature/ui-kit/raise-hand
|
|
10
12
|
7f9cd41e1bf3ea1b110e2706c7e4c5a921230647 refs/remotes/origin/master
|
|
11
13
|
01ad019ae514b6502b64a30b357a20af49b8c8a5 refs/remotes/origin/refactor
|
|
12
14
|
ac8929fda04db3663a7c1eb9c71ca6a97728f0eb refs/remotes/origin/v2-legacy
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
bdb1c4d92e97621ce53b0f1120956832f7617af9
|
|
@@ -4,6 +4,24 @@ import {RtcEngineEvents} from 'react-native-agora/lib/typescript/src/common/RtcE
|
|
|
4
4
|
import {EncryptionMode} from 'react-native-agora';
|
|
5
5
|
import {VideoProfile} from '../Utils/quality';
|
|
6
6
|
|
|
7
|
+
/* User role for live streaming mode */
|
|
8
|
+
export enum ClientRole {
|
|
9
|
+
/* 1: A host can both send and receive streams. */
|
|
10
|
+
Broadcaster = 1,
|
|
11
|
+
/* 2: The default role. An audience can only receive streams. */
|
|
12
|
+
Audience = 2,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* Mode for RTC (Live or Broadcast) */
|
|
16
|
+
export enum ChannelProfile {
|
|
17
|
+
/** 0: (Default) The Communication profile.
|
|
18
|
+
* Use this profile in one-on-one calls or group calls, where all users can talk freely. */
|
|
19
|
+
Communication = 0,
|
|
20
|
+
/** 1: The Live-Broadcast profile.
|
|
21
|
+
* Users in a live-broadcast channel have a role as either host or audience. A host can both send and receive streams; an audience can only receive streams. */
|
|
22
|
+
LiveBroadcasting = 1,
|
|
23
|
+
}
|
|
24
|
+
|
|
7
25
|
// disabled is intentionally kept as the 1st item in the enum.
|
|
8
26
|
// This way, it evaluates to a falsy value in a if statement
|
|
9
27
|
export enum ToggleState {
|
|
@@ -29,6 +47,7 @@ interface remoteBtnStylesInterface {
|
|
|
29
47
|
muteRemoteVideo?: StyleProp<ViewStyle>;
|
|
30
48
|
remoteSwap?: StyleProp<ViewStyle>;
|
|
31
49
|
minCloseBtnStyles?: StyleProp<ViewStyle>;
|
|
50
|
+
liveStreamHostControlBtns?: StyleProp<ViewStyle>;
|
|
32
51
|
}
|
|
33
52
|
|
|
34
53
|
interface localBtnStylesInterface {
|
|
@@ -64,6 +83,7 @@ export interface RtcPropsInterface {
|
|
|
64
83
|
dual?: boolean | null;
|
|
65
84
|
profile?: VideoProfile;
|
|
66
85
|
initialDualStreamMode?: DualStreamMode;
|
|
86
|
+
role?: ClientRole /* Set local user's role between audience and host. Use with mode set to livestreaming. (default: host) */;
|
|
67
87
|
callActive?: boolean;
|
|
68
88
|
encryption?: {
|
|
69
89
|
key: string;
|
|
@@ -97,6 +117,7 @@ export interface PropsInterface {
|
|
|
97
117
|
rtcProps: RtcPropsInterface;
|
|
98
118
|
styleProps?: Partial<StylePropInterface>;
|
|
99
119
|
callbacks?: Partial<CallbacksInterface>;
|
|
120
|
+
mode?: ChannelProfile;
|
|
100
121
|
}
|
|
101
122
|
|
|
102
123
|
const initialValue: PropsInterface = {
|
|
@@ -7,21 +7,31 @@ import {
|
|
|
7
7
|
ViewStyle,
|
|
8
8
|
Text,
|
|
9
9
|
View,
|
|
10
|
+
Platform,
|
|
10
11
|
} from 'react-native';
|
|
11
12
|
import PropsContext from '../Contexts/PropsContext';
|
|
12
13
|
import styles from '../Style';
|
|
13
14
|
import icons, {IconsInterface} from './Icons';
|
|
14
|
-
import useImageDelay from '
|
|
15
|
-
import
|
|
15
|
+
import useImageDelay from '../hooks/useImageDelay';
|
|
16
|
+
import {Either} from './types';
|
|
16
17
|
|
|
17
|
-
interface
|
|
18
|
-
name: keyof IconsInterface;
|
|
18
|
+
interface BtnTemplateBasicInterface {
|
|
19
19
|
color?: string;
|
|
20
20
|
onPress?: TouchableOpacityProps['onPress'];
|
|
21
21
|
style?: StyleProp<ViewStyle>;
|
|
22
22
|
btnText?: string;
|
|
23
23
|
disabled?: boolean;
|
|
24
24
|
}
|
|
25
|
+
interface BtnTemplateInterfaceWithName extends BtnTemplateBasicInterface {
|
|
26
|
+
name?: keyof IconsInterface;
|
|
27
|
+
}
|
|
28
|
+
interface BtnTemplateInterfaceWithIcon extends BtnTemplateBasicInterface {
|
|
29
|
+
icon?: any;
|
|
30
|
+
}
|
|
31
|
+
type BtnTemplateInterface = Either<
|
|
32
|
+
BtnTemplateInterfaceWithIcon,
|
|
33
|
+
BtnTemplateInterfaceWithName
|
|
34
|
+
>;
|
|
25
35
|
|
|
26
36
|
const BtnTemplate: React.FC<BtnTemplateInterface> = (props) => {
|
|
27
37
|
const {disabled = false} = props;
|
|
@@ -30,10 +40,8 @@ const BtnTemplate: React.FC<BtnTemplateInterface> = (props) => {
|
|
|
30
40
|
|
|
31
41
|
const imageRef = React.useRef(null);
|
|
32
42
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
useImageDelay(imageRef, 10, '');
|
|
36
|
-
}
|
|
43
|
+
// This fixes the tint issue in safari browser
|
|
44
|
+
useImageDelay(imageRef, 10, '', props?.color || '');
|
|
37
45
|
|
|
38
46
|
return (
|
|
39
47
|
<TouchableOpacity
|
|
@@ -46,23 +54,23 @@ const BtnTemplate: React.FC<BtnTemplateInterface> = (props) => {
|
|
|
46
54
|
props.style as object,
|
|
47
55
|
]}>
|
|
48
56
|
<Image
|
|
49
|
-
ref={imageRef}
|
|
57
|
+
ref={Platform.OS === 'web' ? imageRef : undefined}
|
|
50
58
|
style={{
|
|
51
59
|
width: '100%',
|
|
52
60
|
height: '100%',
|
|
53
|
-
opacity: disabled ?
|
|
54
|
-
tintColor: disabled ? 'grey' :
|
|
61
|
+
opacity: disabled ? 0.4 : 1,
|
|
62
|
+
tintColor: disabled ? 'grey' : props.color || theme || '#fff',
|
|
55
63
|
}}
|
|
56
64
|
resizeMode={'contain'}
|
|
57
|
-
source={{uri: icons[props.name]}}
|
|
65
|
+
source={{uri: props.name ? icons[props.name] : props.icon}}
|
|
58
66
|
/>
|
|
59
67
|
</View>
|
|
60
68
|
<Text
|
|
61
69
|
style={{
|
|
62
70
|
textAlign: 'center',
|
|
63
71
|
marginTop: 5,
|
|
64
|
-
color: disabled ? 'grey' :
|
|
65
|
-
opacity: disabled ? 0.4 : 1
|
|
72
|
+
color: disabled ? 'grey' : props.color || theme || '#fff',
|
|
73
|
+
opacity: disabled ? 0.4 : 1,
|
|
66
74
|
}}>
|
|
67
75
|
{props.btnText}
|
|
68
76
|
</Text>
|
|
@@ -10,42 +10,46 @@
|
|
|
10
10
|
*********************************************
|
|
11
11
|
*/
|
|
12
12
|
import React, {useContext} from 'react';
|
|
13
|
-
import {Image, StyleProp, ViewStyle} from 'react-native';
|
|
13
|
+
import {Image, Platform, StyleProp, ViewStyle} from 'react-native';
|
|
14
14
|
import icons, {IconsInterface} from './Icons';
|
|
15
15
|
import PropsContext from './../Contexts/PropsContext';
|
|
16
|
-
import useImageDelay from '
|
|
17
|
-
import
|
|
16
|
+
import useImageDelay from '../hooks/useImageDelay';
|
|
17
|
+
import {Either} from './types';
|
|
18
18
|
|
|
19
|
-
interface
|
|
20
|
-
name: keyof IconsInterface;
|
|
19
|
+
interface BaseInterface {
|
|
21
20
|
color?: string;
|
|
22
21
|
style?: StyleProp<ViewStyle>;
|
|
23
22
|
}
|
|
24
23
|
|
|
24
|
+
interface BaseInterfaceWithName extends BaseInterface {
|
|
25
|
+
name?: keyof IconsInterface;
|
|
26
|
+
}
|
|
27
|
+
interface BaseInterfaceWithIcon extends BaseInterface {
|
|
28
|
+
icon?: any;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
type ImageIconInterface = Either<BaseInterfaceWithName, BaseInterfaceWithIcon>;
|
|
32
|
+
|
|
25
33
|
const ImageIcon: React.FC<ImageIconInterface> = (props) => {
|
|
26
34
|
const {styleProps} = useContext(PropsContext);
|
|
27
35
|
const {theme} = styleProps || {};
|
|
28
36
|
const imageRef = React.useRef(null);
|
|
29
37
|
|
|
30
|
-
|
|
31
|
-
// This hook renders the image after a delay to fix
|
|
32
|
-
// tint issue in safari browser
|
|
33
|
-
useImageDelay(imageRef, 10, props.name);
|
|
34
|
-
}
|
|
38
|
+
useImageDelay(imageRef, 10, props?.name || '', props?.color);
|
|
35
39
|
|
|
36
40
|
return (
|
|
37
41
|
<Image
|
|
38
|
-
ref={imageRef}
|
|
42
|
+
ref={Platform.OS === 'web' ? imageRef : undefined}
|
|
39
43
|
style={[
|
|
40
44
|
{
|
|
41
45
|
width: '100%',
|
|
42
46
|
height: '100%',
|
|
43
|
-
tintColor: props.color || theme || '#fff'
|
|
47
|
+
tintColor: props.color || theme || '#fff',
|
|
44
48
|
},
|
|
45
49
|
props.style as object,
|
|
46
50
|
]}
|
|
47
51
|
resizeMode={'contain'}
|
|
48
|
-
source={{uri: icons[props.name]}}
|
|
52
|
+
source={{uri: props.name ? icons[props.name] : props.icon}}
|
|
49
53
|
/>
|
|
50
54
|
);
|
|
51
55
|
};
|
|
@@ -6,7 +6,11 @@ import RtcEngine, {
|
|
|
6
6
|
import {Platform} from 'react-native';
|
|
7
7
|
import requestCameraAndAudioPermission from '../Utils/permission';
|
|
8
8
|
import {DispatchType} from '../Contexts/RtcContext';
|
|
9
|
-
import PropsContext, {
|
|
9
|
+
import PropsContext, {
|
|
10
|
+
ToggleState,
|
|
11
|
+
ClientRole,
|
|
12
|
+
ChannelProfile,
|
|
13
|
+
} from '../Contexts/PropsContext';
|
|
10
14
|
import quality from '../Utils/quality';
|
|
11
15
|
|
|
12
16
|
const Create = ({
|
|
@@ -17,8 +21,10 @@ const Create = ({
|
|
|
17
21
|
children: (engine: React.MutableRefObject<RtcEngine>) => JSX.Element;
|
|
18
22
|
}) => {
|
|
19
23
|
const [ready, setReady] = useState(false);
|
|
20
|
-
const {callbacks, rtcProps} = useContext(PropsContext);
|
|
24
|
+
const {callbacks, rtcProps, mode} = useContext(PropsContext);
|
|
21
25
|
let engine = useRef<RtcEngine>({} as RtcEngine);
|
|
26
|
+
const isVideoEnabledRef = useRef<boolean>(false);
|
|
27
|
+
const firstUpdate = useRef(true);
|
|
22
28
|
|
|
23
29
|
useEffect(() => {
|
|
24
30
|
async function init() {
|
|
@@ -36,6 +42,19 @@ const Create = ({
|
|
|
36
42
|
} else {
|
|
37
43
|
engine.current = await RtcEngine.create(rtcProps.appId);
|
|
38
44
|
}
|
|
45
|
+
/* Live Streaming */
|
|
46
|
+
if (mode == ChannelProfile.LiveBroadcasting) {
|
|
47
|
+
await engine.current.setChannelProfile(
|
|
48
|
+
ChannelProfile.LiveBroadcasting,
|
|
49
|
+
);
|
|
50
|
+
await engine.current.setClientRole(
|
|
51
|
+
rtcProps.role === ClientRole.Audience
|
|
52
|
+
? ClientRole.Audience
|
|
53
|
+
: ClientRole.Broadcaster,
|
|
54
|
+
);
|
|
55
|
+
} else {
|
|
56
|
+
await engine.current.setChannelProfile(ChannelProfile.Communication);
|
|
57
|
+
}
|
|
39
58
|
if (rtcProps.profile) {
|
|
40
59
|
if (Platform.OS === 'web') {
|
|
41
60
|
// move this to bridge?
|
|
@@ -49,18 +68,36 @@ const Create = ({
|
|
|
49
68
|
});
|
|
50
69
|
}
|
|
51
70
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* API enableVideo :
|
|
74
|
+
* On Web -> Asks permissions and then creates microphone and camera tracks
|
|
75
|
+
* On Native -> Used to start the call in video module
|
|
76
|
+
* The following condition allows enableVideo API to run in all the conditions
|
|
77
|
+
* except when mode is livestreaming && user is attendee && running on web,
|
|
78
|
+
* thereby not asking permissions and not creating tracks for attendees
|
|
79
|
+
*/
|
|
80
|
+
if (
|
|
81
|
+
!(
|
|
82
|
+
mode === ChannelProfile.LiveBroadcasting &&
|
|
83
|
+
rtcProps.role == ClientRole.Audience &&
|
|
84
|
+
Platform.OS === 'web'
|
|
85
|
+
)
|
|
86
|
+
) {
|
|
87
|
+
try {
|
|
88
|
+
await engine.current.enableVideo();
|
|
89
|
+
isVideoEnabledRef.current = true;
|
|
90
|
+
} catch (e) {
|
|
91
|
+
dispatch({
|
|
92
|
+
type: 'LocalMuteAudio',
|
|
93
|
+
value: [ToggleState.disabled],
|
|
94
|
+
});
|
|
95
|
+
dispatch({
|
|
96
|
+
type: 'LocalMuteVideo',
|
|
97
|
+
value: [ToggleState.disabled],
|
|
98
|
+
});
|
|
99
|
+
console.error('No devices', e);
|
|
100
|
+
}
|
|
64
101
|
}
|
|
65
102
|
|
|
66
103
|
engine.current.addListener(
|
|
@@ -95,8 +132,6 @@ const Create = ({
|
|
|
95
132
|
});
|
|
96
133
|
|
|
97
134
|
engine.current.addListener('RemoteAudioStateChanged', (...args) => {
|
|
98
|
-
// console.log('RemoteAudioStateChanged', args);
|
|
99
|
-
|
|
100
135
|
dispatch({
|
|
101
136
|
type: 'RemoteAudioStateChanged',
|
|
102
137
|
value: args,
|
|
@@ -108,8 +143,6 @@ const Create = ({
|
|
|
108
143
|
});
|
|
109
144
|
|
|
110
145
|
engine.current.addListener('RemoteVideoStateChanged', (...args) => {
|
|
111
|
-
// console.log('RemoteVideoStateChanged', args);
|
|
112
|
-
|
|
113
146
|
dispatch({
|
|
114
147
|
type: 'RemoteVideoStateChanged',
|
|
115
148
|
value: args,
|
|
@@ -124,7 +157,72 @@ const Create = ({
|
|
|
124
157
|
return () => {
|
|
125
158
|
engine.current!.destroy();
|
|
126
159
|
};
|
|
127
|
-
}, []);
|
|
160
|
+
}, [rtcProps.appId]);
|
|
161
|
+
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
const toggleRole = async () => {
|
|
164
|
+
if (mode == ChannelProfile.LiveBroadcasting) {
|
|
165
|
+
if (rtcProps.role == ClientRole.Broadcaster) {
|
|
166
|
+
await engine.current?.setClientRole(ClientRole.Broadcaster);
|
|
167
|
+
// isVideoEnabledRef checks if the permission is already taken once
|
|
168
|
+
if (!isVideoEnabledRef.current) {
|
|
169
|
+
try {
|
|
170
|
+
// This creates local audio and video track
|
|
171
|
+
await engine.current?.enableVideo();
|
|
172
|
+
isVideoEnabledRef.current = true;
|
|
173
|
+
} catch (error) {
|
|
174
|
+
dispatch({
|
|
175
|
+
type: 'LocalMuteAudio',
|
|
176
|
+
value: [ToggleState.disabled],
|
|
177
|
+
});
|
|
178
|
+
dispatch({
|
|
179
|
+
type: 'LocalMuteVideo',
|
|
180
|
+
value: [ToggleState.disabled],
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (isVideoEnabledRef.current) {
|
|
185
|
+
// This unpublishes the current track
|
|
186
|
+
await engine.current?.muteLocalAudioStream(true);
|
|
187
|
+
await engine.current?.muteLocalVideoStream(true);
|
|
188
|
+
// This updates the uid interface
|
|
189
|
+
dispatch({
|
|
190
|
+
type: 'LocalMuteAudio',
|
|
191
|
+
value: [ToggleState.disabled],
|
|
192
|
+
});
|
|
193
|
+
dispatch({
|
|
194
|
+
type: 'LocalMuteVideo',
|
|
195
|
+
value: [ToggleState.disabled],
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (rtcProps.role == ClientRole.Audience) {
|
|
200
|
+
/**
|
|
201
|
+
* To switch the user role back to "audience", call unpublish first
|
|
202
|
+
* Otherwise the setClientRole method call fails and throws an exception.
|
|
203
|
+
*/
|
|
204
|
+
await engine.current?.muteLocalAudioStream(true);
|
|
205
|
+
await engine.current?.muteLocalVideoStream(true);
|
|
206
|
+
dispatch({
|
|
207
|
+
type: 'LocalMuteAudio',
|
|
208
|
+
value: [ToggleState.disabled],
|
|
209
|
+
});
|
|
210
|
+
dispatch({
|
|
211
|
+
type: 'LocalMuteVideo',
|
|
212
|
+
value: [ToggleState.disabled],
|
|
213
|
+
});
|
|
214
|
+
await engine.current?.setClientRole(ClientRole.Audience);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
// The firstUpdateCurrent ref skips the render of this block for the first time
|
|
219
|
+
if (firstUpdate.current) {
|
|
220
|
+
firstUpdate.current = false;
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
toggleRole();
|
|
224
|
+
}, [rtcProps.role]);
|
|
225
|
+
|
|
128
226
|
return (
|
|
129
227
|
<>
|
|
130
228
|
{
|
|
@@ -11,6 +11,8 @@ import PropsContext, {
|
|
|
11
11
|
RtcPropsInterface,
|
|
12
12
|
CallbacksInterface,
|
|
13
13
|
DualStreamMode,
|
|
14
|
+
ClientRole,
|
|
15
|
+
ChannelProfile,
|
|
14
16
|
} from './Contexts/PropsContext';
|
|
15
17
|
import {MinUidProvider} from './Contexts/MinUidContext';
|
|
16
18
|
import {MaxUidProvider} from './Contexts/MaxUidContext';
|
|
@@ -30,23 +32,32 @@ import {
|
|
|
30
32
|
import Create from './Rtc/Create';
|
|
31
33
|
import Join from './Rtc/Join';
|
|
32
34
|
|
|
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
35
|
const RtcConfigure: React.FC<Partial<RtcPropsInterface>> = (props) => {
|
|
46
|
-
const {callbacks, rtcProps} = useContext(PropsContext);
|
|
36
|
+
const {callbacks, rtcProps, mode} = useContext(PropsContext);
|
|
47
37
|
let [dualStreamMode, setDualStreamMode] = useState<DualStreamMode>(
|
|
48
38
|
rtcProps?.initialDualStreamMode || DualStreamMode.DYNAMIC,
|
|
49
39
|
);
|
|
40
|
+
|
|
41
|
+
const initialLocalState: UidStateInterface = {
|
|
42
|
+
min: [],
|
|
43
|
+
max: [
|
|
44
|
+
{
|
|
45
|
+
uid: 'local',
|
|
46
|
+
audio:
|
|
47
|
+
mode == ChannelProfile.LiveBroadcasting &&
|
|
48
|
+
rtcProps?.role == ClientRole.Audience
|
|
49
|
+
? ToggleState.disabled
|
|
50
|
+
: ToggleState.enabled,
|
|
51
|
+
video:
|
|
52
|
+
mode == ChannelProfile.LiveBroadcasting &&
|
|
53
|
+
rtcProps?.role == ClientRole.Audience
|
|
54
|
+
? ToggleState.disabled
|
|
55
|
+
: ToggleState.enabled,
|
|
56
|
+
streamType: 'high',
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
};
|
|
60
|
+
|
|
50
61
|
const [initialState, setInitialState] = React.useState(
|
|
51
62
|
JSON.parse(JSON.stringify(initialLocalState)),
|
|
52
63
|
);
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import isSafariBrowser from '../Utils/isSafariBrowser';
|
|
2
3
|
|
|
3
4
|
function useImageDelay(
|
|
4
5
|
elementRef: any,
|
|
5
6
|
delay: number | null,
|
|
6
7
|
imageName: string,
|
|
8
|
+
tintColor?: string,
|
|
7
9
|
) {
|
|
8
|
-
// Remember the latest callback if it changes.
|
|
9
10
|
React.useEffect(() => {
|
|
11
|
+
if (!isSafariBrowser()) return;
|
|
10
12
|
// The following block allows to repaint the icon
|
|
11
13
|
let imageElement: any;
|
|
12
14
|
if (elementRef && elementRef.current) {
|
|
@@ -21,8 +23,9 @@ function useImageDelay(
|
|
|
21
23
|
imageElement.style.display = 'initial';
|
|
22
24
|
}
|
|
23
25
|
}, delay);
|
|
26
|
+
|
|
24
27
|
return () => clearTimeout(timer);
|
|
25
|
-
}, [imageName]);
|
|
28
|
+
}, [imageName, tintColor]);
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
export default useImageDelay;
|