diff --git a/package-lock.json b/package-lock.json index 0868a06fb..127c7dad0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { "name": "agora-appbuilder-core", - "version": "4.1.8-3", + "version": "4.1.8-4", "lockfileVersion": 1 } diff --git a/package.json b/package.json index 8f160cae9..afbfd336e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "agora-appbuilder-core", - "version": "4.1.8-3", + "version": "4.1.8-4", "description": "React Native template for RTE app builder", "main": "index.js", "files": [ diff --git a/template/defaultConfig.js b/template/defaultConfig.js index 19d8fd349..d0d47d120 100644 --- a/template/defaultConfig.js +++ b/template/defaultConfig.js @@ -77,8 +77,8 @@ const DefaultConfig = { CHAT_ORG_NAME: '', CHAT_APP_NAME: '', CHAT_URL: '', - CLI_VERSION: '3.1.8-3', - CORE_VERSION: '4.1.8-3', + CLI_VERSION: '3.1.8-4', + CORE_VERSION: '4.1.8-4', DISABLE_LANDSCAPE_MODE: false, STT_AUTO_START: false, CLOUD_RECORDING_AUTO_START: false, diff --git a/template/src/atoms/Input.tsx b/template/src/atoms/Input.tsx index c19d2380e..3fea6cf63 100644 --- a/template/src/atoms/Input.tsx +++ b/template/src/atoms/Input.tsx @@ -60,7 +60,7 @@ const styles = StyleSheet.create({ // height: 60, //causes text cut off in android width: '100%', borderWidth: 1, - paddingVertical: 21, + paddingVertical: 12, paddingHorizontal: 16, borderColor: $config.INPUT_FIELD_BORDER_COLOR, color: $config.FONT_COLOR, @@ -71,6 +71,7 @@ const styles = StyleSheet.create({ ...Platform.select({ web: { outlineStyle: 'none', + lineHeight: '26px', }, }), }, diff --git a/template/src/components/precall/joinCallBtn.native.tsx b/template/src/components/precall/joinCallBtn.native.tsx index ce2971160..487e03f33 100644 --- a/template/src/components/precall/joinCallBtn.native.tsx +++ b/template/src/components/precall/joinCallBtn.native.tsx @@ -33,7 +33,7 @@ export interface PreCallJoinCallBtnProps { const JoinCallBtn = (props: PreCallJoinCallBtnProps) => { const {rtcProps} = useContext(PropsContext); - const {setCallActive} = usePreCall(); + const {setCallActive, setIsNameIsEmpty} = usePreCall(); const username = useGetName(); const {isJoinDataFetched} = useRoomInfo(); const joinRoomButton = @@ -58,12 +58,17 @@ const JoinCallBtn = (props: PreCallJoinCallBtnProps) => { }, [rtcProps?.role]); const onSubmit = () => { + if (!username || (username && username?.trim() === '')) { + setIsNameIsEmpty(true); + return; + } + setIsNameIsEmpty(false); setCallActive(true); }; const title = buttonText; const onPress = () => onSubmit(); - const disabled = !isJoinDataFetched || username === ''; + const disabled = !isJoinDataFetched; return props?.render ? ( props.render(onPress, title, disabled) ) : ( diff --git a/template/src/components/precall/joinCallBtn.tsx b/template/src/components/precall/joinCallBtn.tsx index 56ba22fb2..5dcdf4992 100644 --- a/template/src/components/precall/joinCallBtn.tsx +++ b/template/src/components/precall/joinCallBtn.tsx @@ -42,7 +42,7 @@ export interface PreCallJoinCallBtnProps { const JoinCallBtn = (props: PreCallJoinCallBtnProps) => { const {rtcProps} = useContext(PropsContext); - const {setCallActive} = usePreCall(); + const {setCallActive, setIsNameIsEmpty} = usePreCall(); const username = useGetName(); const setUsername = useSetName(); const {isJoinDataFetched} = useRoomInfo(); @@ -59,6 +59,11 @@ const JoinCallBtn = (props: PreCallJoinCallBtnProps) => { ); const onSubmit = () => { + if (!username || (username && username?.trim() === '')) { + setIsNameIsEmpty(true); + return; + } + setIsNameIsEmpty(false); logger.log( LogSource.Internals, 'PRECALL_SCREEN', @@ -95,7 +100,7 @@ const JoinCallBtn = (props: PreCallJoinCallBtnProps) => { const title = buttonText; const onPress = () => onSubmit(); - const disabled = !isJoinDataFetched || username?.trim() === ''; + const disabled = !isJoinDataFetched; return props?.render ? ( props.render(onPress, title, disabled) ) : ( diff --git a/template/src/components/precall/joinWaitingRoomBtn.native.tsx b/template/src/components/precall/joinWaitingRoomBtn.native.tsx index 5abb48992..bf952aa0f 100644 --- a/template/src/components/precall/joinWaitingRoomBtn.native.tsx +++ b/template/src/components/precall/joinWaitingRoomBtn.native.tsx @@ -58,7 +58,7 @@ const JoinWaitingRoomBtn = (props: PreCallJoinWaitingRoomBtnProps) => { const waitingRoomUsersInCallText = useString(waitingRoomUsersInCall); let pollingTimeout = React.useRef(null); const {rtcProps} = useContext(PropsContext); - const {setCallActive, callActive} = usePreCall(); + const {setCallActive, callActive, setIsNameIsEmpty} = usePreCall(); const username = useGetName(); const {isJoinDataFetched, isInWaitingRoom} = useRoomInfo(); const {setRoomInfo} = useSetRoomInfo(); @@ -212,6 +212,11 @@ const JoinWaitingRoomBtn = (props: PreCallJoinWaitingRoomBtnProps) => { }; const onSubmit = () => { + if (!username || (username && username?.trim() === '')) { + setIsNameIsEmpty(true); + return; + } + setIsNameIsEmpty(false); shouldWaitingRoomPoll = true; // Enter waiting rooom; setRoomInfo(prev => { @@ -232,8 +237,8 @@ const JoinWaitingRoomBtn = (props: PreCallJoinWaitingRoomBtnProps) => { const title = buttonText; const onPress = () => onSubmit(); const disabled = $config.ENABLE_WAITING_ROOM_AUTO_REQUEST - ? !hasHostJoined || isInWaitingRoom || username?.trim() === '' - : isInWaitingRoom || username?.trim() === ''; + ? !hasHostJoined || isInWaitingRoom + : isInWaitingRoom; return props?.render ? ( props.render(onPress, title, disabled) ) : ( diff --git a/template/src/components/precall/joinWaitingRoomBtn.tsx b/template/src/components/precall/joinWaitingRoomBtn.tsx index 8d5be8efd..80362ea4b 100644 --- a/template/src/components/precall/joinWaitingRoomBtn.tsx +++ b/template/src/components/precall/joinWaitingRoomBtn.tsx @@ -45,6 +45,8 @@ import { waitingRoomHostNotJoined, waitingRoomUsersInCall, } from '../../language/default-labels/videoCallScreenLabels'; +import SDKEvents from '../../utils/SdkEvents'; +import isSDK from '../../utils/isSDK'; const audio = new Audio( 'https://dl.dropboxusercontent.com/s/1cdwpm3gca9mlo0/kick.mp3', @@ -69,7 +71,7 @@ const JoinWaitingRoomBtn = (props: PreCallJoinWaitingRoomBtnProps) => { const waitingRoomUsersInCallText = useString(waitingRoomUsersInCall); let pollingTimeout = React.useRef(null); const {rtcProps} = useContext(PropsContext); - const {setCallActive, callActive} = usePreCall(); + const {setCallActive, callActive, setIsNameIsEmpty} = usePreCall(); const username = useGetName(); const setUsername = useSetName(); const {isJoinDataFetched, isInWaitingRoom} = useRoomInfo(); @@ -150,6 +152,10 @@ const JoinWaitingRoomBtn = (props: PreCallJoinWaitingRoomBtnProps) => { }); if (approved) { + if (isSDK()) { + //emit SDKEvent waiting-room-approval-granted + SDKEvents.emit('waiting-room-approval-granted'); + } setRoomInfo(prev => { return { ...prev, @@ -189,6 +195,10 @@ const JoinWaitingRoomBtn = (props: PreCallJoinWaitingRoomBtnProps) => { }; }); } else { + if (isSDK()) { + //emit SDKEvent waiting-room-approval-rejected + SDKEvents.emit('waiting-room-approval-rejected'); + } setRoomInfo(prev => { return { ...prev, @@ -236,6 +246,11 @@ const JoinWaitingRoomBtn = (props: PreCallJoinWaitingRoomBtnProps) => { }; const onSubmit = () => { + if (!username || (username && username?.trim() === '')) { + setIsNameIsEmpty(true); + return; + } + setIsNameIsEmpty(false); shouldWaitingRoomPoll = true; setUsername(username.trim()); //setCallActive(true); @@ -252,7 +267,10 @@ const JoinWaitingRoomBtn = (props: PreCallJoinWaitingRoomBtnProps) => { // join request API to server, server will send RTM message to all hosts regarding request from this user, requestServerToJoinRoom(); - + if (isSDK()) { + //emit SDKEvent waiting for approval + SDKEvents.emit('waiting-room-approval-requested'); + } // Play a sound to avoid autoblocking in safari if (isWebInternal() || isMobileOrTablet()) { audio.volume = 0; @@ -281,8 +299,8 @@ const JoinWaitingRoomBtn = (props: PreCallJoinWaitingRoomBtnProps) => { const title = buttonText; const onPress = () => onSubmit(); const disabled = $config.ENABLE_WAITING_ROOM_AUTO_REQUEST - ? !hasHostJoined || isInWaitingRoom || username?.trim() === '' - : isInWaitingRoom || username?.trim() === ''; + ? !hasHostJoined || isInWaitingRoom + : isInWaitingRoom; return props?.render ? ( props.render(onPress, title, disabled) ) : ( diff --git a/template/src/components/precall/textInput.tsx b/template/src/components/precall/textInput.tsx index 22f7e2f2f..eea74a3d6 100644 --- a/template/src/components/precall/textInput.tsx +++ b/template/src/components/precall/textInput.tsx @@ -11,7 +11,7 @@ */ import React from 'react'; -import {TextStyle} from 'react-native'; +import {TextStyle, Text} from 'react-native'; import TextInput from '../../atoms/TextInput'; import {useString} from '../../utils/useString'; import {useRoomInfo} from '../room-info/useRoomInfo'; @@ -25,6 +25,7 @@ import { precallNameInputPlaceholderText, precallYouAreJoiningAsHeading, } from '../../language/default-labels/precallScreenLabels'; +import {usePreCall} from './usePreCall'; export interface PreCallTextInputProps { labelStyle?: TextStyle; @@ -39,30 +40,52 @@ const PreCallTextInput = (props?: PreCallTextInputProps) => { const username = useGetName(); const setUsername = useSetName(); const {isJoinDataFetched, isInWaitingRoom} = useRoomInfo(); + const {isNameIsEmpty, setIsNameIsEmpty} = usePreCall(); const {isDesktop = false, isOnPrecall = false} = props; return ( - setUsername(text ? text : '')} - onSubmitEditing={() => {}} - placeholder={isJoinDataFetched ? placeHolder : fetchingNamePlaceholder} - editable={!isInWaitingRoom && isJoinDataFetched} - /> + <> + { + setUsername(text ? text : ''); + if (text && text.trim() === '') { + setIsNameIsEmpty(true); + } else { + setIsNameIsEmpty(false); + } + }} + onSubmitEditing={() => {}} + placeholder={isJoinDataFetched ? placeHolder : fetchingNamePlaceholder} + editable={!isInWaitingRoom && isJoinDataFetched} + style={isNameIsEmpty ? {borderColor: $config.SEMANTIC_ERROR} : {}} + /> + {isNameIsEmpty && ( + + {'Name is required'} + + )} + ); }; diff --git a/template/src/components/precall/usePreCall.tsx b/template/src/components/precall/usePreCall.tsx index 6b468a167..e3ae6a8c1 100644 --- a/template/src/components/precall/usePreCall.tsx +++ b/template/src/components/precall/usePreCall.tsx @@ -29,6 +29,8 @@ export interface PreCallContextInterface { setSpeakerAvailable: React.Dispatch>; isPermissionRequested: boolean; setIsPermissionRequested: React.Dispatch>; + isNameIsEmpty: boolean; + setIsNameIsEmpty: React.Dispatch>; } const PreCallContext = createContext({ @@ -42,6 +44,8 @@ const PreCallContext = createContext({ setSpeakerAvailable: () => {}, isPermissionRequested: false, setIsPermissionRequested: () => {}, + isNameIsEmpty: false, + setIsNameIsEmpty: () => {}, }); interface PreCallProviderProps { @@ -54,6 +58,7 @@ const PreCallProvider = (props: PreCallProviderProps) => { const roomInfo = useRoomInfo(); const {deviceList} = useContext(DeviceContext); const setUsername = useSetName(); + const [isNameIsEmpty, setIsNameIsEmpty] = useState(false); const [isCameraAvailable, setCameraAvailable] = useState(false); const [isMicAvailable, setMicAvailable] = useState(false); const [isSpeakerAvailable, setSpeakerAvailable] = useState(false); @@ -69,6 +74,8 @@ const PreCallProvider = (props: PreCallProviderProps) => { setSpeakerAvailable, isPermissionRequested, setIsPermissionRequested, + isNameIsEmpty, + setIsNameIsEmpty, }; useEffect(() => { diff --git a/template/src/utils/SdkEvents.ts b/template/src/utils/SdkEvents.ts index 0bb6a963c..822f9eba0 100644 --- a/template/src/utils/SdkEvents.ts +++ b/template/src/utils/SdkEvents.ts @@ -51,6 +51,9 @@ export interface userEventsMapInterface { 'token-refreshed': () => void; 'rtc-user-removed': (uid: UidType, channel: string) => void; unauthorized: (errorMessage) => void; + 'waiting-room-approval-requested': () => void; + 'waiting-room-approval-granted': () => void; + 'waiting-room-approval-rejected': () => void; } const SDKEvents = createNanoEvents();