diff --git a/template/android/app/src/main/assets/fonts/icomoon.ttf b/template/android/app/src/main/assets/fonts/icomoon.ttf index b0e7f7118..ca419f25b 100644 Binary files a/template/android/app/src/main/assets/fonts/icomoon.ttf and b/template/android/app/src/main/assets/fonts/icomoon.ttf differ diff --git a/template/android/link-assets-manifest.json b/template/android/link-assets-manifest.json index e27bfbeaf..f1cc0c21d 100644 --- a/template/android/link-assets-manifest.json +++ b/template/android/link-assets-manifest.json @@ -2,12 +2,12 @@ "migIndex": 1, "data": [ { - "path": "src/assets/fonts/SourceSansPro-Regular.ttf", - "sha1": "48d6928e08ba5e2ca1e15d754c146580b1c8febd" + "path": "src/assets/fonts/icomoon.ttf", + "sha1": "1e3445ea248797ffdaf3f7ff01438e39964c82a4" }, { - "path": "src/assets/fonts/icomoon.ttf", - "sha1": "f08065b544237fb6aa60f7a4699a3ef1d7d1abf5" + "path": "src/assets/fonts/SourceSansPro-Regular.ttf", + "sha1": "48d6928e08ba5e2ca1e15d754c146580b1c8febd" } ] -} +} \ No newline at end of file diff --git a/template/ios/link-assets-manifest.json b/template/ios/link-assets-manifest.json index e27bfbeaf..f1cc0c21d 100644 --- a/template/ios/link-assets-manifest.json +++ b/template/ios/link-assets-manifest.json @@ -2,12 +2,12 @@ "migIndex": 1, "data": [ { - "path": "src/assets/fonts/SourceSansPro-Regular.ttf", - "sha1": "48d6928e08ba5e2ca1e15d754c146580b1c8febd" + "path": "src/assets/fonts/icomoon.ttf", + "sha1": "1e3445ea248797ffdaf3f7ff01438e39964c82a4" }, { - "path": "src/assets/fonts/icomoon.ttf", - "sha1": "f08065b544237fb6aa60f7a4699a3ef1d7d1abf5" + "path": "src/assets/fonts/SourceSansPro-Regular.ttf", + "sha1": "48d6928e08ba5e2ca1e15d754c146580b1c8febd" } ] -} +} \ No newline at end of file diff --git a/template/src/atoms/Dropdown.tsx b/template/src/atoms/Dropdown.tsx index 99a72c0cb..caefd594b 100644 --- a/template/src/atoms/Dropdown.tsx +++ b/template/src/atoms/Dropdown.tsx @@ -222,7 +222,7 @@ const PlatformWrapper = ({children, onPress}) => { const styles = StyleSheet.create({ dropdownOptionContainer: { - flex: 1, + // flex: 1, flexDirection: 'row', minHeight: 40, backgroundColor: $config.INPUT_FIELD_BACKGROUND_COLOR, diff --git a/template/src/language/default-labels/joinScreenLabels.ts b/template/src/language/default-labels/joinScreenLabels.ts index 2e9b9f7af..dd134a5de 100644 --- a/template/src/language/default-labels/joinScreenLabels.ts +++ b/template/src/language/default-labels/joinScreenLabels.ts @@ -23,9 +23,9 @@ export interface I18nJoinScreenLabelsInterface { export const JoinScreenLabels: I18nJoinScreenLabelsInterface = { [joinRoomHeading]: ({eventMode}) => { if (eventMode) { - return 'Join a Room'; - } else { return 'Join a Stream'; + } else { + return 'Join a Room'; } }, [joinRoomInputLabel]: ({eventMode}) => { diff --git a/template/src/language/default-labels/videoCallScreenLabels.ts b/template/src/language/default-labels/videoCallScreenLabels.ts index 0ee09cff9..5db0c29bf 100644 --- a/template/src/language/default-labels/videoCallScreenLabels.ts +++ b/template/src/language/default-labels/videoCallScreenLabels.ts @@ -213,6 +213,10 @@ export const sttDownloadTranscriptBtnText = `${stt}DownloadTranscriptBtnText` as const; export const sttLanguageChangeInProgress = `${stt}LanguageChangeInProgress` as const; +export const sttSpokenLanguageChangeInProgress = + `${stt}SpokenLanguageChangeInProgress` as const; +export const sttTranslationLanguageChangeInProgress = + `${stt}TranslationLanguageChangeInProgress` as const; export const sttStartError = `${stt}StartError` as const; export const sttUpdateError = `${stt}UpdateError` as const; @@ -655,6 +659,8 @@ export interface I18nVideoCallScreenLabelsInterface { [sttDownloadBtnText]?: I18nBaseType; [sttDownloadTranscriptBtnText]?: I18nBaseType; [sttLanguageChangeInProgress]?: I18nBaseType; + [sttSpokenLanguageChangeInProgress]?: I18nConditionalType; + [sttTranslationLanguageChangeInProgress]?: I18nConditionalType; [sttStartError]?: I18nBaseType; [sttUpdateError]?: I18nBaseType; @@ -1063,6 +1069,12 @@ export const VideoCallScreenLabels: I18nVideoCallScreenLabelsInterface = { isUpdate ? 'Updating Translation Language' : 'Setting Translation Language', [sttChangeTranslationLanguageText]: 'Change Translation Language', [sttLanguageChangeInProgress]: 'Language Change is in progress...', + [sttSpokenLanguageChangeInProgress]: (isUpdate: boolean) => + isUpdate ? 'Updating Spoken Language...' : 'Setting Spoken Language...', + [sttTranslationLanguageChangeInProgress]: (isUpdate: boolean) => + isUpdate + ? 'Updating Translation Language...' + : 'Setting Translation Language...', [sttStartError]: 'Failed to start captions', [sttUpdateError]: 'Failed to update caption settings', diff --git a/template/src/subComponents/caption/Caption.tsx b/template/src/subComponents/caption/Caption.tsx index 8b0747d74..2642f4a0e 100644 --- a/template/src/subComponents/caption/Caption.tsx +++ b/template/src/subComponents/caption/Caption.tsx @@ -12,6 +12,8 @@ import {useLocalUid} from '../../../agora-rn-uikit'; import { sttSettingSpokenLanguageText, sttSettingTranslationLanguageText, + sttSpokenLanguageChangeInProgress, + sttTranslationLanguageChangeInProgress, } from '../../language/default-labels/videoCallScreenLabels'; export type WebStreamMessageArgs = [number, Uint8Array]; @@ -45,12 +47,19 @@ const Caption: React.FC = ({ getBotOwnerUid, isSTTActive, remoteSpokenLanguages, + langChangeType, } = useCaption(); const currentUserUid = useLocalUid(); const ssLabel = useString(sttSettingSpokenLanguageText)(); const stLabel = useString(sttSettingTranslationLanguageText)( isSTTActive, ); + const spokenLanguageChangeInProgress = useString( + sttSpokenLanguageChangeInProgress, + ); + const translationLanguageChangeInProgress = useString( + sttTranslationLanguageChangeInProgress, + ); const {streamMessageCallback} = useStreamMessageUtils(); const {defaultContent} = useContent(); @@ -80,7 +89,11 @@ const Caption: React.FC = ({ if (isLangChangeInProgress) { return ( { // const isFirstTimePopupOpen = React.useRef(false); // const {start, restart, isAuthorizedSTTUser} = useSTTAPI(); // const isDisabled = !isAuthorizedSTTUser(); + const isDisabled = !sttDepsReady || props?.disabled; const captionLabel = useString(toolbarItemCaptionText); const label = captionLabel(isCaptionON); const onPress = () => { @@ -64,13 +65,15 @@ const CaptionIcon = (props: CaptionIconProps) => { }; const iconButtonProps: IconButtonProps = { onPress: onPressCustom || onPress, - disabled: !sttDepsReady, + disabled: isDisabled, iconProps: { name: isCaptionON ? 'captions-off' : 'captions', iconBackgroundColor: isCaptionON ? $config.PRIMARY_ACTION_BRAND_COLOR : '', - tintColor: isCaptionON + tintColor: isDisabled + ? $config.SEMANTIC_NEUTRAL + : isCaptionON ? $config.PRIMARY_ACTION_TEXT_COLOR : $config.SECONDARY_ACTION_COLOR, }, @@ -80,7 +83,7 @@ const CaptionIcon = (props: CaptionIconProps) => { ? labelCustom || label?.replace(' ', '\n') : labelCustom || label : '', - textColor: $config.FONT_COLOR, + textColor: isDisabled ? $config.SEMANTIC_NEUTRAL : $config.FONT_COLOR, numberOfLines: 2, }, }; diff --git a/template/src/subComponents/caption/LanguageSelectorPopup.tsx b/template/src/subComponents/caption/LanguageSelectorPopup.tsx index 5caab0e52..6e79581ce 100644 --- a/template/src/subComponents/caption/LanguageSelectorPopup.tsx +++ b/template/src/subComponents/caption/LanguageSelectorPopup.tsx @@ -16,6 +16,8 @@ import { sttChangeLanguagePopupHeading, sttChangeLanguagePopupPrimaryBtnText, sttLanguageChangeInProgress, + sttSpokenLanguageChangeInProgress, + sttTranslationLanguageChangeInProgress, } from '../../language/default-labels/videoCallScreenLabels'; import {cancelText} from '../../language/default-labels/commonLabels'; @@ -30,9 +32,15 @@ const LanguageSelectorPopup = (props: LanguageSelectorPopup) => { const heading = useString(sttChangeLanguagePopupHeading); const cancelBtnLabel = useString(cancelText)(); const ConfirmBtnLabel = useString(sttChangeLanguagePopupPrimaryBtnText)(); + const spokenLanguageChangeInProgress = useString( + sttSpokenLanguageChangeInProgress, + ); + const translationLanguageChangeInProgress = useString( + sttTranslationLanguageChangeInProgress, + ); const languageChangeInProgress = useString(sttLanguageChangeInProgress)(); - const {globalSttState, isLangChangeInProgress} = useCaption(); + const {globalSttState, isLangChangeInProgress, langChangeType} = useCaption(); const [draftSpokenLanguage, setDraftSpokenLanguage] = useState( globalSttState?.globalSpokenLanguage || 'en-US', @@ -64,7 +72,15 @@ const LanguageSelectorPopup = (props: LanguageSelectorPopup) => { {isLangChangeInProgress ? ( { const { meetingTranscript, isLangChangeInProgress, + langChangeType, isSTTListenerAdded, setIsSTTListenerAdded, getBotOwnerUid, @@ -69,6 +72,12 @@ const Transcript = (props: TranscriptProps) => { const settingTranslationLanguageLabel = useString( sttSettingTranslationLanguageText, )(isSTTActive); + const spokenLanguageChangeInProgress = useString( + sttSpokenLanguageChangeInProgress, + ); + const translationLanguageChangeInProgress = useString( + sttTranslationLanguageChangeInProgress, + ); const searchText = useString(sttTranscriptPanelSearchText)(); const noresults = useString(sttTranscriptPanelNoSearchResultsFoundText)(); const viewlatest = useString(sttTranscriptPanelViewLatestText)(); @@ -339,7 +348,11 @@ const Transcript = (props: TranscriptProps) => { {isLangChangeInProgress ? ( { const {isSTTActive, isSTTError, sttDepsReady, confirmSpokenLanguageChange} = useCaption(); // const isDisabled = !isAuthorizedTranscriptUser(); + const isDisabled = !sttDepsReady || props?.disabled; const [isLanguagePopupOpen, setLanguagePopup] = React.useState(false); // const isFirstTimePopupOpen = React.useRef(false); @@ -53,23 +54,25 @@ const TranscriptIcon = (props: TranscriptIconProps) => { const label = useString(toolbarItemTranscriptText); const iconButtonProps: IconButtonProps = { onPress: onPressCustom || onPress, + disabled: isDisabled, iconProps: { name: 'transcript', iconBackgroundColor: isTranscriptON ? $config.PRIMARY_ACTION_BRAND_COLOR : '', - tintColor: isTranscriptON + tintColor: isDisabled + ? $config.SEMANTIC_NEUTRAL + : isTranscriptON ? $config.PRIMARY_ACTION_TEXT_COLOR : $config.SECONDARY_ACTION_COLOR, }, - disabled: !sttDepsReady, btnTextProps: { text: showLabel ? isOnActionSheet ? labelCustom || label(isTranscriptON)?.replace(' ', '\n') : labelCustom || label(isTranscriptON) : '', - textColor: $config.FONT_COLOR, + textColor: isDisabled ? $config.SEMANTIC_NEUTRAL : $config.FONT_COLOR, numberOfLines: 2, }, }; diff --git a/template/src/subComponents/caption/useCaption.tsx b/template/src/subComponents/caption/useCaption.tsx index a4177094b..b466b2d6f 100644 --- a/template/src/subComponents/caption/useCaption.tsx +++ b/template/src/subComponents/caption/useCaption.tsx @@ -132,6 +132,8 @@ export const CaptionContext = React.createContext<{ isLangChangeInProgress: boolean; setIsLangChangeInProgress: React.Dispatch>; + // holds the type of language change in progress ('spoken' | 'translation' | null) + langChangeType: 'spoken' | 'translation' | null; // holds live captions captionObj: CaptionObj; setCaptionObj: React.Dispatch>; @@ -182,6 +184,7 @@ export const CaptionContext = React.createContext<{ setMeetingTranscript: () => {}, isLangChangeInProgress: false, setIsLangChangeInProgress: () => {}, + langChangeType: null, captionObj: {}, setCaptionObj: () => {}, isSTTListenerAdded: false, @@ -234,6 +237,9 @@ const CaptionProvider: React.FC = ({ const [isSTTError, setIsSTTError] = React.useState(false); const [isLangChangeInProgress, setIsLangChangeInProgress] = React.useState(false); + const [langChangeType, setLangChangeType] = React.useState< + 'spoken' | 'translation' | null + >(null); const [captionObj, setCaptionObj] = React.useState({}); const [meetingTranscript, setMeetingTranscript] = React.useState< @@ -446,6 +452,7 @@ const CaptionProvider: React.FC = ({ ): Promise => { try { setIsLangChangeInProgress(true); + setLangChangeType('spoken'); const result = await start(localBotUidRef.current, newConfig); console.log('[STT] start result: ', result); if (result.success || result.error?.code === 610) { @@ -476,9 +483,11 @@ const CaptionProvider: React.FC = ({ }); } setIsLangChangeInProgress(false); + setLangChangeType(null); return result; } catch (error: any) { setIsLangChangeInProgress(false); + setLangChangeType(null); setIsSTTError(true); logger.error(LogSource.NetworkRest, 'stt', 'STT start error', error); // Show error toast: text1 = translated label, text2 = exception error @@ -504,7 +513,16 @@ const CaptionProvider: React.FC = ({ targetChange?: TargetChange, ): Promise => { try { - isLocal && setIsLangChangeInProgress(true); + if (isLocal) { + setIsLangChangeInProgress(true); + // If targetChange exists and prev/next differ, it's a translation change + // Otherwise it's a spoken language change + setLangChangeType( + targetChange && targetChange.prev !== targetChange.next + ? 'translation' + : 'spoken', + ); + } const result = await update(localBotUidRef.current, newConfig); if (result.success) { setIsSTTError(false); @@ -548,9 +566,11 @@ const CaptionProvider: React.FC = ({ }); } setIsLangChangeInProgress(false); + setLangChangeType(null); return result; } catch (error: any) { setIsLangChangeInProgress(false); + setLangChangeType(null); setIsSTTError(true); logger.error(LogSource.NetworkRest, 'stt', 'STT update error', error); // Show error toast: text1 = translated label, text2 = exception error @@ -1035,6 +1055,7 @@ const CaptionProvider: React.FC = ({ setMeetingTranscript, isLangChangeInProgress, setIsLangChangeInProgress, + langChangeType, captionObj, setCaptionObj, isSTTListenerAdded,