@memori.ai/memori-react 1.0.0-alpha.21 → 1.0.0-alpha.23
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/CHANGELOG.md +19 -0
- package/dist/components/ChatInputs/ChatInputs.js +4 -1
- package/dist/components/ChatInputs/ChatInputs.js.map +1 -1
- package/dist/components/MemoriWidget/MemoriWidget.js +165 -139
- package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/dist/components/StartPanel/StartPanel.js +1 -0
- package/dist/components/StartPanel/StartPanel.js.map +1 -1
- package/esm/components/ChatInputs/ChatInputs.js +4 -1
- package/esm/components/ChatInputs/ChatInputs.js.map +1 -1
- package/esm/components/MemoriWidget/MemoriWidget.js +165 -139
- package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/esm/components/StartPanel/StartPanel.js +1 -0
- package/esm/components/StartPanel/StartPanel.js.map +1 -1
- package/package.json +1 -1
- package/src/components/ChatInputs/ChatInputs.tsx +4 -1
- package/src/components/MemoriWidget/MemoriWidget.tsx +201 -175
- package/src/components/StartPanel/StartPanel.tsx +3 -0
|
@@ -31,7 +31,7 @@ import React, {
|
|
|
31
31
|
} from 'react';
|
|
32
32
|
import { useTranslation } from 'react-i18next';
|
|
33
33
|
import memoriApiClient from '@memori.ai/memori-api-client';
|
|
34
|
-
import { AudioContext } from 'standardized-audio-context';
|
|
34
|
+
import { AudioContext, IAudioContext } from 'standardized-audio-context';
|
|
35
35
|
import * as speechSdk from 'microsoft-cognitiveservices-speech-sdk';
|
|
36
36
|
import cx from 'classnames';
|
|
37
37
|
|
|
@@ -143,6 +143,7 @@ let recognizer: SpeechRecognizer | null;
|
|
|
143
143
|
let speechConfig: SpeechConfig;
|
|
144
144
|
let speechSynthesizer: SpeechSynthesizer | null;
|
|
145
145
|
let audioDestination: SpeakerAudioDestination;
|
|
146
|
+
let audioContext: IAudioContext;
|
|
146
147
|
|
|
147
148
|
export interface Props {
|
|
148
149
|
memori: Memori;
|
|
@@ -254,7 +255,7 @@ const MemoriWidget = ({
|
|
|
254
255
|
const [showPositionDrawer, setShowPositionDrawer] = useState(false);
|
|
255
256
|
const [showSettingsDrawer, setShowSettingsDrawer] = useState(false);
|
|
256
257
|
const [muteSpeaker, setMuteSpeaker] = useState(false);
|
|
257
|
-
const [continuousSpeech, setContinuousSpeech] = useState(
|
|
258
|
+
const [continuousSpeech, setContinuousSpeech] = useState(true);
|
|
258
259
|
const [continuousSpeechTimeout, setContinuousSpeechTimeout] = useState(3);
|
|
259
260
|
const [isPlayingAudio, setIsPlayingAudio] = useState(false);
|
|
260
261
|
useEffect(() => {
|
|
@@ -264,7 +265,7 @@ const MemoriWidget = ({
|
|
|
264
265
|
|
|
265
266
|
useEffect(() => {
|
|
266
267
|
setMuteSpeaker(getLocalConfig('muteSpeaker', false));
|
|
267
|
-
setContinuousSpeech(getLocalConfig('continuousSpeech',
|
|
268
|
+
setContinuousSpeech(getLocalConfig('continuousSpeech', true));
|
|
268
269
|
setContinuousSpeechTimeout(getLocalConfig('continuousSpeechTimeout', 3));
|
|
269
270
|
}, []);
|
|
270
271
|
|
|
@@ -379,6 +380,7 @@ const MemoriWidget = ({
|
|
|
379
380
|
media: currentState.media,
|
|
380
381
|
fromUser: false,
|
|
381
382
|
});
|
|
383
|
+
speak(currentState.emission);
|
|
382
384
|
}
|
|
383
385
|
} else {
|
|
384
386
|
console.error(response, resp);
|
|
@@ -405,6 +407,7 @@ const MemoriWidget = ({
|
|
|
405
407
|
media: currentState.media,
|
|
406
408
|
fromUser: false,
|
|
407
409
|
});
|
|
410
|
+
speak(currentState.emission);
|
|
408
411
|
}
|
|
409
412
|
} else {
|
|
410
413
|
console.error(response, resp);
|
|
@@ -420,19 +423,25 @@ const MemoriWidget = ({
|
|
|
420
423
|
!instruct &&
|
|
421
424
|
isMultilanguageEnabled
|
|
422
425
|
) {
|
|
423
|
-
translateDialogState(currentState, userLang)
|
|
426
|
+
translateDialogState(currentState, userLang).then(ts => {
|
|
427
|
+
if (ts.emission) {
|
|
428
|
+
speak(ts.emission);
|
|
429
|
+
}
|
|
430
|
+
});
|
|
424
431
|
} else {
|
|
425
432
|
setCurrentDialogState({
|
|
426
433
|
...currentState,
|
|
427
434
|
emission,
|
|
428
435
|
});
|
|
429
436
|
|
|
430
|
-
if (emission)
|
|
437
|
+
if (emission) {
|
|
431
438
|
pushMessage({
|
|
432
439
|
text: emission,
|
|
433
440
|
media: currentState.media,
|
|
434
441
|
fromUser: false,
|
|
435
442
|
});
|
|
443
|
+
speak(emission);
|
|
444
|
+
}
|
|
436
445
|
}
|
|
437
446
|
} else if (response.resultCode === 404) {
|
|
438
447
|
// remove last sent message, will set it as initial
|
|
@@ -447,15 +456,16 @@ const MemoriWidget = ({
|
|
|
447
456
|
instruct && memori.giverPIN ? memori.giverPIN : undefined,
|
|
448
457
|
initialContextVars,
|
|
449
458
|
initialQuestion
|
|
450
|
-
).then(
|
|
459
|
+
).then(state => {
|
|
451
460
|
console.info('session timeout');
|
|
452
|
-
if (sessionID) {
|
|
461
|
+
if (state?.sessionID) {
|
|
453
462
|
setTimeout(() => {
|
|
454
|
-
sendMessage(text, media, sessionID);
|
|
463
|
+
sendMessage(text, media, state?.sessionID);
|
|
455
464
|
}, 500);
|
|
456
465
|
}
|
|
457
466
|
});
|
|
458
467
|
}
|
|
468
|
+
|
|
459
469
|
setMemoriTyping(false);
|
|
460
470
|
};
|
|
461
471
|
|
|
@@ -577,53 +587,6 @@ const MemoriWidget = ({
|
|
|
577
587
|
session.resultCode === 0
|
|
578
588
|
) {
|
|
579
589
|
setSessionId(session.sessionID);
|
|
580
|
-
const language =
|
|
581
|
-
memori.culture?.split('-')?.[0] ?? i18n.language ?? 'IT';
|
|
582
|
-
|
|
583
|
-
if (
|
|
584
|
-
!instruct &&
|
|
585
|
-
isMultilanguageEnabled &&
|
|
586
|
-
userLang.toLowerCase() !== language.toLowerCase()
|
|
587
|
-
) {
|
|
588
|
-
translateDialogState(session.currentState, userLang).then(state => {
|
|
589
|
-
if (state?.emission) {
|
|
590
|
-
history.length <= 1
|
|
591
|
-
? setHistory([
|
|
592
|
-
{
|
|
593
|
-
text: state.emission,
|
|
594
|
-
media: state.media,
|
|
595
|
-
fromUser: false,
|
|
596
|
-
initial: true,
|
|
597
|
-
},
|
|
598
|
-
])
|
|
599
|
-
: pushMessage({
|
|
600
|
-
text: state.emission,
|
|
601
|
-
media: state.media,
|
|
602
|
-
fromUser: false,
|
|
603
|
-
initial: true,
|
|
604
|
-
});
|
|
605
|
-
}
|
|
606
|
-
});
|
|
607
|
-
} else {
|
|
608
|
-
setCurrentDialogState(session.currentState);
|
|
609
|
-
if (session.currentState.emission) {
|
|
610
|
-
history.length <= 1
|
|
611
|
-
? setHistory([
|
|
612
|
-
{
|
|
613
|
-
text: session.currentState.emission,
|
|
614
|
-
media: session.currentState.media,
|
|
615
|
-
fromUser: false,
|
|
616
|
-
initial: true,
|
|
617
|
-
},
|
|
618
|
-
])
|
|
619
|
-
: pushMessage({
|
|
620
|
-
text: session.currentState.emission,
|
|
621
|
-
media: session.currentState.media,
|
|
622
|
-
fromUser: false,
|
|
623
|
-
initial: true,
|
|
624
|
-
});
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
590
|
|
|
628
591
|
if (position) applyPosition(position, session.sessionID);
|
|
629
592
|
|
|
@@ -688,7 +651,10 @@ const MemoriWidget = ({
|
|
|
688
651
|
if (position) applyPosition(position, sessionID);
|
|
689
652
|
|
|
690
653
|
setLoading(false);
|
|
691
|
-
return
|
|
654
|
+
return {
|
|
655
|
+
dialogState: currentState,
|
|
656
|
+
sessionID,
|
|
657
|
+
};
|
|
692
658
|
} else {
|
|
693
659
|
console.error(response);
|
|
694
660
|
message.error(t(getErrori18nKey(response.resultCode)));
|
|
@@ -721,7 +687,6 @@ const MemoriWidget = ({
|
|
|
721
687
|
|
|
722
688
|
if (resultCode === 0) {
|
|
723
689
|
let textResult = 0;
|
|
724
|
-
// console.debug('[APPCONTEXT/CHANGETAG]', currentState);
|
|
725
690
|
if (
|
|
726
691
|
tag !== anonTag &&
|
|
727
692
|
pin &&
|
|
@@ -846,13 +811,18 @@ const MemoriWidget = ({
|
|
|
846
811
|
translateDialogState(
|
|
847
812
|
{ ...currentState, emission: emission },
|
|
848
813
|
userLang
|
|
849
|
-
)
|
|
814
|
+
).then(ts => {
|
|
815
|
+
if (ts.emission) {
|
|
816
|
+
speak(ts.emission);
|
|
817
|
+
}
|
|
818
|
+
});
|
|
850
819
|
} else if (emission && emission.length > 0) {
|
|
851
820
|
pushMessage({
|
|
852
821
|
text: emission,
|
|
853
822
|
media: currentState.media,
|
|
854
823
|
fromUser: false,
|
|
855
824
|
});
|
|
825
|
+
speak(emission);
|
|
856
826
|
setCurrentDialogState(currentState);
|
|
857
827
|
}
|
|
858
828
|
}
|
|
@@ -916,40 +886,19 @@ const MemoriWidget = ({
|
|
|
916
886
|
speechConfig.speechSynthesisOutputFormat =
|
|
917
887
|
speechSdk.SpeechSynthesisOutputFormat.Audio16Khz32KBitRateMonoMp3;
|
|
918
888
|
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
let source = context.createBufferSource();
|
|
932
|
-
source.buffer = buffer;
|
|
933
|
-
source.connect(context.destination);
|
|
934
|
-
} catch (e) {
|
|
935
|
-
console.error(e);
|
|
936
|
-
}
|
|
937
|
-
})
|
|
938
|
-
.catch((e: any) => {
|
|
939
|
-
console.error('error playing intro audio', e);
|
|
940
|
-
});
|
|
941
|
-
}
|
|
889
|
+
audioContext = new AudioContext();
|
|
890
|
+
let buffer = audioContext.createBuffer(1, 10000, 22050);
|
|
891
|
+
let source = audioContext.createBufferSource();
|
|
892
|
+
source.buffer = buffer;
|
|
893
|
+
source.connect(audioContext.destination);
|
|
894
|
+
|
|
895
|
+
audioDestination = new speechSdk.SpeakerAudioDestination();
|
|
896
|
+
let audioConfig = speechSdk.AudioConfig.fromSpeakerOutput(audioDestination);
|
|
897
|
+
speechSynthesizer = new speechSdk.SpeechSynthesizer(
|
|
898
|
+
speechConfig,
|
|
899
|
+
audioConfig
|
|
900
|
+
);
|
|
942
901
|
};
|
|
943
|
-
useEffect(() => {
|
|
944
|
-
return () => {
|
|
945
|
-
if (audioDestination) audioDestination.pause();
|
|
946
|
-
if (speechSynthesizer) {
|
|
947
|
-
speechSynthesizer.close();
|
|
948
|
-
speechSynthesizer = null;
|
|
949
|
-
}
|
|
950
|
-
};
|
|
951
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
952
|
-
}, []);
|
|
953
902
|
|
|
954
903
|
const getTTSVoice = useCallback(
|
|
955
904
|
(lang?: string): string => {
|
|
@@ -1032,8 +981,12 @@ const MemoriWidget = ({
|
|
|
1032
981
|
|
|
1033
982
|
const getCultureCodeByLanguage = (lang?: string): string => {
|
|
1034
983
|
let voice = '';
|
|
1035
|
-
let voiceLang = (
|
|
1036
|
-
|
|
984
|
+
let voiceLang = (
|
|
985
|
+
lang ||
|
|
986
|
+
memori.culture?.split('-')?.[0] ||
|
|
987
|
+
i18n.language ||
|
|
988
|
+
'IT'
|
|
989
|
+
).toUpperCase();
|
|
1037
990
|
switch (voiceLang) {
|
|
1038
991
|
case 'IT':
|
|
1039
992
|
voice = 'it-IT';
|
|
@@ -1121,7 +1074,7 @@ const MemoriWidget = ({
|
|
|
1121
1074
|
// .replace(/qfe/gi, `<sub alias="Quota Filo Erba">QFE</sub>`)
|
|
1122
1075
|
};
|
|
1123
1076
|
|
|
1124
|
-
const speak = (text: string
|
|
1077
|
+
const speak = (text: string): void => {
|
|
1125
1078
|
console.log(
|
|
1126
1079
|
AZURE_COGNITIVE_SERVICES_TTS_KEY,
|
|
1127
1080
|
hasUserActivatedSpeak,
|
|
@@ -1129,59 +1082,62 @@ const MemoriWidget = ({
|
|
|
1129
1082
|
);
|
|
1130
1083
|
if (!AZURE_COGNITIVE_SERVICES_TTS_KEY) return;
|
|
1131
1084
|
|
|
1132
|
-
if (
|
|
1085
|
+
if (listening) {
|
|
1086
|
+
stopListening();
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
if (preview) return;
|
|
1090
|
+
|
|
1133
1091
|
if (audioDestination) audioDestination.pause();
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1092
|
+
|
|
1093
|
+
let isSafari =
|
|
1094
|
+
window.navigator.userAgent.includes('Safari') &&
|
|
1095
|
+
!window.navigator.userAgent.includes('Chrome');
|
|
1096
|
+
let isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
|
|
1097
|
+
if (isIOS && isSafari) {
|
|
1098
|
+
audioContext.suspend();
|
|
1099
|
+
} else if (audioContext.state === 'suspended') {
|
|
1100
|
+
stopAudio();
|
|
1101
|
+
audioContext = new AudioContext();
|
|
1102
|
+
let buffer = audioContext.createBuffer(1, 10000, 22050);
|
|
1103
|
+
let source = audioContext.createBufferSource();
|
|
1104
|
+
source.buffer = buffer;
|
|
1105
|
+
source.connect(audioContext.destination);
|
|
1137
1106
|
}
|
|
1138
1107
|
|
|
1139
|
-
if (
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1108
|
+
if (!speechSynthesizer) {
|
|
1109
|
+
audioDestination = new speechSdk.SpeakerAudioDestination();
|
|
1110
|
+
let audioConfig =
|
|
1111
|
+
speechSdk.AudioConfig.fromSpeakerOutput(audioDestination);
|
|
1112
|
+
speechSynthesizer = new speechSdk.SpeechSynthesizer(
|
|
1113
|
+
speechConfig,
|
|
1114
|
+
audioConfig
|
|
1115
|
+
);
|
|
1147
1116
|
}
|
|
1148
1117
|
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1118
|
+
if (muteSpeaker) {
|
|
1119
|
+
// trigger start continuous listening if set, see MemoriChat
|
|
1120
|
+
if (continuousSpeech) {
|
|
1121
|
+
setListeningTimeout();
|
|
1122
|
+
}
|
|
1123
|
+
return;
|
|
1124
|
+
}
|
|
1155
1125
|
|
|
1156
1126
|
audioDestination.onAudioEnd = () => {
|
|
1157
1127
|
setIsPlayingAudio(false);
|
|
1158
1128
|
|
|
1159
|
-
if (
|
|
1160
|
-
// trigger start continuous listening if set
|
|
1129
|
+
if (continuousSpeech) {
|
|
1130
|
+
// trigger start continuous listening if set
|
|
1161
1131
|
document.dispatchEvent(new Event('endSpeakStartListen'));
|
|
1162
1132
|
}
|
|
1163
1133
|
};
|
|
1164
1134
|
|
|
1165
|
-
// speechSynthesizer.visemeReceived = function (s, e) {
|
|
1166
|
-
// window.console.log(
|
|
1167
|
-
// '(Viseme), Audio offset: ' +
|
|
1168
|
-
// e.audioOffset / 10000 +
|
|
1169
|
-
// 'ms. Viseme ID: ' +
|
|
1170
|
-
// e.visemeId,
|
|
1171
|
-
// e,
|
|
1172
|
-
// );
|
|
1173
|
-
|
|
1174
|
-
// // `Animation` is an xml string for SVG or a json string for blend shapes
|
|
1175
|
-
// // var animation = e.Animation;
|
|
1176
|
-
// };
|
|
1177
|
-
|
|
1178
1135
|
setIsPlayingAudio(true);
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
// window.speechSynthesis.speak(new SpeechSynthesisUtterance(text));
|
|
1136
|
+
|
|
1137
|
+
speechSynthesizer.synthesisCompleted = (s, e) => {
|
|
1138
|
+
console.log('synthesisCompleted', s, e);
|
|
1139
|
+
setIsPlayingAudio(false);
|
|
1140
|
+
};
|
|
1185
1141
|
speechSynthesizer.speakSsmlAsync(
|
|
1186
1142
|
`<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xmlns:mstts="https://www.w3.org/2001/mstts" xmlns:emo="http://www.w3.org/2009/10/emotionml" xml:lang="${getCultureCodeByLanguage(
|
|
1187
1143
|
userLang
|
|
@@ -1191,7 +1147,19 @@ const MemoriWidget = ({
|
|
|
1191
1147
|
)}</s></voice></speak>`,
|
|
1192
1148
|
result => {
|
|
1193
1149
|
if (result) {
|
|
1150
|
+
console.log('result', result);
|
|
1194
1151
|
try {
|
|
1152
|
+
audioContext.decodeAudioData(result.audioData, function (buffer) {
|
|
1153
|
+
const source = audioContext.createBufferSource();
|
|
1154
|
+
source.buffer = buffer;
|
|
1155
|
+
source.connect(audioContext.destination);
|
|
1156
|
+
|
|
1157
|
+
if (history.length < 1 || (isSafari && isIOS)) {
|
|
1158
|
+
source.start(0);
|
|
1159
|
+
}
|
|
1160
|
+
});
|
|
1161
|
+
audioContext.resume();
|
|
1162
|
+
|
|
1195
1163
|
if (speechSynthesizer) {
|
|
1196
1164
|
speechSynthesizer.close();
|
|
1197
1165
|
speechSynthesizer = null;
|
|
@@ -1200,9 +1168,14 @@ const MemoriWidget = ({
|
|
|
1200
1168
|
console.error('speak error: ', e);
|
|
1201
1169
|
window.speechSynthesis.speak(new SpeechSynthesisUtterance(text));
|
|
1202
1170
|
setIsPlayingAudio(false);
|
|
1171
|
+
|
|
1172
|
+
if (speechSynthesizer) {
|
|
1173
|
+
speechSynthesizer.close();
|
|
1174
|
+
speechSynthesizer = null;
|
|
1175
|
+
}
|
|
1203
1176
|
}
|
|
1204
1177
|
} else {
|
|
1205
|
-
|
|
1178
|
+
audioContext.resume();
|
|
1206
1179
|
setIsPlayingAudio(false);
|
|
1207
1180
|
}
|
|
1208
1181
|
},
|
|
@@ -1214,12 +1187,20 @@ const MemoriWidget = ({
|
|
|
1214
1187
|
);
|
|
1215
1188
|
|
|
1216
1189
|
setIsPlayingAudio(false);
|
|
1190
|
+
setMemoriTyping(false);
|
|
1217
1191
|
};
|
|
1218
1192
|
const stopAudio = () => {
|
|
1219
1193
|
if (speechSynthesizer) {
|
|
1220
1194
|
speechSynthesizer.close();
|
|
1221
1195
|
speechSynthesizer = null;
|
|
1222
1196
|
}
|
|
1197
|
+
if (audioContext) {
|
|
1198
|
+
audioContext.close();
|
|
1199
|
+
}
|
|
1200
|
+
if (audioDestination) {
|
|
1201
|
+
audioDestination.pause();
|
|
1202
|
+
audioDestination.close();
|
|
1203
|
+
}
|
|
1223
1204
|
};
|
|
1224
1205
|
|
|
1225
1206
|
/**
|
|
@@ -1271,10 +1252,7 @@ const MemoriWidget = ({
|
|
|
1271
1252
|
useEffect(() => {
|
|
1272
1253
|
resetListeningTimeout();
|
|
1273
1254
|
resetInteractionTimeout();
|
|
1274
|
-
|
|
1275
|
-
const transcriptMessage = stripDuplicates(transcript);
|
|
1276
|
-
if (transcriptMessage.length > 0) setUserMessage(transcriptMessage);
|
|
1277
|
-
}
|
|
1255
|
+
|
|
1278
1256
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1279
1257
|
}, [transcript]);
|
|
1280
1258
|
|
|
@@ -1317,7 +1295,13 @@ const MemoriWidget = ({
|
|
|
1317
1295
|
setListening(true);
|
|
1318
1296
|
recognizer.recognized = (_s, e) => {
|
|
1319
1297
|
if (e.result.reason === speechSdk.ResultReason.RecognizedSpeech) {
|
|
1320
|
-
|
|
1298
|
+
let transcript = e.result.text;
|
|
1299
|
+
setTranscript(transcript || '');
|
|
1300
|
+
if (transcript?.length > 0) {
|
|
1301
|
+
const transcriptMessage = stripDuplicates(transcript);
|
|
1302
|
+
if (transcriptMessage.length > 0)
|
|
1303
|
+
setUserMessage(transcriptMessage);
|
|
1304
|
+
}
|
|
1321
1305
|
} else if (e.result.reason === speechSdk.ResultReason.NoMatch) {
|
|
1322
1306
|
console.debug('NOMATCH: Speech could not be recognized.');
|
|
1323
1307
|
}
|
|
@@ -1335,7 +1319,7 @@ const MemoriWidget = ({
|
|
|
1335
1319
|
};
|
|
1336
1320
|
|
|
1337
1321
|
recognizer.sessionStopped = (_s, _e) => {
|
|
1338
|
-
|
|
1322
|
+
stopListening();
|
|
1339
1323
|
};
|
|
1340
1324
|
recognizer.startContinuousRecognitionAsync();
|
|
1341
1325
|
})
|
|
@@ -1349,8 +1333,8 @@ const MemoriWidget = ({
|
|
|
1349
1333
|
recognizer.stopContinuousRecognitionAsync();
|
|
1350
1334
|
recognizer.close();
|
|
1351
1335
|
recognizer = null;
|
|
1352
|
-
setListening(false);
|
|
1353
1336
|
}
|
|
1337
|
+
setListening(false);
|
|
1354
1338
|
};
|
|
1355
1339
|
const clearListening = () => {
|
|
1356
1340
|
setHasUserActivatedListening(false);
|
|
@@ -1374,19 +1358,6 @@ const MemoriWidget = ({
|
|
|
1374
1358
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1375
1359
|
}, [currentDialogState?.state]);
|
|
1376
1360
|
|
|
1377
|
-
useEffect(() => {
|
|
1378
|
-
if (
|
|
1379
|
-
hasUserActivatedSpeak &&
|
|
1380
|
-
!preview &&
|
|
1381
|
-
!muteSpeaker &&
|
|
1382
|
-
history.length > 0 &&
|
|
1383
|
-
currentDialogState?.emission
|
|
1384
|
-
) {
|
|
1385
|
-
speak(currentDialogState.emission, currentDialogState.state !== 'Z0');
|
|
1386
|
-
}
|
|
1387
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1388
|
-
}, [currentDialogState, hasUserActivatedSpeak]);
|
|
1389
|
-
|
|
1390
1361
|
/**
|
|
1391
1362
|
* Speech recognition event handlers
|
|
1392
1363
|
*/
|
|
@@ -1658,7 +1629,19 @@ const MemoriWidget = ({
|
|
|
1658
1629
|
const sessionID = session?.sessionID || sessionId;
|
|
1659
1630
|
const dialogState = session?.dialogState || currentDialogState;
|
|
1660
1631
|
setClickedStart(true);
|
|
1661
|
-
|
|
1632
|
+
|
|
1633
|
+
let memoriAudioElement = document.getElementById(
|
|
1634
|
+
'memori-audio'
|
|
1635
|
+
) as HTMLAudioElement;
|
|
1636
|
+
let isSafari =
|
|
1637
|
+
window.navigator.userAgent.includes('Safari') &&
|
|
1638
|
+
!window.navigator.userAgent.includes('Chrome');
|
|
1639
|
+
if (memoriAudioElement && isSafari) {
|
|
1640
|
+
memoriAudioElement.muted = false;
|
|
1641
|
+
memoriAudioElement.play().catch((e: any) => {
|
|
1642
|
+
console.error('error playing intro audio', e);
|
|
1643
|
+
});
|
|
1644
|
+
}
|
|
1662
1645
|
|
|
1663
1646
|
if (
|
|
1664
1647
|
(!sessionID &&
|
|
@@ -1682,7 +1665,7 @@ const MemoriWidget = ({
|
|
|
1682
1665
|
initialContextVars,
|
|
1683
1666
|
initialQuestion,
|
|
1684
1667
|
});
|
|
1685
|
-
onClickStart(session || undefined);
|
|
1668
|
+
await onClickStart(session || undefined);
|
|
1686
1669
|
return;
|
|
1687
1670
|
} else if (initialSessionID) {
|
|
1688
1671
|
// check if session is valid and not expired
|
|
@@ -1692,7 +1675,7 @@ const MemoriWidget = ({
|
|
|
1692
1675
|
setGotErrorInOpening(true);
|
|
1693
1676
|
setSessionId(undefined);
|
|
1694
1677
|
setClickedStart(false);
|
|
1695
|
-
onClickStart();
|
|
1678
|
+
await onClickStart();
|
|
1696
1679
|
return;
|
|
1697
1680
|
}
|
|
1698
1681
|
|
|
@@ -1722,9 +1705,15 @@ const MemoriWidget = ({
|
|
|
1722
1705
|
);
|
|
1723
1706
|
|
|
1724
1707
|
if (session && session.resultCode === 0) {
|
|
1725
|
-
translateDialogState(session.currentState, userLang)
|
|
1726
|
-
|
|
1727
|
-
|
|
1708
|
+
translateDialogState(session.currentState, userLang)
|
|
1709
|
+
.then(ts => {
|
|
1710
|
+
if (ts.emission) {
|
|
1711
|
+
speak(ts.emission);
|
|
1712
|
+
}
|
|
1713
|
+
})
|
|
1714
|
+
.finally(() => {
|
|
1715
|
+
setHasUserActivatedSpeak(true);
|
|
1716
|
+
});
|
|
1728
1717
|
} else {
|
|
1729
1718
|
console.error('session #1', session);
|
|
1730
1719
|
throw new Error('No session');
|
|
@@ -1762,9 +1751,15 @@ const MemoriWidget = ({
|
|
|
1762
1751
|
);
|
|
1763
1752
|
|
|
1764
1753
|
if (session && session.resultCode === 0) {
|
|
1765
|
-
translateDialogState(session.currentState, userLang)
|
|
1766
|
-
|
|
1767
|
-
|
|
1754
|
+
translateDialogState(session.currentState, userLang)
|
|
1755
|
+
.then(ts => {
|
|
1756
|
+
if (ts.emission) {
|
|
1757
|
+
speak(ts.emission);
|
|
1758
|
+
}
|
|
1759
|
+
})
|
|
1760
|
+
.finally(() => {
|
|
1761
|
+
setHasUserActivatedSpeak(true);
|
|
1762
|
+
});
|
|
1768
1763
|
} else {
|
|
1769
1764
|
console.error('session #4', session);
|
|
1770
1765
|
throw new Error('No session');
|
|
@@ -1802,9 +1797,15 @@ const MemoriWidget = ({
|
|
|
1802
1797
|
);
|
|
1803
1798
|
|
|
1804
1799
|
if (session && session.resultCode === 0) {
|
|
1805
|
-
translateDialogState(session.currentState, userLang)
|
|
1806
|
-
|
|
1807
|
-
|
|
1800
|
+
translateDialogState(session.currentState, userLang)
|
|
1801
|
+
.then(ts => {
|
|
1802
|
+
if (ts.emission) {
|
|
1803
|
+
speak(ts.emission);
|
|
1804
|
+
}
|
|
1805
|
+
})
|
|
1806
|
+
.finally(() => {
|
|
1807
|
+
setHasUserActivatedSpeak(true);
|
|
1808
|
+
});
|
|
1808
1809
|
} else {
|
|
1809
1810
|
console.error('session #7', session);
|
|
1810
1811
|
throw new Error('No session');
|
|
@@ -1825,18 +1826,30 @@ const MemoriWidget = ({
|
|
|
1825
1826
|
}
|
|
1826
1827
|
} else {
|
|
1827
1828
|
// no need to change tag
|
|
1828
|
-
translateDialogState(currentState, userLang)
|
|
1829
|
-
|
|
1830
|
-
|
|
1829
|
+
translateDialogState(currentState, userLang)
|
|
1830
|
+
.then(ts => {
|
|
1831
|
+
if (ts.emission) {
|
|
1832
|
+
speak(ts.emission);
|
|
1833
|
+
}
|
|
1834
|
+
})
|
|
1835
|
+
.finally(() => {
|
|
1836
|
+
setHasUserActivatedSpeak(true);
|
|
1837
|
+
});
|
|
1831
1838
|
}
|
|
1832
1839
|
} else {
|
|
1833
1840
|
// reset history
|
|
1834
1841
|
setHistory([]);
|
|
1835
1842
|
|
|
1836
1843
|
// everything is fine, just translate dialog state and activate chat
|
|
1837
|
-
translateDialogState(dialogState!, userLang)
|
|
1838
|
-
|
|
1839
|
-
|
|
1844
|
+
translateDialogState(dialogState!, userLang)
|
|
1845
|
+
.then(ts => {
|
|
1846
|
+
if (ts.emission) {
|
|
1847
|
+
speak(ts.emission);
|
|
1848
|
+
}
|
|
1849
|
+
})
|
|
1850
|
+
.finally(() => {
|
|
1851
|
+
setHasUserActivatedSpeak(true);
|
|
1852
|
+
});
|
|
1840
1853
|
}
|
|
1841
1854
|
};
|
|
1842
1855
|
|
|
@@ -1890,7 +1903,18 @@ const MemoriWidget = ({
|
|
|
1890
1903
|
setShowPositionDrawer={setShowPositionDrawer}
|
|
1891
1904
|
setShowSettingsDrawer={setShowSettingsDrawer}
|
|
1892
1905
|
speakerMuted={muteSpeaker}
|
|
1893
|
-
setSpeakerMuted={
|
|
1906
|
+
setSpeakerMuted={mute => {
|
|
1907
|
+
setMuteSpeaker(mute);
|
|
1908
|
+
if (mute) {
|
|
1909
|
+
stopAudio();
|
|
1910
|
+
} else {
|
|
1911
|
+
audioContext = new AudioContext();
|
|
1912
|
+
let buffer = audioContext.createBuffer(1, 10000, 22050);
|
|
1913
|
+
let source = audioContext.createBufferSource();
|
|
1914
|
+
source.buffer = buffer;
|
|
1915
|
+
source.connect(audioContext.destination);
|
|
1916
|
+
}
|
|
1917
|
+
}}
|
|
1894
1918
|
showSettings={showSettings}
|
|
1895
1919
|
hasUserActivatedSpeak={hasUserActivatedSpeak}
|
|
1896
1920
|
/>
|
|
@@ -2070,9 +2094,9 @@ const MemoriWidget = ({
|
|
|
2070
2094
|
initialContextVars,
|
|
2071
2095
|
initialQuestion
|
|
2072
2096
|
)
|
|
2073
|
-
.then(
|
|
2097
|
+
.then(state => {
|
|
2074
2098
|
setAuthModalState(null);
|
|
2075
|
-
|
|
2099
|
+
onClickStart(state || undefined);
|
|
2076
2100
|
})
|
|
2077
2101
|
.catch(() => {
|
|
2078
2102
|
setAuthModalState(null);
|
|
@@ -2119,6 +2143,7 @@ const MemoriWidget = ({
|
|
|
2119
2143
|
media: currentState.media,
|
|
2120
2144
|
fromUser: false,
|
|
2121
2145
|
});
|
|
2146
|
+
speak(currentState.emission);
|
|
2122
2147
|
}
|
|
2123
2148
|
} else {
|
|
2124
2149
|
console.error(resp, currentState, medium);
|
|
@@ -2174,6 +2199,7 @@ const MemoriWidget = ({
|
|
|
2174
2199
|
media: currentState.media,
|
|
2175
2200
|
fromUser: false,
|
|
2176
2201
|
});
|
|
2202
|
+
speak(currentState.emission);
|
|
2177
2203
|
}
|
|
2178
2204
|
} else {
|
|
2179
2205
|
console.error(resp, currentState, medium);
|
|
@@ -213,6 +213,9 @@ const StartPanel: React.FC<Props> = ({
|
|
|
213
213
|
disabled={!!memori.blockedUntil && !memori.isGiver}
|
|
214
214
|
loading={clickedStart}
|
|
215
215
|
onClick={_e => {
|
|
216
|
+
speechSynthesis.speak(
|
|
217
|
+
new SpeechSynthesisUtterance('') // This is needed to enable the speech synthesis on iOS
|
|
218
|
+
);
|
|
216
219
|
if (initializeTTS) initializeTTS();
|
|
217
220
|
if (onClickStart) onClickStart();
|
|
218
221
|
}}
|