agora-appbuilder-core 4.1.10-beta.1 → 4.1.11-beta.2
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 +2 -2
- package/template/agora-rn-uikit/src/Utils/isBotUser.ts +1 -1
- package/template/android/app/build.gradle +0 -7
- package/template/bridge/rtc/webNg/RtcEngine.ts +2 -2
- package/template/bridge/rtm/web/Types.ts +0 -183
- package/template/bridge/rtm/web/index.ts +488 -450
- package/template/customization-api/typeDefinition.ts +0 -1
- package/template/defaultConfig.js +3 -4
- package/template/global.d.ts +0 -1
- package/template/ios/Podfile +0 -41
- package/template/package.json +5 -5
- package/template/src/AppRoutes.tsx +3 -3
- package/template/src/ai-agent/components/ControlButtons.tsx +1 -1
- package/template/src/assets/font-styles.css +1 -33
- package/template/src/assets/fonts/icomoon.ttf +0 -0
- package/template/src/assets/selection.json +1 -1
- package/template/src/atoms/ActionMenu.tsx +93 -13
- package/template/src/atoms/CustomIcon.tsx +1 -8
- package/template/src/atoms/DropDownMulti.tsx +80 -29
- package/template/src/atoms/Dropdown.tsx +0 -5
- package/template/src/atoms/Input.tsx +2 -1
- package/template/src/atoms/TertiaryButton.tsx +1 -1
- package/template/src/atoms/UserAvatar.tsx +1 -1
- package/template/src/components/ChatContext.ts +3 -5
- package/template/src/components/Controls.tsx +167 -208
- package/template/src/components/DeviceConfigure.tsx +1 -1
- package/template/src/components/EventsConfigure.tsx +168 -118
- package/template/src/components/Navbar.tsx +11 -14
- package/template/src/components/RTMConfigure.tsx +819 -32
- package/template/src/components/beauty-effect/useBeautyEffects.tsx +13 -50
- package/template/src/components/chat/chatConfigure.tsx +1 -7
- package/template/src/components/chat-messages/useChatMessages.tsx +11 -43
- package/template/src/components/controls/useControlPermissionMatrix.tsx +4 -32
- package/template/src/components/participants/AllHostParticipants.tsx +2 -10
- package/template/src/components/participants/Participant.tsx +1 -7
- package/template/src/components/participants/UserActionMenuOptions.tsx +2 -12
- package/template/src/components/precall/joinCallBtn.native.tsx +7 -2
- package/template/src/components/precall/joinCallBtn.tsx +7 -2
- package/template/src/components/precall/joinWaitingRoomBtn.native.tsx +16 -15
- package/template/src/components/precall/joinWaitingRoomBtn.tsx +31 -17
- package/template/src/components/precall/textInput.tsx +45 -22
- package/template/src/components/precall/usePreCall.tsx +7 -0
- package/template/src/components/recordings/RecordingsDateTable.tsx +2 -3
- package/template/src/components/room-info/useRoomInfo.tsx +5 -0
- package/template/src/components/useUserPreference.tsx +12 -39
- package/template/src/components/virtual-background/useVB.tsx +0 -18
- package/template/src/components/whiteboard/WhiteboardConfigure.tsx +0 -27
- package/template/src/language/default-labels/videoCallScreenLabels.ts +27 -11
- package/template/src/logger/AppBuilderLogger.tsx +3 -11
- package/template/src/pages/VideoCall.tsx +518 -171
- package/template/src/pages/video-call/ActionSheetContent.tsx +77 -77
- package/template/src/pages/video-call/SidePanelHeader.tsx +81 -53
- package/template/src/pages/video-call/VideoCallScreen.tsx +0 -18
- package/template/src/pages/video-call/VideoCallScreenWrapper.tsx +1 -0
- package/template/src/rtm/RTMEngine.ts +37 -262
- package/template/src/rtm/utils.ts +1 -68
- package/template/src/rtm-events/constants.ts +7 -40
- package/template/src/rtm-events-api/Events.ts +39 -158
- package/template/src/subComponents/ChatBubble.tsx +3 -3
- package/template/src/subComponents/ChatContainer.tsx +9 -19
- package/template/src/subComponents/LocalAudioMute.tsx +2 -2
- package/template/src/subComponents/LocalVideoMute.tsx +2 -2
- package/template/src/subComponents/SidePanelEnum.tsx +0 -1
- package/template/src/subComponents/caption/Caption.tsx +48 -7
- package/template/src/subComponents/caption/CaptionContainer.tsx +324 -51
- package/template/src/subComponents/caption/CaptionIcon.tsx +35 -34
- package/template/src/subComponents/caption/CaptionText.tsx +103 -2
- package/template/src/subComponents/caption/LanguageSelectorPopup.tsx +179 -69
- package/template/src/subComponents/caption/Transcript.tsx +46 -11
- package/template/src/subComponents/caption/TranscriptIcon.tsx +27 -35
- package/template/src/subComponents/caption/TranscriptText.tsx +78 -3
- package/template/src/subComponents/caption/proto/ptoto.js +38 -4
- package/template/src/subComponents/caption/proto/test.proto +34 -19
- package/template/src/subComponents/caption/useCaption.tsx +754 -11
- package/template/src/subComponents/caption/useSTTAPI.tsx +118 -205
- package/template/src/subComponents/caption/useStreamMessageUtils.native.ts +152 -33
- package/template/src/subComponents/caption/useStreamMessageUtils.ts +165 -34
- package/template/src/subComponents/caption/utils.ts +171 -3
- package/template/src/subComponents/chat/ChatSendButton.tsx +0 -1
- package/template/src/subComponents/screenshare/ScreenshareButton.tsx +0 -16
- package/template/src/subComponents/screenshare/ScreenshareConfigure.native.tsx +1 -1
- package/template/src/subComponents/waiting-rooms/WaitingRoomControls.tsx +4 -7
- package/template/src/utils/SdkEvents.ts +3 -0
- package/template/src/utils/useEndCall.ts +4 -4
- package/template/src/utils/useMuteToggleLocal.ts +10 -14
- package/template/src/utils/useSpeechToText.ts +31 -20
- package/template/bridge/rtm/web/index-legacy.ts +0 -540
- package/template/src/components/RTMConfigure-legacy.tsx +0 -848
- package/template/src/components/UserGlobalPreferenceProvider.tsx +0 -227
- package/template/src/components/breakout-room/BreakoutRoomPanel.tsx +0 -58
- package/template/src/components/breakout-room/context/BreakoutRoomContext.tsx +0 -2508
- package/template/src/components/breakout-room/events/BreakoutRoomEventsConfigure.tsx +0 -272
- package/template/src/components/breakout-room/events/constants.ts +0 -17
- package/template/src/components/breakout-room/hoc/BreakoutRoomNameRenderer.tsx +0 -68
- package/template/src/components/breakout-room/hooks/useBreakoutRoomExit.ts +0 -49
- package/template/src/components/breakout-room/state/reducer.ts +0 -522
- package/template/src/components/breakout-room/state/types.ts +0 -54
- package/template/src/components/breakout-room/ui/BreakoutMeetingTitle.tsx +0 -60
- package/template/src/components/breakout-room/ui/BreakoutRoomActionMenu.tsx +0 -136
- package/template/src/components/breakout-room/ui/BreakoutRoomAnnouncementModal.tsx +0 -135
- package/template/src/components/breakout-room/ui/BreakoutRoomGroupSettings.tsx +0 -588
- package/template/src/components/breakout-room/ui/BreakoutRoomMainRoomUsers.tsx +0 -142
- package/template/src/components/breakout-room/ui/BreakoutRoomMemberActionMenu.tsx +0 -122
- package/template/src/components/breakout-room/ui/BreakoutRoomParticipants.tsx +0 -124
- package/template/src/components/breakout-room/ui/BreakoutRoomRaiseHand.tsx +0 -65
- package/template/src/components/breakout-room/ui/BreakoutRoomRenameModal.tsx +0 -227
- package/template/src/components/breakout-room/ui/BreakoutRoomSettings.tsx +0 -140
- package/template/src/components/breakout-room/ui/BreakoutRoomTransition.tsx +0 -52
- package/template/src/components/breakout-room/ui/BreakoutRoomView.tsx +0 -193
- package/template/src/components/breakout-room/ui/ExitBreakoutRoomIconButton.tsx +0 -79
- package/template/src/components/breakout-room/ui/ParticipantManualAssignmentModal.tsx +0 -638
- package/template/src/components/breakout-room/ui/SelectParticipantAssignmentStrategy.tsx +0 -57
- package/template/src/components/common/Dividers.tsx +0 -53
- package/template/src/components/controls/toolbar-items/ExitBreakoutRoomToolbarItem.tsx +0 -13
- package/template/src/components/raise-hand/RaiseHandButton.tsx +0 -50
- package/template/src/components/raise-hand/RaiseHandProvider.tsx +0 -308
- package/template/src/components/raise-hand/index.ts +0 -14
- package/template/src/components/room-info/useCurrentRoomInfo.tsx +0 -42
- package/template/src/components/room-info/useSetBreakoutRoomInfo.tsx +0 -64
- package/template/src/pages/video-call/BreakoutVideoCall.tsx +0 -213
- package/template/src/pages/video-call/VideoCallContent.tsx +0 -211
- package/template/src/pages/video-call/VideoCallStateWrapper.tsx +0 -495
- package/template/src/rtm/RTMConfigureBreakoutRoomProvider.tsx +0 -882
- package/template/src/rtm/RTMConfigureMainRoomProvider.tsx +0 -757
- package/template/src/rtm/RTMCoreProvider.tsx +0 -419
- package/template/src/rtm/RTMGlobalStateProvider.tsx +0 -706
- package/template/src/rtm/RTMStatusBanner.tsx +0 -99
- package/template/src/rtm/constants.ts +0 -12
- package/template/src/rtm/hooks/useMainRoomUserDisplayName.ts +0 -45
- package/template/src/rtm/rtm-presence-utils.ts +0 -344
- package/template/src/subComponents/chat/ChatAnnouncementView.tsx +0 -65
- package/template/src/utils/useDebouncedCallback.tsx +0 -20
|
@@ -1,16 +1,48 @@
|
|
|
1
1
|
import {createHook} from 'customization-implementation';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
import {LanguageType} from './utils';
|
|
2
|
+
import React, {useContext} from 'react';
|
|
3
|
+
import {LanguageType, getLanguageLabel, hasConfigChanged} from './utils';
|
|
4
|
+
import useSTTAPI, {STTAPIResponse} from './useSTTAPI';
|
|
5
|
+
import {useLocalUid} from '../../../agora-rn-uikit';
|
|
6
|
+
import {logger, LogSource} from '../../logger/AppBuilderLogger';
|
|
7
|
+
import events, {PersistanceLevel} from '../../rtm-events-api';
|
|
8
|
+
import {EventNames} from '../../rtm-events';
|
|
9
|
+
import useGetName from '../../utils/useGetName';
|
|
10
|
+
import Toast from '../../../react-native-toast-message';
|
|
11
|
+
import {useString} from '../../utils/useString';
|
|
12
|
+
import {
|
|
13
|
+
sttStartError,
|
|
14
|
+
sttUpdateError,
|
|
15
|
+
} from '../../language/default-labels/videoCallScreenLabels';
|
|
16
|
+
import chatContext from '../../components/ChatContext';
|
|
17
|
+
|
|
18
|
+
type TranslationItem = {
|
|
19
|
+
lang: string;
|
|
20
|
+
text: string;
|
|
21
|
+
isFinal: boolean;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type LanguageTranslationConfig = {
|
|
25
|
+
source: LanguageType[]; // 'en-US'
|
|
26
|
+
targets: LanguageType[]; // ['zh-CN', 'ja-JP']
|
|
27
|
+
autoPopulate?: boolean; // e.g. if auto-populated from others
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type CaptionViewMode = 'original-and-translated' | 'translated';
|
|
4
31
|
|
|
5
32
|
export type TranscriptItem = {
|
|
6
33
|
uid: string;
|
|
7
34
|
time: number;
|
|
8
35
|
text: string;
|
|
36
|
+
translations?: TranslationItem[];
|
|
37
|
+
// Stores which translation language was active when this transcript was created
|
|
38
|
+
// This preserves historical context when users switch translation languages mid-meeting
|
|
39
|
+
selectedTranslationLanguage?: string;
|
|
9
40
|
};
|
|
10
41
|
|
|
11
42
|
type CaptionObj = {
|
|
12
43
|
[key: string]: {
|
|
13
44
|
text: string;
|
|
45
|
+
translations: TranslationItem[];
|
|
14
46
|
lastUpdated: number;
|
|
15
47
|
};
|
|
16
48
|
};
|
|
@@ -28,9 +60,20 @@ export const CaptionContext = React.createContext<{
|
|
|
28
60
|
isSTTActive: boolean;
|
|
29
61
|
setIsSTTActive: React.Dispatch<React.SetStateAction<boolean>>;
|
|
30
62
|
|
|
31
|
-
// holds the language selection for stt
|
|
32
|
-
language: LanguageType[];
|
|
33
|
-
setLanguage: React.Dispatch<React.SetStateAction<LanguageType[]>>;
|
|
63
|
+
// holds the language selection for stt (deprecated - use sttForm instead)
|
|
64
|
+
// language: LanguageType[];
|
|
65
|
+
// setLanguage: React.Dispatch<React.SetStateAction<LanguageType[]>>;
|
|
66
|
+
|
|
67
|
+
translationConfig: LanguageTranslationConfig;
|
|
68
|
+
setTranslationConfig: React.Dispatch<
|
|
69
|
+
React.SetStateAction<LanguageTranslationConfig>
|
|
70
|
+
>;
|
|
71
|
+
|
|
72
|
+
captionViewMode: CaptionViewMode;
|
|
73
|
+
setCaptionViewMode: React.Dispatch<React.SetStateAction<CaptionViewMode>>;
|
|
74
|
+
|
|
75
|
+
transcriptViewMode: CaptionViewMode;
|
|
76
|
+
setTranscriptViewMode: React.Dispatch<React.SetStateAction<CaptionViewMode>>;
|
|
34
77
|
|
|
35
78
|
// holds meeting transcript
|
|
36
79
|
meetingTranscript: TranscriptItem[];
|
|
@@ -40,6 +83,12 @@ export const CaptionContext = React.createContext<{
|
|
|
40
83
|
isLangChangeInProgress: boolean;
|
|
41
84
|
setIsLangChangeInProgress: React.Dispatch<React.SetStateAction<boolean>>;
|
|
42
85
|
|
|
86
|
+
// holds status of translation language change process
|
|
87
|
+
isTranslationChangeInProgress: boolean;
|
|
88
|
+
setIsTranslationChangeInProgress: React.Dispatch<
|
|
89
|
+
React.SetStateAction<boolean>
|
|
90
|
+
>;
|
|
91
|
+
|
|
43
92
|
// holds live captions
|
|
44
93
|
captionObj: CaptionObj;
|
|
45
94
|
setCaptionObj: React.Dispatch<React.SetStateAction<CaptionObj>>;
|
|
@@ -50,6 +99,34 @@ export const CaptionContext = React.createContext<{
|
|
|
50
99
|
|
|
51
100
|
activeSpeakerRef: React.MutableRefObject<string>;
|
|
52
101
|
prevSpeakerRef: React.MutableRefObject<string>;
|
|
102
|
+
|
|
103
|
+
selectedTranslationLanguage: string;
|
|
104
|
+
setSelectedTranslationLanguage: React.Dispatch<React.SetStateAction<string>>;
|
|
105
|
+
// Ref for translation language - prevents stale closures in callbacks
|
|
106
|
+
selectedTranslationLanguageRef: React.MutableRefObject<string>;
|
|
107
|
+
// Ref for translation config - prevents stale closures in callbacks
|
|
108
|
+
translationConfigRef: React.MutableRefObject<LanguageTranslationConfig>;
|
|
109
|
+
|
|
110
|
+
// Stores spoken languages of all remote users (userUid -> spoken language)
|
|
111
|
+
// Used to auto-populate target languages for new users
|
|
112
|
+
remoteSpokenLanguages: Record<string, LanguageType>;
|
|
113
|
+
setRemoteSpokenLanguages: React.Dispatch<
|
|
114
|
+
React.SetStateAction<Record<string, LanguageType>>
|
|
115
|
+
>;
|
|
116
|
+
|
|
117
|
+
handleTranslateConfigChange: (
|
|
118
|
+
inputTranslationConfig: LanguageTranslationConfig,
|
|
119
|
+
) => Promise<void>;
|
|
120
|
+
startSTTBotSession: (
|
|
121
|
+
newConfig: LanguageTranslationConfig,
|
|
122
|
+
) => Promise<STTAPIResponse>;
|
|
123
|
+
updateSTTBotSession: (
|
|
124
|
+
newConfig: LanguageTranslationConfig,
|
|
125
|
+
) => Promise<STTAPIResponse>;
|
|
126
|
+
stopSTTBotSession: () => Promise<void>;
|
|
127
|
+
|
|
128
|
+
// Helper function to get user UID from bot UID
|
|
129
|
+
getBotOwnerUid: (botUid: string | number) => string | number;
|
|
53
130
|
}>({
|
|
54
131
|
isCaptionON: false,
|
|
55
132
|
setIsCaptionON: () => {},
|
|
@@ -57,22 +134,44 @@ export const CaptionContext = React.createContext<{
|
|
|
57
134
|
setIsSTTError: () => {},
|
|
58
135
|
isSTTActive: false,
|
|
59
136
|
setIsSTTActive: () => {},
|
|
60
|
-
language: ['en-US'],
|
|
61
|
-
setLanguage: () => {},
|
|
137
|
+
// language: ['en-US'],
|
|
138
|
+
// setLanguage: () => {},
|
|
139
|
+
translationConfig: {
|
|
140
|
+
source: [],
|
|
141
|
+
targets: [],
|
|
142
|
+
},
|
|
143
|
+
setTranslationConfig: () => {},
|
|
144
|
+
captionViewMode: 'translated',
|
|
145
|
+
setCaptionViewMode: () => {},
|
|
146
|
+
transcriptViewMode: 'translated',
|
|
147
|
+
setTranscriptViewMode: () => {},
|
|
62
148
|
meetingTranscript: [],
|
|
63
149
|
setMeetingTranscript: () => {},
|
|
64
150
|
isLangChangeInProgress: false,
|
|
65
151
|
setIsLangChangeInProgress: () => {},
|
|
152
|
+
isTranslationChangeInProgress: false,
|
|
153
|
+
setIsTranslationChangeInProgress: () => {},
|
|
66
154
|
captionObj: {},
|
|
67
155
|
setCaptionObj: () => {},
|
|
68
156
|
isSTTListenerAdded: false,
|
|
69
157
|
setIsSTTListenerAdded: () => {},
|
|
70
158
|
activeSpeakerRef: {current: ''},
|
|
71
159
|
prevSpeakerRef: {current: ''},
|
|
160
|
+
selectedTranslationLanguage: '',
|
|
161
|
+
setSelectedTranslationLanguage: () => {},
|
|
162
|
+
selectedTranslationLanguageRef: {current: ''},
|
|
163
|
+
translationConfigRef: {current: {source: [], targets: []}},
|
|
164
|
+
remoteSpokenLanguages: {},
|
|
165
|
+
setRemoteSpokenLanguages: () => {},
|
|
166
|
+
handleTranslateConfigChange: async () => {},
|
|
167
|
+
startSTTBotSession: async () => ({success: false}),
|
|
168
|
+
updateSTTBotSession: async () => ({success: false}),
|
|
169
|
+
stopSTTBotSession: async () => {},
|
|
170
|
+
getBotOwnerUid: (botUid: string | number) => botUid,
|
|
72
171
|
});
|
|
73
172
|
|
|
74
173
|
interface CaptionProviderProps {
|
|
75
|
-
callActive
|
|
174
|
+
callActive: boolean;
|
|
76
175
|
children: React.ReactNode;
|
|
77
176
|
}
|
|
78
177
|
|
|
@@ -83,21 +182,648 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
83
182
|
const [isSTTError, setIsSTTError] = React.useState<boolean>(false);
|
|
84
183
|
const [isCaptionON, setIsCaptionON] = React.useState<boolean>(false);
|
|
85
184
|
const [isSTTActive, setIsSTTActive] = React.useState<boolean>(false);
|
|
86
|
-
const [language, setLanguage] = React.useState<[LanguageType]>(['']);
|
|
185
|
+
// const [language, setLanguage] = React.useState<[LanguageType]>(['']);
|
|
186
|
+
|
|
187
|
+
// STT Form state - contains agentId, source, and target languages
|
|
188
|
+
const [translationConfig, setTranslationConfig] =
|
|
189
|
+
React.useState<LanguageTranslationConfig>({
|
|
190
|
+
source: [],
|
|
191
|
+
targets: [],
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
const [captionViewMode, setCaptionViewMode] =
|
|
195
|
+
React.useState<CaptionViewMode>('translated');
|
|
196
|
+
|
|
197
|
+
const [transcriptViewMode, setTranscriptViewMode] =
|
|
198
|
+
React.useState<CaptionViewMode>('translated');
|
|
199
|
+
|
|
87
200
|
const [isLangChangeInProgress, setIsLangChangeInProgress] =
|
|
88
201
|
React.useState<boolean>(false);
|
|
202
|
+
const [isTranslationChangeInProgress, setIsTranslationChangeInProgress] =
|
|
203
|
+
React.useState<boolean>(false);
|
|
89
204
|
const [meetingTranscript, setMeetingTranscript] = React.useState<
|
|
90
205
|
TranscriptItem[]
|
|
91
206
|
>([]);
|
|
92
207
|
const [captionObj, setCaptionObj] = React.useState<CaptionObj>({});
|
|
208
|
+
console.log('[STT_PER_USER_BOT] captionObj: ', captionObj);
|
|
93
209
|
const [isSTTListenerAdded, setIsSTTListenerAdded] =
|
|
94
210
|
React.useState<boolean>(false);
|
|
95
211
|
const [activeSpeakerUID, setActiveSpeakerUID] = React.useState<string>('');
|
|
96
212
|
const [prevActiveSpeakerUID, setPrevActiveSpeakerUID] =
|
|
97
213
|
React.useState<string>('');
|
|
214
|
+
const [selectedTranslationLanguage, setSelectedTranslationLanguage] =
|
|
215
|
+
React.useState<string>('');
|
|
216
|
+
const [remoteSpokenLanguages, setRemoteSpokenLanguages] = React.useState<
|
|
217
|
+
Record<string, LanguageType>
|
|
218
|
+
>({});
|
|
98
219
|
|
|
99
220
|
const activeSpeakerRef = React.useRef('');
|
|
100
221
|
const prevSpeakerRef = React.useRef('');
|
|
222
|
+
const selectedTranslationLanguageRef = React.useRef('');
|
|
223
|
+
const translationConfigRef = React.useRef<LanguageTranslationConfig>({
|
|
224
|
+
source: [],
|
|
225
|
+
targets: [],
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// Sync ref with state for selectedTranslationLanguage
|
|
229
|
+
React.useEffect(() => {
|
|
230
|
+
selectedTranslationLanguageRef.current = selectedTranslationLanguage;
|
|
231
|
+
}, [selectedTranslationLanguage]);
|
|
232
|
+
|
|
233
|
+
// Sync ref with state for translationConfig
|
|
234
|
+
React.useEffect(() => {
|
|
235
|
+
translationConfigRef.current = translationConfig;
|
|
236
|
+
}, [translationConfig]);
|
|
237
|
+
|
|
238
|
+
// Import STT API methods
|
|
239
|
+
const {start, stop, update} = useSTTAPI();
|
|
240
|
+
|
|
241
|
+
const localUid = useLocalUid();
|
|
242
|
+
const username = useGetName();
|
|
243
|
+
const {hasUserJoinedRTM} = useContext(chatContext);
|
|
244
|
+
|
|
245
|
+
const [localBotUid, setLocalBotUid] = React.useState<number | null>(null);
|
|
246
|
+
|
|
247
|
+
// i18n labels for error toasts
|
|
248
|
+
const startErrorLabel = useString(sttStartError)();
|
|
249
|
+
const updateErrorLabel = useString(sttUpdateError)();
|
|
250
|
+
|
|
251
|
+
React.useEffect(() => {
|
|
252
|
+
if (!localUid || !username || !hasUserJoinedRTM) {
|
|
253
|
+
return;
|
|
254
|
+
} // wait for room info to be ready
|
|
255
|
+
const uid = generateBotUidForUser(localUid);
|
|
256
|
+
setLocalBotUid(uid);
|
|
257
|
+
}, [localUid, username, hasUserJoinedRTM]);
|
|
258
|
+
|
|
259
|
+
// Silent update function to update local user's STT config without showing progress bar
|
|
260
|
+
const silentUpdateSTT = React.useCallback(
|
|
261
|
+
async (newtargetLanguages: LanguageType[]) => {
|
|
262
|
+
try {
|
|
263
|
+
// Merge new target languages with existing ones and keep unique
|
|
264
|
+
const currentTargets = translationConfigRef.current?.targets || [];
|
|
265
|
+
const mergedTargets = Array.from(
|
|
266
|
+
new Set([...newtargetLanguages, ...currentTargets]),
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
const newConfig: LanguageTranslationConfig = {
|
|
270
|
+
source: translationConfigRef.current?.source || [],
|
|
271
|
+
targets: mergedTargets,
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
console.log(
|
|
275
|
+
'[STT_PER_USER_BOT] Silent updating with merged targets:',
|
|
276
|
+
'newRemoteLanguages:',
|
|
277
|
+
newtargetLanguages,
|
|
278
|
+
'existingTargets:',
|
|
279
|
+
currentTargets,
|
|
280
|
+
'mergedTargets:',
|
|
281
|
+
mergedTargets,
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
// Call update API without showing progress bar (don't set isLangChangeInProgress)
|
|
285
|
+
const result = await update(localBotUid, newConfig);
|
|
286
|
+
|
|
287
|
+
if (result.success) {
|
|
288
|
+
setTranslationConfig(newConfig);
|
|
289
|
+
setIsSTTError(false);
|
|
290
|
+
|
|
291
|
+
logger.log(
|
|
292
|
+
LogSource.NetworkRest,
|
|
293
|
+
'stt',
|
|
294
|
+
'Local user STT updated silently',
|
|
295
|
+
{newtargetLanguages, mergedTargets, botUid: localBotUid},
|
|
296
|
+
);
|
|
297
|
+
} else {
|
|
298
|
+
setIsSTTError(true);
|
|
299
|
+
logger.error(
|
|
300
|
+
LogSource.NetworkRest,
|
|
301
|
+
'stt',
|
|
302
|
+
'Failed to silently update local user STT',
|
|
303
|
+
result.error,
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
} catch (error) {
|
|
307
|
+
setIsSTTError(true);
|
|
308
|
+
logger.error(
|
|
309
|
+
LogSource.NetworkRest,
|
|
310
|
+
'stt',
|
|
311
|
+
'Error in silentUpdateSTT',
|
|
312
|
+
error,
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
[localBotUid],
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
React.useEffect(() => {
|
|
320
|
+
const remoteLangs = Array.from(
|
|
321
|
+
new Set(
|
|
322
|
+
Object.entries(remoteSpokenLanguages)
|
|
323
|
+
.filter(([uid, lang]) => uid !== String(localUid) && lang)
|
|
324
|
+
.map(([, lang]) => lang),
|
|
325
|
+
),
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
// If STT is active, check if received language differs from current target languages
|
|
329
|
+
if (isSTTActive && remoteLangs && remoteLangs.length > 0) {
|
|
330
|
+
const currentTargetLanguages =
|
|
331
|
+
translationConfigRef.current?.targets || [];
|
|
332
|
+
// Only update if any received language is not in current target languages
|
|
333
|
+
const hasTargetsChanged = remoteLangs.some(
|
|
334
|
+
lang => !currentTargetLanguages.includes(lang),
|
|
335
|
+
);
|
|
336
|
+
if (hasTargetsChanged) {
|
|
337
|
+
console.log(
|
|
338
|
+
'[STT_PER_USER_BOT] Spoken language change detected',
|
|
339
|
+
'currentTargets:',
|
|
340
|
+
currentTargetLanguages,
|
|
341
|
+
'receivedSpokenLanguages (unique):',
|
|
342
|
+
remoteLangs,
|
|
343
|
+
);
|
|
344
|
+
// Call silentUpdateSTT directly
|
|
345
|
+
silentUpdateSTT(remoteLangs);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}, [remoteSpokenLanguages]);
|
|
349
|
+
|
|
350
|
+
// Listen for spoken language updates from other users
|
|
351
|
+
React.useEffect(() => {
|
|
352
|
+
const handleSpokenLanguage = (data: any) => {
|
|
353
|
+
try {
|
|
354
|
+
const payload = JSON.parse(data.payload);
|
|
355
|
+
const {userUid, spokenLanguage, username} = payload;
|
|
356
|
+
|
|
357
|
+
console.log(
|
|
358
|
+
'[STT_PER_USER_BOT] Received spoken language from user:',
|
|
359
|
+
username,
|
|
360
|
+
'userUid:',
|
|
361
|
+
userUid,
|
|
362
|
+
'spokenLanguage:',
|
|
363
|
+
spokenLanguage,
|
|
364
|
+
);
|
|
365
|
+
|
|
366
|
+
// Update remoteSpokenLanguages with the user's spoken language
|
|
367
|
+
setRemoteSpokenLanguages(prev => ({
|
|
368
|
+
...prev,
|
|
369
|
+
[userUid]: spokenLanguage,
|
|
370
|
+
}));
|
|
371
|
+
} catch (error) {
|
|
372
|
+
logger.error(
|
|
373
|
+
LogSource.Internals,
|
|
374
|
+
'STT',
|
|
375
|
+
'Failed to parse STT_SPOKEN_LANGUAGE event',
|
|
376
|
+
error,
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
events.on(EventNames.STT_SPOKEN_LANGUAGE, handleSpokenLanguage);
|
|
382
|
+
|
|
383
|
+
// Cleanup listener on unmount
|
|
384
|
+
return () => {
|
|
385
|
+
events.off(EventNames.STT_SPOKEN_LANGUAGE, handleSpokenLanguage);
|
|
386
|
+
};
|
|
387
|
+
}, []);
|
|
388
|
+
|
|
389
|
+
// Listen for when remote users stop translation and clear their translations
|
|
390
|
+
React.useEffect(() => {
|
|
391
|
+
const handleUserStoppedTranslation = (data: any) => {
|
|
392
|
+
try {
|
|
393
|
+
const payload = JSON.parse(data.payload);
|
|
394
|
+
const {userUid, username} = payload;
|
|
395
|
+
|
|
396
|
+
console.log(
|
|
397
|
+
'[STT_PER_USER_BOT] User stopped translation:',
|
|
398
|
+
username,
|
|
399
|
+
'userUid:',
|
|
400
|
+
userUid,
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
// Clear translations for this user by setting captionObj translations to empty
|
|
404
|
+
setCaptionObj(prevState => {
|
|
405
|
+
if (prevState[userUid]) {
|
|
406
|
+
return {
|
|
407
|
+
...prevState,
|
|
408
|
+
[userUid]: {
|
|
409
|
+
...prevState[userUid],
|
|
410
|
+
translations: [], // Clear translations
|
|
411
|
+
},
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
return prevState;
|
|
415
|
+
});
|
|
416
|
+
} catch (error) {
|
|
417
|
+
logger.error(
|
|
418
|
+
LogSource.Internals,
|
|
419
|
+
'STT',
|
|
420
|
+
'Failed to parse USER_STOPPED_TRANSLATION event',
|
|
421
|
+
error,
|
|
422
|
+
);
|
|
423
|
+
}
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
events.on(
|
|
427
|
+
EventNames.USER_STOPPED_TRANSLATION,
|
|
428
|
+
handleUserStoppedTranslation,
|
|
429
|
+
);
|
|
430
|
+
|
|
431
|
+
// Cleanup listener on unmount
|
|
432
|
+
return () => {
|
|
433
|
+
events.off(
|
|
434
|
+
EventNames.USER_STOPPED_TRANSLATION,
|
|
435
|
+
handleUserStoppedTranslation,
|
|
436
|
+
);
|
|
437
|
+
};
|
|
438
|
+
}, []);
|
|
439
|
+
|
|
440
|
+
const startSTTBotSession = async (
|
|
441
|
+
newConfig: LanguageTranslationConfig,
|
|
442
|
+
): Promise<STTAPIResponse> => {
|
|
443
|
+
if (!localBotUid || !localUid) {
|
|
444
|
+
console.warn('[STT] Missing localUid or botUid');
|
|
445
|
+
return {
|
|
446
|
+
success: false,
|
|
447
|
+
error: {message: 'Missing localUid or botUid'},
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
try {
|
|
452
|
+
setIsLangChangeInProgress(true);
|
|
453
|
+
const result = await start(localBotUid, newConfig);
|
|
454
|
+
console.log('STT start result: ', result);
|
|
455
|
+
|
|
456
|
+
if (result.success || result.error?.code === 610) {
|
|
457
|
+
// Success or already started
|
|
458
|
+
setIsSTTActive(true);
|
|
459
|
+
setIsSTTError(false);
|
|
460
|
+
|
|
461
|
+
// Add transcript entry for language change
|
|
462
|
+
// If STT was not active before, this is the first time setting the language
|
|
463
|
+
const actionText = !isSTTActive
|
|
464
|
+
? `has set the spoken language to "${getLanguageLabel(
|
|
465
|
+
newConfig.source,
|
|
466
|
+
)}"`
|
|
467
|
+
: `changed the spoken language from "${getLanguageLabel(
|
|
468
|
+
translationConfig?.source,
|
|
469
|
+
)}" to "${getLanguageLabel(newConfig.source)}"`;
|
|
470
|
+
|
|
471
|
+
setTranslationConfig(newConfig);
|
|
472
|
+
setMeetingTranscript(prev => [
|
|
473
|
+
...prev,
|
|
474
|
+
{
|
|
475
|
+
name: 'langUpdate',
|
|
476
|
+
time: new Date().getTime(),
|
|
477
|
+
uid: `langUpdate-${localUid}`,
|
|
478
|
+
text: actionText,
|
|
479
|
+
},
|
|
480
|
+
]);
|
|
481
|
+
|
|
482
|
+
// Broadcast spoken language to all users
|
|
483
|
+
events.send(
|
|
484
|
+
EventNames.STT_SPOKEN_LANGUAGE,
|
|
485
|
+
JSON.stringify({
|
|
486
|
+
userUid: localUid,
|
|
487
|
+
spokenLanguage: newConfig.source[0],
|
|
488
|
+
username: username,
|
|
489
|
+
}),
|
|
490
|
+
PersistanceLevel.Sender,
|
|
491
|
+
);
|
|
492
|
+
|
|
493
|
+
logger.log(
|
|
494
|
+
LogSource.NetworkRest,
|
|
495
|
+
'stt',
|
|
496
|
+
'STT started successfully',
|
|
497
|
+
result.data,
|
|
498
|
+
);
|
|
499
|
+
} else {
|
|
500
|
+
// setIsCaptionON(false);
|
|
501
|
+
setIsSTTError(true);
|
|
502
|
+
logger.error(
|
|
503
|
+
LogSource.NetworkRest,
|
|
504
|
+
'stt',
|
|
505
|
+
'Failed to start STT',
|
|
506
|
+
result.error,
|
|
507
|
+
);
|
|
508
|
+
// Show error toast: text1 = translated label, text2 = API error
|
|
509
|
+
Toast.show({
|
|
510
|
+
leadingIconName: 'alert',
|
|
511
|
+
type: 'error',
|
|
512
|
+
text1: startErrorLabel,
|
|
513
|
+
text2: result.error?.message || 'Unknown error occurred',
|
|
514
|
+
visibilityTime: 4000,
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
setIsLangChangeInProgress(false);
|
|
518
|
+
return result;
|
|
519
|
+
} catch (error) {
|
|
520
|
+
setIsLangChangeInProgress(false);
|
|
521
|
+
setIsSTTError(true);
|
|
522
|
+
logger.error(LogSource.NetworkRest, 'stt', 'STT start error', error);
|
|
523
|
+
// Show error toast: text1 = translated label, text2 = exception error
|
|
524
|
+
Toast.show({
|
|
525
|
+
leadingIconName: 'alert',
|
|
526
|
+
type: 'error',
|
|
527
|
+
text1: startErrorLabel,
|
|
528
|
+
text2: error?.message || 'Unknown error occurred',
|
|
529
|
+
visibilityTime: 4000,
|
|
530
|
+
});
|
|
531
|
+
return {
|
|
532
|
+
success: false,
|
|
533
|
+
error: {message: error?.message || 'Unknown error'},
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
const updateSTTBotSession = async (
|
|
539
|
+
newConfig: LanguageTranslationConfig,
|
|
540
|
+
): Promise<STTAPIResponse> => {
|
|
541
|
+
if (!localBotUid || !localUid) {
|
|
542
|
+
console.warn('[STT] Missing localUid or botUid');
|
|
543
|
+
return {
|
|
544
|
+
success: false,
|
|
545
|
+
error: {message: 'Missing localUid or botUid'},
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
try {
|
|
550
|
+
setIsLangChangeInProgress(true);
|
|
551
|
+
const result = await update(localBotUid, newConfig);
|
|
552
|
+
|
|
553
|
+
if (result.success) {
|
|
554
|
+
setTranslationConfig(newConfig);
|
|
555
|
+
setIsSTTError(false);
|
|
556
|
+
|
|
557
|
+
// Add transcript entry for language change
|
|
558
|
+
// Determine what actually changed
|
|
559
|
+
const spokenLanguageChanged =
|
|
560
|
+
translationConfig?.source[0] !== newConfig.source[0];
|
|
561
|
+
const oldTargetsSorted = (translationConfig?.targets || [])
|
|
562
|
+
.sort()
|
|
563
|
+
.map(lang => getLanguageLabel([lang]))
|
|
564
|
+
.join(', ');
|
|
565
|
+
const newTargetsSorted = (newConfig.targets || [])
|
|
566
|
+
.sort()
|
|
567
|
+
.map(lang => getLanguageLabel([lang]))
|
|
568
|
+
.join(', ');
|
|
569
|
+
const targetsChanged = oldTargetsSorted !== newTargetsSorted;
|
|
570
|
+
|
|
571
|
+
const oldTargetsLength = translationConfig?.targets?.length || 0;
|
|
572
|
+
const newTargetsLength = newConfig.targets?.length || 0;
|
|
573
|
+
const targetsWereDisabled =
|
|
574
|
+
oldTargetsLength > 0 && newTargetsLength === 0;
|
|
575
|
+
const targetsWereEnabled =
|
|
576
|
+
oldTargetsLength === 0 && newTargetsLength > 0;
|
|
577
|
+
|
|
578
|
+
// Build target message once
|
|
579
|
+
let targetMessage = '';
|
|
580
|
+
if (targetsChanged) {
|
|
581
|
+
if (targetsWereDisabled) {
|
|
582
|
+
targetMessage = 'stopped translations';
|
|
583
|
+
} else if (targetsWereEnabled) {
|
|
584
|
+
targetMessage = `enabled translations to "${newTargetsSorted}"`;
|
|
585
|
+
} else {
|
|
586
|
+
targetMessage = `changed target translation languages to "${newTargetsSorted}"`;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// Build action text
|
|
591
|
+
let actionText = '';
|
|
592
|
+
if (spokenLanguageChanged && targetsChanged) {
|
|
593
|
+
// Both spoken language and targets changed
|
|
594
|
+
actionText = `changed spoken language from "${getLanguageLabel(
|
|
595
|
+
translationConfig?.source,
|
|
596
|
+
)}" to "${getLanguageLabel(newConfig.source)}" and ${targetMessage}`;
|
|
597
|
+
} else if (spokenLanguageChanged) {
|
|
598
|
+
// Only spoken language changed
|
|
599
|
+
actionText = `changed the spoken language from "${getLanguageLabel(
|
|
600
|
+
translationConfig?.source,
|
|
601
|
+
)}" to "${getLanguageLabel(newConfig.source)}"`;
|
|
602
|
+
} else if (targetsChanged) {
|
|
603
|
+
// Only target languages changed
|
|
604
|
+
actionText = targetMessage;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
if (actionText) {
|
|
608
|
+
setMeetingTranscript(prev => [
|
|
609
|
+
...prev,
|
|
610
|
+
{
|
|
611
|
+
name: 'langUpdate',
|
|
612
|
+
uid: `langUpdate-${localUid}`,
|
|
613
|
+
time: new Date().getTime(),
|
|
614
|
+
text: actionText,
|
|
615
|
+
},
|
|
616
|
+
]);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
// Broadcast updated spoken language to all users (only if it changed)
|
|
620
|
+
if (spokenLanguageChanged) {
|
|
621
|
+
events.send(
|
|
622
|
+
EventNames.STT_SPOKEN_LANGUAGE,
|
|
623
|
+
JSON.stringify({
|
|
624
|
+
userUid: localUid,
|
|
625
|
+
spokenLanguage: newConfig.source[0],
|
|
626
|
+
username: username,
|
|
627
|
+
}),
|
|
628
|
+
PersistanceLevel.Sender,
|
|
629
|
+
);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// Send event when user stops translation
|
|
633
|
+
if (targetsWereDisabled) {
|
|
634
|
+
events.send(
|
|
635
|
+
EventNames.USER_STOPPED_TRANSLATION,
|
|
636
|
+
JSON.stringify({
|
|
637
|
+
userUid: localUid,
|
|
638
|
+
username: username,
|
|
639
|
+
}),
|
|
640
|
+
);
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
logger.log(
|
|
644
|
+
LogSource.NetworkRest,
|
|
645
|
+
'stt',
|
|
646
|
+
'STT updated successfully',
|
|
647
|
+
result.data,
|
|
648
|
+
);
|
|
649
|
+
} else {
|
|
650
|
+
setIsSTTError(true);
|
|
651
|
+
logger.error(
|
|
652
|
+
LogSource.NetworkRest,
|
|
653
|
+
'stt',
|
|
654
|
+
'Failed to update STT',
|
|
655
|
+
result.error,
|
|
656
|
+
);
|
|
657
|
+
// Show error toast: text1 = translated label, text2 = API error
|
|
658
|
+
Toast.show({
|
|
659
|
+
leadingIconName: 'alert',
|
|
660
|
+
type: 'error',
|
|
661
|
+
text1: updateErrorLabel,
|
|
662
|
+
text2: result.error?.message || 'Unknown error occurred',
|
|
663
|
+
visibilityTime: 4000,
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
setIsLangChangeInProgress(false);
|
|
667
|
+
return result;
|
|
668
|
+
} catch (error) {
|
|
669
|
+
setIsLangChangeInProgress(false);
|
|
670
|
+
setIsSTTError(true);
|
|
671
|
+
logger.error(LogSource.NetworkRest, 'stt', 'STT update error', error);
|
|
672
|
+
// Show error toast: text1 = translated label, text2 = exception error
|
|
673
|
+
Toast.show({
|
|
674
|
+
leadingIconName: 'alert',
|
|
675
|
+
type: 'error',
|
|
676
|
+
text1: updateErrorLabel,
|
|
677
|
+
text2: error?.message || 'Unknown error occurred',
|
|
678
|
+
visibilityTime: 4000,
|
|
679
|
+
});
|
|
680
|
+
return {
|
|
681
|
+
success: false,
|
|
682
|
+
error: {message: error?.message || 'Unknown error'},
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
};
|
|
686
|
+
|
|
687
|
+
const handleTranslateConfigChange = async (
|
|
688
|
+
inputTranslateConfig: LanguageTranslationConfig,
|
|
689
|
+
) => {
|
|
690
|
+
if (!localBotUid || !localUid) {
|
|
691
|
+
console.warn('[STT] Missing localUid or botUid');
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
const newConfig: LanguageTranslationConfig = {
|
|
696
|
+
source: inputTranslateConfig?.source,
|
|
697
|
+
targets: inputTranslateConfig?.targets,
|
|
698
|
+
};
|
|
699
|
+
|
|
700
|
+
let action: 'start' | 'update' = 'start';
|
|
701
|
+
if (!isSTTActive) {
|
|
702
|
+
action = 'start';
|
|
703
|
+
} else if (hasConfigChanged(translationConfig, newConfig)) {
|
|
704
|
+
action = 'update';
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
console.log('[STT_HANDLE_CONFIRM]', {
|
|
708
|
+
action,
|
|
709
|
+
localBotUid,
|
|
710
|
+
inputConfig: inputTranslateConfig,
|
|
711
|
+
sanitizedConfig: newConfig,
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
try {
|
|
715
|
+
switch (action) {
|
|
716
|
+
case 'start':
|
|
717
|
+
const startResult = await startSTTBotSession(newConfig);
|
|
718
|
+
if (!startResult.success) {
|
|
719
|
+
throw new Error(
|
|
720
|
+
startResult.error?.message || 'Failed to start STT',
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
break;
|
|
724
|
+
|
|
725
|
+
case 'update':
|
|
726
|
+
const updateResult = await updateSTTBotSession(newConfig);
|
|
727
|
+
if (!updateResult.success) {
|
|
728
|
+
throw new Error(
|
|
729
|
+
updateResult.error?.message || 'Failed to update STT config',
|
|
730
|
+
);
|
|
731
|
+
}
|
|
732
|
+
break;
|
|
733
|
+
|
|
734
|
+
default:
|
|
735
|
+
console.warn('Unknown STT action');
|
|
736
|
+
}
|
|
737
|
+
} catch (error) {
|
|
738
|
+
setIsSTTError(true);
|
|
739
|
+
setIsLangChangeInProgress(false);
|
|
740
|
+
logger.error(
|
|
741
|
+
LogSource.NetworkRest,
|
|
742
|
+
'stt',
|
|
743
|
+
'Error in handleTranslateConfigChange',
|
|
744
|
+
error,
|
|
745
|
+
);
|
|
746
|
+
throw error;
|
|
747
|
+
}
|
|
748
|
+
};
|
|
749
|
+
|
|
750
|
+
const stopSTTBotSession = React.useCallback(async () => {
|
|
751
|
+
console.log('[STT_PER_USER_BOT] stopCaption called');
|
|
752
|
+
|
|
753
|
+
if (!localBotUid) {
|
|
754
|
+
console.warn('[STT] Missing botUid');
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
try {
|
|
759
|
+
const result = await stop(localBotUid);
|
|
760
|
+
|
|
761
|
+
if (result.success) {
|
|
762
|
+
// Set STT inactive locally
|
|
763
|
+
setIsSTTActive(false);
|
|
764
|
+
// Clear user's source language when stopping
|
|
765
|
+
setTranslationConfig({
|
|
766
|
+
source: [],
|
|
767
|
+
targets: [],
|
|
768
|
+
});
|
|
769
|
+
// setIsCaptionON(false);
|
|
770
|
+
setIsSTTError(false);
|
|
771
|
+
|
|
772
|
+
logger.log(
|
|
773
|
+
LogSource.NetworkRest,
|
|
774
|
+
'stt',
|
|
775
|
+
'STT stopped successfully',
|
|
776
|
+
result.data,
|
|
777
|
+
);
|
|
778
|
+
} else {
|
|
779
|
+
setIsSTTError(true);
|
|
780
|
+
logger.error(
|
|
781
|
+
LogSource.NetworkRest,
|
|
782
|
+
'stt',
|
|
783
|
+
'Failed to stop STT',
|
|
784
|
+
result.error,
|
|
785
|
+
);
|
|
786
|
+
}
|
|
787
|
+
} catch (error) {
|
|
788
|
+
setIsSTTError(true);
|
|
789
|
+
logger.error(
|
|
790
|
+
LogSource.NetworkRest,
|
|
791
|
+
'stt',
|
|
792
|
+
'Error in stopSTTBotSession',
|
|
793
|
+
error,
|
|
794
|
+
);
|
|
795
|
+
throw error;
|
|
796
|
+
}
|
|
797
|
+
}, [stop, localBotUid]);
|
|
798
|
+
|
|
799
|
+
// Helper function to convert user UID to stt bot UID
|
|
800
|
+
const generateBotUidForUser = (userLocalUid: number): number => {
|
|
801
|
+
return 900000000 + (userLocalUid % 100000000);
|
|
802
|
+
};
|
|
803
|
+
|
|
804
|
+
// Helper function to convert bot UID to user UID
|
|
805
|
+
// Bot UIDs are in format: 900000000 + userUid
|
|
806
|
+
// This function reverse-maps botUid → userUid using mathematical calculation
|
|
807
|
+
const getBotOwnerUid = React.useCallback(
|
|
808
|
+
(botUid: string | number): string | number => {
|
|
809
|
+
const botUidStr = String(botUid);
|
|
810
|
+
|
|
811
|
+
// Check if this is a special UID (langUpdate, translationUpdate, etc.)
|
|
812
|
+
if (botUidStr.indexOf('Update') !== -1) {
|
|
813
|
+
return botUid;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
// If it's a bot UID (starts with 900000000), extract the user UID
|
|
817
|
+
const botUidNum = Number(botUid);
|
|
818
|
+
if (!isNaN(botUidNum) && botUidNum >= 900000000) {
|
|
819
|
+
return botUidNum - 900000000;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// Otherwise it's already a user UID, return as is
|
|
823
|
+
return botUid;
|
|
824
|
+
},
|
|
825
|
+
[],
|
|
826
|
+
);
|
|
101
827
|
|
|
102
828
|
return (
|
|
103
829
|
<CaptionContext.Provider
|
|
@@ -108,18 +834,35 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
108
834
|
setIsSTTError,
|
|
109
835
|
isSTTActive,
|
|
110
836
|
setIsSTTActive,
|
|
111
|
-
|
|
112
|
-
|
|
837
|
+
translationConfig,
|
|
838
|
+
setTranslationConfig,
|
|
839
|
+
captionViewMode,
|
|
840
|
+
setCaptionViewMode,
|
|
841
|
+
transcriptViewMode,
|
|
842
|
+
setTranscriptViewMode,
|
|
113
843
|
meetingTranscript,
|
|
114
844
|
setMeetingTranscript,
|
|
115
845
|
isLangChangeInProgress,
|
|
116
846
|
setIsLangChangeInProgress,
|
|
847
|
+
isTranslationChangeInProgress,
|
|
848
|
+
setIsTranslationChangeInProgress,
|
|
117
849
|
captionObj,
|
|
118
850
|
setCaptionObj,
|
|
119
851
|
isSTTListenerAdded,
|
|
120
852
|
setIsSTTListenerAdded,
|
|
121
853
|
activeSpeakerRef,
|
|
122
854
|
prevSpeakerRef,
|
|
855
|
+
selectedTranslationLanguage,
|
|
856
|
+
setSelectedTranslationLanguage,
|
|
857
|
+
selectedTranslationLanguageRef,
|
|
858
|
+
translationConfigRef,
|
|
859
|
+
remoteSpokenLanguages,
|
|
860
|
+
setRemoteSpokenLanguages,
|
|
861
|
+
handleTranslateConfigChange,
|
|
862
|
+
startSTTBotSession,
|
|
863
|
+
updateSTTBotSession,
|
|
864
|
+
stopSTTBotSession,
|
|
865
|
+
getBotOwnerUid,
|
|
123
866
|
}}>
|
|
124
867
|
{children}
|
|
125
868
|
</CaptionContext.Provider>
|