agora-appbuilder-core 4.1.23 → 4.1.24-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 +1 -1
- package/template/bridge/rtc/webNg/RtcEngine.ts +86 -49
- package/template/bridge/rtc/webNg/__tests__/screenshareLifecycle.test.ts +50 -21
- package/template/defaultConfig.js +2 -2
- package/template/src/components/PinnedVideo.tsx +43 -23
- package/template/src/components/__tests__/pinnedLayoutState.test.ts +47 -0
- package/template/src/components/participants/UserActionMenuOptions.tsx +15 -2
- package/template/src/components/pinnedLayoutState.ts +43 -0
- package/template/src/pages/video-call/VideoRenderer.tsx +2 -0
- package/template/src/subComponents/caption/Transcript.tsx +36 -0
- package/template/src/subComponents/caption/__tests__/transcriptJourney.test.ts +7 -0
- package/template/src/subComponents/caption/transcriptJourney.ts +1 -0
- package/template/src/subComponents/caption/useCaption.tsx +215 -46
- package/template/src/subComponents/caption/useSTTAPI.tsx +13 -12
- package/template/src/subComponents/caption/useStreamMessageUtils.ts +109 -8
- package/template/src/subComponents/screenshare/ScreenshareConfigure.native.tsx +115 -30
- package/template/src/subComponents/screenshare/ScreenshareConfigure.tsx +489 -147
- package/template/src/subComponents/screenshare/__tests__/ScreenshareConfigure.test.tsx +245 -0
- package/template/src/subComponents/screenshare/__tests__/screenshareInterruptionRecovery.test.ts +119 -0
- package/template/src/subComponents/screenshare/screenshareInterruptionRecovery.ts +118 -0
|
@@ -247,10 +247,12 @@ const VideoRenderer: React.FC<VideoRendererProps> = ({
|
|
|
247
247
|
uid={user.uid}
|
|
248
248
|
hasLeadingIcon={
|
|
249
249
|
currentLayout === DefaultLayouts[1].name &&
|
|
250
|
+
!isMax &&
|
|
250
251
|
user.uid === secondaryPinnedUid
|
|
251
252
|
}
|
|
252
253
|
/>
|
|
253
254
|
{currentLayout === DefaultLayouts[1].name &&
|
|
255
|
+
!isMax &&
|
|
254
256
|
user.uid === secondaryPinnedUid ? (
|
|
255
257
|
<View
|
|
256
258
|
style={{
|
|
@@ -40,6 +40,8 @@ import {
|
|
|
40
40
|
sttTranscriptPanelSearchText,
|
|
41
41
|
sttTranscriptPanelViewLatestText,
|
|
42
42
|
} from '../../../src/language/default-labels/videoCallScreenLabels';
|
|
43
|
+
import {logger, LogSource} from '../../logger/AppBuilderLogger';
|
|
44
|
+
import {TRANSCRIPT_JOURNEY} from './transcriptJourney';
|
|
43
45
|
|
|
44
46
|
export interface TranscriptProps {
|
|
45
47
|
showHeader?: boolean;
|
|
@@ -56,6 +58,7 @@ const Transcript = (props: TranscriptProps) => {
|
|
|
56
58
|
isSTTActive,
|
|
57
59
|
selectedTranslationLanguage,
|
|
58
60
|
transcriptViewMode,
|
|
61
|
+
isSTTListenerAdded,
|
|
59
62
|
} = useCaption();
|
|
60
63
|
|
|
61
64
|
const settingSpokenLanguageLabel = useString(sttSettingSpokenLanguageText)();
|
|
@@ -68,6 +71,39 @@ const Transcript = (props: TranscriptProps) => {
|
|
|
68
71
|
|
|
69
72
|
const data = meetingTranscript; // Object.entries(transcript);
|
|
70
73
|
console.log('[STT_GLOBAL] meetingTranscript data: ', data);
|
|
74
|
+
const hasLoggedFirstEntryRef = React.useRef(false);
|
|
75
|
+
const transcriptEntryCountRef = React.useRef(data.length);
|
|
76
|
+
transcriptEntryCountRef.current = data.length;
|
|
77
|
+
|
|
78
|
+
React.useEffect(() => {
|
|
79
|
+
logger.log(
|
|
80
|
+
LogSource.Internals,
|
|
81
|
+
'TRANSCRIPT',
|
|
82
|
+
`${TRANSCRIPT_JOURNEY} transcript panel state`,
|
|
83
|
+
{
|
|
84
|
+
stage: 'transcript_panel',
|
|
85
|
+
isSTTActive,
|
|
86
|
+
listenerRegistered: isSTTListenerAdded,
|
|
87
|
+
transcriptEntryCount: transcriptEntryCountRef.current,
|
|
88
|
+
},
|
|
89
|
+
);
|
|
90
|
+
}, [isSTTActive, isSTTListenerAdded]);
|
|
91
|
+
|
|
92
|
+
React.useEffect(() => {
|
|
93
|
+
if (data.length > 0 && !hasLoggedFirstEntryRef.current) {
|
|
94
|
+
hasLoggedFirstEntryRef.current = true;
|
|
95
|
+
logger.log(
|
|
96
|
+
LogSource.Internals,
|
|
97
|
+
'TRANSCRIPT',
|
|
98
|
+
`${TRANSCRIPT_JOURNEY} first transcript entry available to panel`,
|
|
99
|
+
{
|
|
100
|
+
stage: 'transcript_panel_data',
|
|
101
|
+
outcome: 'success',
|
|
102
|
+
transcriptEntryCount: data.length,
|
|
103
|
+
},
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}, [data.length]);
|
|
71
107
|
|
|
72
108
|
const [showButton, setShowButton] = React.useState(false);
|
|
73
109
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const TRANSCRIPT_JOURNEY = '[TRANSCRIPT_JOURNEY]';
|
|
@@ -21,6 +21,7 @@ import {useRoomInfo} from '../../components/room-info/useRoomInfo';
|
|
|
21
21
|
import {useContent, useRtc} from 'customization-api';
|
|
22
22
|
import useStreamMessageUtils from './useStreamMessageUtils';
|
|
23
23
|
import {isWebInternal} from '../../utils/common';
|
|
24
|
+
import {TRANSCRIPT_JOURNEY} from './transcriptJourney';
|
|
24
25
|
|
|
25
26
|
// Types
|
|
26
27
|
type GlobalSttState = {
|
|
@@ -348,17 +349,58 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
348
349
|
return;
|
|
349
350
|
}
|
|
350
351
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
352
|
+
logger.log(
|
|
353
|
+
LogSource.Internals,
|
|
354
|
+
'TRANSCRIPT',
|
|
355
|
+
`${TRANSCRIPT_JOURNEY} stream listener registration requested`,
|
|
356
|
+
{stage: 'listener_registration', outcome: 'started'},
|
|
354
357
|
);
|
|
355
|
-
|
|
358
|
+
try {
|
|
359
|
+
transcriptListenerSubscriptionRef.current = RtcEngineUnsafe.addListener(
|
|
360
|
+
'onStreamMessage',
|
|
361
|
+
handleStreamMessageCallback,
|
|
362
|
+
);
|
|
363
|
+
setIsSTTListenerAdded(true);
|
|
364
|
+
logger.log(
|
|
365
|
+
LogSource.Internals,
|
|
366
|
+
'TRANSCRIPT',
|
|
367
|
+
`${TRANSCRIPT_JOURNEY} stream listener registered`,
|
|
368
|
+
{stage: 'listener_registration', outcome: 'success'},
|
|
369
|
+
);
|
|
370
|
+
} catch (error) {
|
|
371
|
+
logger.error(
|
|
372
|
+
LogSource.Internals,
|
|
373
|
+
'TRANSCRIPT',
|
|
374
|
+
`${TRANSCRIPT_JOURNEY} stream listener registration failed`,
|
|
375
|
+
{
|
|
376
|
+
stage: 'listener_registration',
|
|
377
|
+
outcome: 'failure',
|
|
378
|
+
error: error ?? null,
|
|
379
|
+
},
|
|
380
|
+
);
|
|
381
|
+
}
|
|
356
382
|
}, [RtcEngineUnsafe, callActive, handleStreamMessageCallback]);
|
|
357
383
|
|
|
358
384
|
React.useEffect(() => {
|
|
359
385
|
return () => {
|
|
386
|
+
logger.log(
|
|
387
|
+
LogSource.Internals,
|
|
388
|
+
'TRANSCRIPT',
|
|
389
|
+
`${TRANSCRIPT_JOURNEY} stream listener cleanup requested`,
|
|
390
|
+
{
|
|
391
|
+
stage: 'listener_cleanup',
|
|
392
|
+
outcome: 'started',
|
|
393
|
+
listenerReferencePresent: !!transcriptListenerSubscriptionRef.current,
|
|
394
|
+
},
|
|
395
|
+
);
|
|
360
396
|
transcriptListenerSubscriptionRef.current?.remove();
|
|
361
397
|
transcriptListenerSubscriptionRef.current = null;
|
|
398
|
+
logger.log(
|
|
399
|
+
LogSource.Internals,
|
|
400
|
+
'TRANSCRIPT',
|
|
401
|
+
`${TRANSCRIPT_JOURNEY} stream listener subscription remove called and local reference cleared`,
|
|
402
|
+
{stage: 'listener_cleanup', outcome: 'completed'},
|
|
403
|
+
);
|
|
362
404
|
};
|
|
363
405
|
}, []);
|
|
364
406
|
|
|
@@ -409,6 +451,31 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
409
451
|
sttDepsReadyRef.current = sttDepsReady;
|
|
410
452
|
}, [sttDepsReady]);
|
|
411
453
|
|
|
454
|
+
React.useEffect(() => {
|
|
455
|
+
logger.log(
|
|
456
|
+
LogSource.Internals,
|
|
457
|
+
'TRANSCRIPT',
|
|
458
|
+
`${TRANSCRIPT_JOURNEY} STT readiness changed`,
|
|
459
|
+
{
|
|
460
|
+
stage: 'stt_readiness',
|
|
461
|
+
outcome: sttDepsReady ? 'ready' : 'waiting',
|
|
462
|
+
localUidReady: !!localUid,
|
|
463
|
+
localBotUidReady: !!localBotUid,
|
|
464
|
+
rtmJoined: !!hasUserJoinedRTM,
|
|
465
|
+
callActive: !!callActive,
|
|
466
|
+
roomInfoReady: !!(roomId?.host || roomId?.attendee),
|
|
467
|
+
listenerRegistered: !!transcriptListenerSubscriptionRef.current,
|
|
468
|
+
},
|
|
469
|
+
);
|
|
470
|
+
}, [
|
|
471
|
+
callActive,
|
|
472
|
+
hasUserJoinedRTM,
|
|
473
|
+
localBotUid,
|
|
474
|
+
localUid,
|
|
475
|
+
roomId,
|
|
476
|
+
sttDepsReady,
|
|
477
|
+
]);
|
|
478
|
+
|
|
412
479
|
React.useEffect(() => {
|
|
413
480
|
if (sttDepsReadyRef.current && !hasFlushedSttQueueRef.current) {
|
|
414
481
|
hasFlushedSttQueueRef.current = true;
|
|
@@ -526,22 +593,21 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
526
593
|
try {
|
|
527
594
|
setIsLangChangeInProgress(true);
|
|
528
595
|
const result = await start(localBotUidRef.current, newConfig);
|
|
529
|
-
console.log('[STT] start result: ', result);
|
|
530
596
|
if (result.success) {
|
|
531
597
|
setIsSTTError(false);
|
|
532
598
|
logger.log(
|
|
533
599
|
LogSource.NetworkRest,
|
|
534
600
|
'stt',
|
|
535
|
-
|
|
536
|
-
result.data,
|
|
601
|
+
`${TRANSCRIPT_JOURNEY} STT started successfully`,
|
|
602
|
+
result.data ?? null,
|
|
537
603
|
);
|
|
538
604
|
} else {
|
|
539
605
|
setIsSTTError(true);
|
|
540
606
|
logger.error(
|
|
541
607
|
LogSource.NetworkRest,
|
|
542
608
|
'stt',
|
|
543
|
-
|
|
544
|
-
result.error,
|
|
609
|
+
`${TRANSCRIPT_JOURNEY} failed to start STT`,
|
|
610
|
+
result.error ?? null,
|
|
545
611
|
);
|
|
546
612
|
Toast.show({
|
|
547
613
|
leadingIconName: 'alert',
|
|
@@ -558,7 +624,12 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
558
624
|
} catch (error: any) {
|
|
559
625
|
setIsLangChangeInProgress(false);
|
|
560
626
|
setIsSTTError(true);
|
|
561
|
-
logger.error(
|
|
627
|
+
logger.error(
|
|
628
|
+
LogSource.NetworkRest,
|
|
629
|
+
'stt',
|
|
630
|
+
`${TRANSCRIPT_JOURNEY} STT start error`,
|
|
631
|
+
error ?? null,
|
|
632
|
+
);
|
|
562
633
|
// Show error toast: text1 = translated label, text2 = exception error
|
|
563
634
|
Toast.show({
|
|
564
635
|
leadingIconName: 'alert',
|
|
@@ -603,16 +674,16 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
603
674
|
logger.log(
|
|
604
675
|
LogSource.NetworkRest,
|
|
605
676
|
'stt',
|
|
606
|
-
|
|
607
|
-
result.data,
|
|
677
|
+
`${TRANSCRIPT_JOURNEY} STT updated successfully`,
|
|
678
|
+
result.data ?? null,
|
|
608
679
|
);
|
|
609
680
|
} else {
|
|
610
681
|
setIsSTTError(true);
|
|
611
682
|
logger.error(
|
|
612
683
|
LogSource.NetworkRest,
|
|
613
684
|
'stt',
|
|
614
|
-
|
|
615
|
-
result.error,
|
|
685
|
+
`${TRANSCRIPT_JOURNEY} failed to update STT`,
|
|
686
|
+
result.error ?? null,
|
|
616
687
|
);
|
|
617
688
|
// Show error toast: text1 = translated label, text2 = API error
|
|
618
689
|
Toast.show({
|
|
@@ -630,7 +701,12 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
630
701
|
} catch (error: any) {
|
|
631
702
|
setIsLangChangeInProgress(false);
|
|
632
703
|
setIsSTTError(true);
|
|
633
|
-
logger.error(
|
|
704
|
+
logger.error(
|
|
705
|
+
LogSource.NetworkRest,
|
|
706
|
+
'stt',
|
|
707
|
+
`${TRANSCRIPT_JOURNEY} STT update error`,
|
|
708
|
+
error ?? null,
|
|
709
|
+
);
|
|
634
710
|
// Show error toast: text1 = translated label, text2 = exception error
|
|
635
711
|
Toast.show({
|
|
636
712
|
leadingIconName: 'alert',
|
|
@@ -649,10 +725,20 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
649
725
|
};
|
|
650
726
|
|
|
651
727
|
const stopSTTBotSession = React.useCallback(async () => {
|
|
652
|
-
|
|
728
|
+
logger.log(
|
|
729
|
+
LogSource.Internals,
|
|
730
|
+
'TRANSCRIPT',
|
|
731
|
+
`${TRANSCRIPT_JOURNEY} STT stop requested`,
|
|
732
|
+
{stage: 'stt_stop', localBotUid: localBotUidRef.current ?? null},
|
|
733
|
+
);
|
|
653
734
|
|
|
654
735
|
if (!localBotUidRef.current) {
|
|
655
|
-
|
|
736
|
+
logger.warn(
|
|
737
|
+
LogSource.Internals,
|
|
738
|
+
'TRANSCRIPT',
|
|
739
|
+
`${TRANSCRIPT_JOURNEY} STT stop skipped because bot UID is missing`,
|
|
740
|
+
{stage: 'stt_stop', outcome: 'skipped'},
|
|
741
|
+
);
|
|
656
742
|
return;
|
|
657
743
|
}
|
|
658
744
|
|
|
@@ -668,16 +754,16 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
668
754
|
logger.log(
|
|
669
755
|
LogSource.NetworkRest,
|
|
670
756
|
'stt',
|
|
671
|
-
|
|
672
|
-
result.data,
|
|
757
|
+
`${TRANSCRIPT_JOURNEY} STT stopped successfully`,
|
|
758
|
+
result.data ?? null,
|
|
673
759
|
);
|
|
674
760
|
} else {
|
|
675
761
|
setIsSTTError(true);
|
|
676
762
|
logger.error(
|
|
677
763
|
LogSource.NetworkRest,
|
|
678
764
|
'stt',
|
|
679
|
-
|
|
680
|
-
result.error,
|
|
765
|
+
`${TRANSCRIPT_JOURNEY} failed to stop STT`,
|
|
766
|
+
result.error ?? null,
|
|
681
767
|
);
|
|
682
768
|
}
|
|
683
769
|
} catch (error) {
|
|
@@ -685,8 +771,8 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
685
771
|
logger.error(
|
|
686
772
|
LogSource.NetworkRest,
|
|
687
773
|
'stt',
|
|
688
|
-
|
|
689
|
-
error,
|
|
774
|
+
`${TRANSCRIPT_JOURNEY} error in stopSTTBotSession`,
|
|
775
|
+
error ?? null,
|
|
690
776
|
);
|
|
691
777
|
}
|
|
692
778
|
}, [stop]);
|
|
@@ -757,12 +843,29 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
757
843
|
// Queue
|
|
758
844
|
enqueueSttEvent(updatedState, true, targetChange);
|
|
759
845
|
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
846
|
+
logger.log(
|
|
847
|
+
LogSource.Internals,
|
|
848
|
+
'TRANSCRIPT',
|
|
849
|
+
`${TRANSCRIPT_JOURNEY} local spoken-language state queued`,
|
|
850
|
+
{
|
|
851
|
+
stage: 'global_state_queue',
|
|
852
|
+
outcome: 'queued',
|
|
853
|
+
spokenLanguage: updatedState.globalSpokenLanguage ?? null,
|
|
854
|
+
translationTargetCount:
|
|
855
|
+
updatedState.globalTranslationTargets.length,
|
|
856
|
+
},
|
|
763
857
|
);
|
|
764
858
|
} catch (error) {
|
|
765
|
-
|
|
859
|
+
logger.error(
|
|
860
|
+
LogSource.Internals,
|
|
861
|
+
'TRANSCRIPT',
|
|
862
|
+
`${TRANSCRIPT_JOURNEY} local spoken-language state failed`,
|
|
863
|
+
{
|
|
864
|
+
stage: 'global_state_queue',
|
|
865
|
+
outcome: 'failure',
|
|
866
|
+
error: error ?? null,
|
|
867
|
+
},
|
|
868
|
+
);
|
|
766
869
|
}
|
|
767
870
|
},
|
|
768
871
|
[localUid], // only real dependency
|
|
@@ -817,15 +920,24 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
817
920
|
// Queues all local + remote stt events
|
|
818
921
|
const enqueueSttEvent = React.useCallback(
|
|
819
922
|
(state: GlobalSttState, isLocal: boolean, targetChange?: TargetChange) => {
|
|
820
|
-
console.log(
|
|
821
|
-
'[STT_GLOBAL] inside enqueueSttEvent - sttDepsReadyRef flag',
|
|
822
|
-
sttDepsReadyRef.current,
|
|
823
|
-
);
|
|
824
923
|
sttEventQueueRef.current.push({
|
|
825
924
|
state,
|
|
826
925
|
isLocal,
|
|
827
926
|
targetChange,
|
|
828
927
|
});
|
|
928
|
+
logger.log(
|
|
929
|
+
LogSource.Internals,
|
|
930
|
+
'TRANSCRIPT',
|
|
931
|
+
`${TRANSCRIPT_JOURNEY} STT global state queued`,
|
|
932
|
+
{
|
|
933
|
+
stage: 'global_state_queue',
|
|
934
|
+
outcome: 'queued',
|
|
935
|
+
stateOrigin: isLocal ? 'local' : 'remote',
|
|
936
|
+
sttEnabled: state.globalSttEnabled,
|
|
937
|
+
sttDepsReady: sttDepsReadyRef.current,
|
|
938
|
+
queueSize: sttEventQueueRef.current.length,
|
|
939
|
+
},
|
|
940
|
+
);
|
|
829
941
|
if (sttDepsReadyRef.current) {
|
|
830
942
|
processSttEventQueue();
|
|
831
943
|
}
|
|
@@ -852,7 +964,12 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
852
964
|
!globalSttStateRef.current.globalSttEnabled &&
|
|
853
965
|
sttEventQueueRef.current.length === 0
|
|
854
966
|
) {
|
|
855
|
-
|
|
967
|
+
logger.log(
|
|
968
|
+
LogSource.Internals,
|
|
969
|
+
'TRANSCRIPT',
|
|
970
|
+
`${TRANSCRIPT_JOURNEY} STT auto-start state injected`,
|
|
971
|
+
{stage: 'global_state_queue', outcome: 'queued'},
|
|
972
|
+
);
|
|
856
973
|
|
|
857
974
|
sttAutoStartGuardRef.current = true;
|
|
858
975
|
|
|
@@ -879,7 +996,12 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
879
996
|
const {state: newState, isLocal, targetChange} = item;
|
|
880
997
|
const prevState = globalSttStateRef.current;
|
|
881
998
|
if (isSameState(prevState, newState)) {
|
|
882
|
-
|
|
999
|
+
logger.log(
|
|
1000
|
+
LogSource.Internals,
|
|
1001
|
+
'TRANSCRIPT',
|
|
1002
|
+
`${TRANSCRIPT_JOURNEY} duplicate STT global state skipped`,
|
|
1003
|
+
{stage: 'global_state_queue', outcome: 'skipped'},
|
|
1004
|
+
);
|
|
883
1005
|
continue; // no call to processGlobalSttSingleEvent
|
|
884
1006
|
}
|
|
885
1007
|
const ok = await processGlobalSttSingleEvent(
|
|
@@ -889,16 +1011,22 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
889
1011
|
);
|
|
890
1012
|
if (!ok) {
|
|
891
1013
|
if (isLocal) {
|
|
892
|
-
|
|
893
|
-
|
|
1014
|
+
logger.warn(
|
|
1015
|
+
LogSource.Internals,
|
|
1016
|
+
'TRANSCRIPT',
|
|
1017
|
+
`${TRANSCRIPT_JOURNEY} local global state update skipped because API failed`,
|
|
1018
|
+
{stage: 'global_state_apply', outcome: 'skipped'},
|
|
894
1019
|
);
|
|
895
1020
|
continue;
|
|
896
1021
|
}
|
|
897
1022
|
// A received RTM event is authoritative for the meeting-level state.
|
|
898
1023
|
// Failure to provision this participant's bot must not make the UI
|
|
899
1024
|
// report that meeting STT is disabled while captions are arriving.
|
|
900
|
-
|
|
901
|
-
|
|
1025
|
+
logger.warn(
|
|
1026
|
+
LogSource.Internals,
|
|
1027
|
+
'TRANSCRIPT',
|
|
1028
|
+
`${TRANSCRIPT_JOURNEY} remote global state applied after local STT API failure`,
|
|
1029
|
+
{stage: 'global_state_apply', outcome: 'applied_with_api_failure'},
|
|
902
1030
|
);
|
|
903
1031
|
}
|
|
904
1032
|
// update global state AFTER processing
|
|
@@ -923,10 +1051,24 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
923
1051
|
const isStopOperation = wasEnabledBefore && !isEnabledNow;
|
|
924
1052
|
try {
|
|
925
1053
|
if (isStartOperation) {
|
|
926
|
-
|
|
1054
|
+
logger.log(
|
|
1055
|
+
LogSource.Internals,
|
|
1056
|
+
'TRANSCRIPT',
|
|
1057
|
+
`${TRANSCRIPT_JOURNEY} STT global state selected start operation`,
|
|
1058
|
+
{
|
|
1059
|
+
stage: 'global_state_operation',
|
|
1060
|
+
outcome: 'started',
|
|
1061
|
+
stateOrigin: isLocal ? 'local' : 'remote',
|
|
1062
|
+
},
|
|
1063
|
+
);
|
|
927
1064
|
// Start guard starts
|
|
928
1065
|
if (sttStartGuardRef.current) {
|
|
929
|
-
|
|
1066
|
+
logger.log(
|
|
1067
|
+
LogSource.Internals,
|
|
1068
|
+
'TRANSCRIPT',
|
|
1069
|
+
`${TRANSCRIPT_JOURNEY} STT start skipped by start guard`,
|
|
1070
|
+
{stage: 'global_state_operation', outcome: 'skipped'},
|
|
1071
|
+
);
|
|
930
1072
|
return;
|
|
931
1073
|
}
|
|
932
1074
|
sttStartGuardRef.current = true;
|
|
@@ -997,7 +1139,16 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
997
1139
|
}
|
|
998
1140
|
return true;
|
|
999
1141
|
} else if (isUpdateOperation) {
|
|
1000
|
-
|
|
1142
|
+
logger.log(
|
|
1143
|
+
LogSource.Internals,
|
|
1144
|
+
'TRANSCRIPT',
|
|
1145
|
+
`${TRANSCRIPT_JOURNEY} STT global state selected update operation`,
|
|
1146
|
+
{
|
|
1147
|
+
stage: 'global_state_operation',
|
|
1148
|
+
outcome: 'started',
|
|
1149
|
+
stateOrigin: isLocal ? 'local' : 'remote',
|
|
1150
|
+
},
|
|
1151
|
+
);
|
|
1001
1152
|
const result = await updateSTTBotSession(
|
|
1002
1153
|
{
|
|
1003
1154
|
source: [newState.globalSpokenLanguage],
|
|
@@ -1061,7 +1212,16 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
1061
1212
|
}
|
|
1062
1213
|
return true;
|
|
1063
1214
|
} else if (isStopOperation) {
|
|
1064
|
-
|
|
1215
|
+
logger.log(
|
|
1216
|
+
LogSource.Internals,
|
|
1217
|
+
'TRANSCRIPT',
|
|
1218
|
+
`${TRANSCRIPT_JOURNEY} STT global state selected stop operation`,
|
|
1219
|
+
{
|
|
1220
|
+
stage: 'global_state_operation',
|
|
1221
|
+
outcome: 'started',
|
|
1222
|
+
stateOrigin: isLocal ? 'local' : 'remote',
|
|
1223
|
+
},
|
|
1224
|
+
);
|
|
1065
1225
|
await stopSTTBotSession();
|
|
1066
1226
|
sttStartGuardRef.current = false;
|
|
1067
1227
|
return true;
|
|
@@ -1074,8 +1234,8 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
1074
1234
|
logger.error(
|
|
1075
1235
|
LogSource.Internals,
|
|
1076
1236
|
'STT',
|
|
1077
|
-
|
|
1078
|
-
error,
|
|
1237
|
+
`${TRANSCRIPT_JOURNEY} error handling STT_GLOBAL_STATE event`,
|
|
1238
|
+
error ?? null,
|
|
1079
1239
|
);
|
|
1080
1240
|
return false;
|
|
1081
1241
|
}
|
|
@@ -1087,7 +1247,16 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
1087
1247
|
React.useEffect(() => {
|
|
1088
1248
|
const handleGlobalSTTChange = async (evt: any) => {
|
|
1089
1249
|
const {payload} = evt || {};
|
|
1090
|
-
|
|
1250
|
+
logger.log(
|
|
1251
|
+
LogSource.Internals,
|
|
1252
|
+
'TRANSCRIPT',
|
|
1253
|
+
`${TRANSCRIPT_JOURNEY} STT_GLOBAL_STATE event received`,
|
|
1254
|
+
{
|
|
1255
|
+
stage: 'global_state_event',
|
|
1256
|
+
outcome: 'received',
|
|
1257
|
+
payloadPresent: typeof payload === 'string' && payload.length > 0,
|
|
1258
|
+
},
|
|
1259
|
+
);
|
|
1091
1260
|
let newState: GlobalSttState;
|
|
1092
1261
|
try {
|
|
1093
1262
|
newState = JSON.parse(payload);
|
|
@@ -1095,8 +1264,8 @@ const CaptionProvider: React.FC<CaptionProviderProps> = ({
|
|
|
1095
1264
|
logger.error(
|
|
1096
1265
|
LogSource.Internals,
|
|
1097
1266
|
'STT',
|
|
1098
|
-
|
|
1099
|
-
error,
|
|
1267
|
+
`${TRANSCRIPT_JOURNEY} failed to parse STT_GLOBAL_STATE event payload`,
|
|
1268
|
+
error ?? null,
|
|
1100
1269
|
);
|
|
1101
1270
|
return;
|
|
1102
1271
|
}
|
|
@@ -7,6 +7,7 @@ import {logger, LogSource} from '../../logger/AppBuilderLogger';
|
|
|
7
7
|
import getUniqueID from '../../utils/getUniqueID';
|
|
8
8
|
import {buildSTTRequestBody, type STTMethod} from './sttRequestBody';
|
|
9
9
|
import {ensureSTTSessionId} from './sttSessionId';
|
|
10
|
+
import {TRANSCRIPT_JOURNEY} from './transcriptJourney';
|
|
10
11
|
|
|
11
12
|
export interface STTAPIResponse {
|
|
12
13
|
success: boolean;
|
|
@@ -99,12 +100,12 @@ const useSTTAPI = (): IuseSTTAPI => {
|
|
|
99
100
|
});
|
|
100
101
|
|
|
101
102
|
console.log(
|
|
102
|
-
|
|
103
|
+
`${TRANSCRIPT_JOURNEY} [STT_BOT_SUBSCRIPTION] ${method.toUpperCase()} - Bot UID: ${botUid} will subscribe to User UID: ${ownerUid}`,
|
|
103
104
|
{
|
|
104
105
|
method,
|
|
105
106
|
botUid,
|
|
106
107
|
ownerUid,
|
|
107
|
-
translationConfig,
|
|
108
|
+
translationConfig: translationConfig ?? null,
|
|
108
109
|
},
|
|
109
110
|
);
|
|
110
111
|
const response = await fetch(`${STT_API_URL}/${method}`, {
|
|
@@ -146,10 +147,10 @@ const useSTTAPI = (): IuseSTTAPI => {
|
|
|
146
147
|
logger.error(
|
|
147
148
|
LogSource.NetworkRest,
|
|
148
149
|
'stt',
|
|
149
|
-
|
|
150
|
-
errorPayload,
|
|
150
|
+
`${TRANSCRIPT_JOURNEY} STT API Failure - Called ${method}`,
|
|
151
|
+
errorPayload ?? {message},
|
|
151
152
|
{
|
|
152
|
-
responseData: res,
|
|
153
|
+
responseData: res ?? null,
|
|
153
154
|
httpStatus,
|
|
154
155
|
requestId,
|
|
155
156
|
startReqTs,
|
|
@@ -172,9 +173,9 @@ const useSTTAPI = (): IuseSTTAPI => {
|
|
|
172
173
|
logger.log(
|
|
173
174
|
LogSource.NetworkRest,
|
|
174
175
|
'stt',
|
|
175
|
-
|
|
176
|
+
`${TRANSCRIPT_JOURNEY} STT API Success - Called ${method}`,
|
|
176
177
|
{
|
|
177
|
-
responseData: res,
|
|
178
|
+
responseData: res ?? null,
|
|
178
179
|
httpStatus,
|
|
179
180
|
requestId,
|
|
180
181
|
startReqTs,
|
|
@@ -194,8 +195,8 @@ const useSTTAPI = (): IuseSTTAPI => {
|
|
|
194
195
|
logger.error(
|
|
195
196
|
LogSource.NetworkRest,
|
|
196
197
|
'stt',
|
|
197
|
-
|
|
198
|
-
error,
|
|
198
|
+
`${TRANSCRIPT_JOURNEY} STT API Failure - Called ${method}`,
|
|
199
|
+
error ?? null,
|
|
199
200
|
{
|
|
200
201
|
requestId,
|
|
201
202
|
startReqTs,
|
|
@@ -235,14 +236,14 @@ const useSTTAPI = (): IuseSTTAPI => {
|
|
|
235
236
|
logger.log(
|
|
236
237
|
LogSource.NetworkRest,
|
|
237
238
|
'stt',
|
|
238
|
-
|
|
239
|
+
`${TRANSCRIPT_JOURNEY} Retrying STT start after transient failure`,
|
|
239
240
|
{
|
|
240
241
|
attempt,
|
|
241
242
|
maxAttempts: STT_START_MAX_ATTEMPTS,
|
|
242
243
|
retryDelayMs,
|
|
243
244
|
botUid,
|
|
244
|
-
httpStatus: result.httpStatus,
|
|
245
|
-
errorCode: result.error?.code,
|
|
245
|
+
httpStatus: result.httpStatus ?? null,
|
|
246
|
+
errorCode: result.error?.code ?? null,
|
|
246
247
|
},
|
|
247
248
|
);
|
|
248
249
|
await wait(retryDelayMs);
|