@davi-ai/retorik-framework 4.0.4 → 5.0.1

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.
Files changed (84) hide show
  1. package/README.md +13 -0
  2. package/dist/{AttachmentDetail.637ad44f.js → AttachmentDetail.3f9c113d.js} +15 -6
  3. package/dist/AttachmentDetail.3f9c113d.js.map +1 -0
  4. package/dist/{AttachmentDetail.83788045.js → AttachmentDetail.57c5579a.js} +15 -6
  5. package/dist/AttachmentDetail.57c5579a.js.map +1 -0
  6. package/dist/{CustomView.bf84bdf3.js → CustomView.6b96f53f.js} +8 -4
  7. package/dist/CustomView.6b96f53f.js.map +1 -0
  8. package/dist/{CustomView.9930c671.js → CustomView.b32a608f.js} +8 -4
  9. package/dist/CustomView.b32a608f.js.map +1 -0
  10. package/dist/{Emergency.1112c09f.js → Emergency.43605d14.js} +11 -2
  11. package/dist/Emergency.43605d14.js.map +1 -0
  12. package/dist/{Emergency.d5810ff2.js → Emergency.f1287bd5.js} +11 -2
  13. package/dist/Emergency.f1287bd5.js.map +1 -0
  14. package/dist/FullScreenImage.17df27bf.js.map +1 -1
  15. package/dist/FullScreenImage.99e19e10.js.map +1 -1
  16. package/dist/{HistoryList.3b4b1ffb.js → HistoryList.c19556a7.js} +8 -2
  17. package/dist/HistoryList.c19556a7.js.map +1 -0
  18. package/dist/{HistoryList.e5c01f21.js → HistoryList.e7262d62.js} +8 -2
  19. package/dist/HistoryList.e7262d62.js.map +1 -0
  20. package/dist/{LanguageChoice.1d866cfa.js → LanguageChoice.54fae1dc.js} +19 -8
  21. package/dist/LanguageChoice.54fae1dc.js.map +1 -0
  22. package/dist/{LanguageChoice.cce361a3.js → LanguageChoice.6e8b74f6.js} +19 -8
  23. package/dist/LanguageChoice.6e8b74f6.js.map +1 -0
  24. package/dist/LittleWeatherContainer.7e41105e.js.map +1 -1
  25. package/dist/LittleWeatherContainer.ee087e22.js.map +1 -1
  26. package/dist/{MapContainer.14c28128.js → MapContainer.25c8f4b4.js} +20 -5
  27. package/dist/MapContainer.25c8f4b4.js.map +1 -0
  28. package/dist/{MapContainer.f22ad81f.js → MapContainer.d00ab5b2.js} +20 -5
  29. package/dist/MapContainer.d00ab5b2.js.map +1 -0
  30. package/dist/{NewsContainer.d9de093c.js → NewsContainer.a39630c3.js} +33 -26
  31. package/dist/NewsContainer.a39630c3.js.map +1 -0
  32. package/dist/{NewsContainer.463e74de.js → NewsContainer.ec15c3bb.js} +33 -26
  33. package/dist/NewsContainer.ec15c3bb.js.map +1 -0
  34. package/dist/PrintingPreview.375e62b0.js.map +1 -1
  35. package/dist/PrintingPreview.c0ca7706.js.map +1 -1
  36. package/dist/RecognitionManager.c58b8a3d.js +298 -0
  37. package/dist/RecognitionManager.c58b8a3d.js.map +1 -0
  38. package/dist/RecognitionManager.cdfb39fc.js +314 -0
  39. package/dist/RecognitionManager.cdfb39fc.js.map +1 -0
  40. package/dist/SpiritEngineWrapper.21ea10d4.js.map +1 -1
  41. package/dist/SpiritEngineWrapper.39627300.js.map +1 -1
  42. package/dist/SynthesisPonyfillManager.10888d6d.js +888 -0
  43. package/dist/SynthesisPonyfillManager.10888d6d.js.map +1 -0
  44. package/dist/SynthesisPonyfillManager.f9f9a915.js +920 -0
  45. package/dist/SynthesisPonyfillManager.f9f9a915.js.map +1 -0
  46. package/dist/{ThreeJsWrapper.dd4906ff.js → ThreeJsWrapper.0285d280.js} +24 -12
  47. package/dist/ThreeJsWrapper.0285d280.js.map +1 -0
  48. package/dist/{ThreeJsWrapper.c02a077f.js → ThreeJsWrapper.ad746197.js} +24 -11
  49. package/dist/ThreeJsWrapper.ad746197.js.map +1 -0
  50. package/dist/{VeilleManager.f3bafdec.js → VeilleManager.0b3f2454.js} +11 -13
  51. package/dist/VeilleManager.0b3f2454.js.map +1 -0
  52. package/dist/{VeilleManager.85967e7c.js → VeilleManager.340a7825.js} +11 -13
  53. package/dist/VeilleManager.340a7825.js.map +1 -0
  54. package/dist/{Weather.7e945307.js → Weather.abc13d88.js} +9 -3
  55. package/dist/Weather.abc13d88.js.map +1 -0
  56. package/dist/{Weather.e81b7205.js → Weather.b9d9f82e.js} +9 -3
  57. package/dist/Weather.b9d9f82e.js.map +1 -0
  58. package/dist/index.d.ts +21 -951
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +52952 -33750
  61. package/dist/index.js.map +1 -1
  62. package/dist/index.modern.js +53468 -34269
  63. package/dist/index.modern.js.map +1 -1
  64. package/package.json +21 -21
  65. package/dist/AttachmentDetail.637ad44f.js.map +0 -1
  66. package/dist/AttachmentDetail.83788045.js.map +0 -1
  67. package/dist/CustomView.9930c671.js.map +0 -1
  68. package/dist/CustomView.bf84bdf3.js.map +0 -1
  69. package/dist/Emergency.1112c09f.js.map +0 -1
  70. package/dist/Emergency.d5810ff2.js.map +0 -1
  71. package/dist/HistoryList.3b4b1ffb.js.map +0 -1
  72. package/dist/HistoryList.e5c01f21.js.map +0 -1
  73. package/dist/LanguageChoice.1d866cfa.js.map +0 -1
  74. package/dist/LanguageChoice.cce361a3.js.map +0 -1
  75. package/dist/MapContainer.14c28128.js.map +0 -1
  76. package/dist/MapContainer.f22ad81f.js.map +0 -1
  77. package/dist/NewsContainer.463e74de.js.map +0 -1
  78. package/dist/NewsContainer.d9de093c.js.map +0 -1
  79. package/dist/ThreeJsWrapper.c02a077f.js.map +0 -1
  80. package/dist/ThreeJsWrapper.dd4906ff.js.map +0 -1
  81. package/dist/VeilleManager.85967e7c.js.map +0 -1
  82. package/dist/VeilleManager.f3bafdec.js.map +0 -1
  83. package/dist/Weather.7e945307.js.map +0 -1
  84. package/dist/Weather.e81b7205.js.map +0 -1
@@ -0,0 +1,920 @@
1
+ var $4yQHp$reactjsxruntime = require("react/jsx-runtime");
2
+ var $4yQHp$react = require("react");
3
+ var $4yQHp$daviaiwebspeechcognitiveservicesdavi = require("@davi-ai/web-speech-cognitive-services-davi");
4
+ var $4yQHp$reactredux = require("react-redux");
5
+ var $4yQHp$daviaispeechmarkdowndavijs = require("@davi-ai/speechmarkdown-davi-js");
6
+
7
+
8
+ function $parcel$interopDefault(a) {
9
+ return a && a.__esModule ? a.default : a;
10
+ }
11
+
12
+ function $parcel$defineInteropFlag(a) {
13
+ Object.defineProperty(a, '__esModule', {value: true, configurable: true});
14
+ }
15
+
16
+ function $parcel$export(e, n, v, s) {
17
+ Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
18
+ }
19
+
20
+ var $parcel$global =
21
+ typeof globalThis !== 'undefined'
22
+ ? globalThis
23
+ : typeof self !== 'undefined'
24
+ ? self
25
+ : typeof window !== 'undefined'
26
+ ? window
27
+ : typeof global !== 'undefined'
28
+ ? global
29
+ : {};
30
+ var parcelRequire = $parcel$global["parcelRequirea39d"];
31
+ var parcelRegister = parcelRequire.register;
32
+ parcelRegister("eRUoO", function(module, exports) {
33
+
34
+ $parcel$defineInteropFlag(module.exports);
35
+
36
+ $parcel$export(module.exports, "default", () => $fe06f31a645aa3a1$export$2e2bcd8739ae039);
37
+
38
+
39
+
40
+
41
+
42
+ var $kpW3P = parcelRequire("kpW3P");
43
+
44
+ var $ieTrG = parcelRequire("ieTrG");
45
+
46
+ var $gvTLl = parcelRequire("gvTLl");
47
+
48
+ var $iiIh5 = parcelRequire("iiIh5");
49
+ const $fe06f31a645aa3a1$var$SynthesisPonyfillManager = ({ isRetorikNews: isRetorikNews })=>{
50
+ const dispatch = (0, $4yQHp$reactredux.useDispatch)();
51
+ const customVoice = (0, $4yQHp$reactredux.useSelector)((state)=>state.speechReducer.customVoice);
52
+ const ponyfillCredentials = (0, $4yQHp$reactredux.useSelector)((state)=>state.speechReducer.ponyfillCredentials);
53
+ const locale = (0, $4yQHp$reactredux.useSelector)((state)=>state.localeReducer.locale);
54
+ const agentData = (0, $4yQHp$reactredux.useSelector)((state)=>state.retorikReducer.agentData);
55
+ const [ponyfillCreated, setPonyfillCreated] = (0, $4yQHp$react.useState)(false);
56
+ const ponyfillRef = (0, $4yQHp$react.useRef)(undefined);
57
+ const refreshTimerRef = (0, $4yQHp$react.useRef)(null);
58
+ /**
59
+ * Async function to retrieve a new token and assign it to the speechConfig inside ponyfill.speechSynthesis
60
+ * @param {string} region
61
+ * @param {string} key
62
+ */ const refreshTokenInNineMinutes = async (region, key)=>{
63
+ // A token is valid during 10 minutes, let's refresh it after 9 minutes
64
+ refreshTimerRef.current = setTimeout(async ()=>{
65
+ var _ponyfillRef_current_speechSynthesis, _ponyfillRef_current;
66
+ const token = await (0, $ieTrG.fetchSpeechServicesToken)(region, key);
67
+ if (token && ((_ponyfillRef_current = ponyfillRef.current) === null || _ponyfillRef_current === void 0 ? void 0 : (_ponyfillRef_current_speechSynthesis = _ponyfillRef_current.speechSynthesis) === null || _ponyfillRef_current_speechSynthesis === void 0 ? void 0 : _ponyfillRef_current_speechSynthesis.speechConfig)) {
68
+ ponyfillRef.current.speechSynthesis.speechConfig.authorizationToken = token;
69
+ refreshTokenInNineMinutes(region, key);
70
+ }
71
+ }, 540000) // 9 minutes
72
+ ;
73
+ };
74
+ /**
75
+ * Fetch speech synthesis token and create the ponyfill containing all data
76
+ * @param {string} region
77
+ * @param {string} key
78
+ */ const fetchTokenAndCreatePonyfill = async (region, key)=>{
79
+ const token = await (0, $ieTrG.fetchSpeechServicesToken)(region, key);
80
+ if (token) {
81
+ ponyfillRef.current = (0, $4yQHp$daviaiwebspeechcognitiveservicesdavi.createSpeechSynthesisPonyfill)({
82
+ credentials: {
83
+ region: ponyfillCredentials === null || ponyfillCredentials === void 0 ? void 0 : ponyfillCredentials.region,
84
+ authorizationToken: token
85
+ }
86
+ });
87
+ // Launch token refresh after ponyfill creation
88
+ refreshTokenInNineMinutes(region, key);
89
+ setPonyfillCreated(true);
90
+ }
91
+ };
92
+ (0, $4yQHp$react.useEffect)(()=>{
93
+ if ((ponyfillCredentials === null || ponyfillCredentials === void 0 ? void 0 : ponyfillCredentials.authorizationToken) && ponyfillCredentials.region) {
94
+ const data = {
95
+ credentials: ponyfillCredentials
96
+ };
97
+ ponyfillRef.current = (0, $4yQHp$daviaiwebspeechcognitiveservicesdavi.createSpeechSynthesisPonyfill)(data);
98
+ setPonyfillCreated(true);
99
+ } else if ((ponyfillCredentials === null || ponyfillCredentials === void 0 ? void 0 : ponyfillCredentials.subscriptionKey) && ponyfillCredentials.region) fetchTokenAndCreatePonyfill(ponyfillCredentials.region, ponyfillCredentials.subscriptionKey);
100
+ else if (ponyfillCredentials === null || ponyfillCredentials === void 0 ? void 0 : ponyfillCredentials.speechSynthesisHostname) {
101
+ // To use self-hosted voice containers, we need no 'region', and 'speechSynthesisHostname' and 'speechRecognitionHostname' must both be defined
102
+ // As this ponyfill is for speech synthesis only, we put a mock 'speechRecognitionHostname'
103
+ const data = {
104
+ credentials: {
105
+ // @ts-ignore
106
+ speechSynthesisHostname: new URL(ponyfillCredentials.speechSynthesisHostname),
107
+ speechRecognitionHostname: ponyfillCredentials.speechRecognitionHostname || 'mandatory_recognition_host_name',
108
+ subscriptionKey: ponyfillCredentials.subscriptionKey || 'mandatory_subscription_key'
109
+ }
110
+ };
111
+ ponyfillRef.current = (0, $4yQHp$daviaiwebspeechcognitiveservicesdavi.createSpeechSynthesisPonyfill)(data);
112
+ setPonyfillCreated(true);
113
+ }
114
+ }, [
115
+ ponyfillCredentials
116
+ ]);
117
+ const onVoicesChanged = ()=>{
118
+ var _ponyfillRef_current;
119
+ const voices = (_ponyfillRef_current = ponyfillRef.current) === null || _ponyfillRef_current === void 0 ? void 0 : _ponyfillRef_current.speechSynthesis.getVoices();
120
+ if (voices && Array.isArray(voices) && voices.length) dispatch((0, $kpW3P.storeActions).speech.setVoice((0, $gvTLl.selectVoice)(voices, locale, customVoice, agentData) || undefined));
121
+ };
122
+ (0, $4yQHp$react.useEffect)(()=>{
123
+ if (ponyfillRef.current) {
124
+ const voices = ponyfillRef.current.speechSynthesis.getVoices();
125
+ if (voices && Array.isArray(voices) && voices.length) dispatch((0, $kpW3P.storeActions).speech.setVoice((0, $gvTLl.selectVoice)(voices, locale, customVoice, agentData) || undefined));
126
+ else ponyfillRef.current.speechSynthesis.onvoiceschanged = onVoicesChanged;
127
+ }
128
+ }, [
129
+ ponyfillCreated,
130
+ customVoice,
131
+ agentData,
132
+ locale
133
+ ]);
134
+ (0, $4yQHp$react.useEffect)(()=>{
135
+ return ()=>{
136
+ refreshTimerRef.current && clearTimeout(refreshTimerRef.current);
137
+ };
138
+ }, []);
139
+ return ponyfillCreated && ponyfillRef.current ? /*#__PURE__*/ (0, $4yQHp$reactjsxruntime.jsx)((0, $iiIh5.default), {
140
+ ponyfill: ponyfillRef.current,
141
+ isRetorikNews: isRetorikNews
142
+ }) : /*#__PURE__*/ (0, $4yQHp$reactjsxruntime.jsx)((0, ($parcel$interopDefault($4yQHp$react))).Fragment, {});
143
+ };
144
+ var $fe06f31a645aa3a1$export$2e2bcd8739ae039 = $fe06f31a645aa3a1$var$SynthesisPonyfillManager;
145
+
146
+ });
147
+ parcelRegister("ieTrG", function(module, exports) {
148
+
149
+ $parcel$export(module.exports, "fetchSpeechServicesToken", () => $f2ae26d736ec24dc$export$a2ce4fdd6972d6a7);
150
+ const $f2ae26d736ec24dc$export$a2ce4fdd6972d6a7 = async (region, key)=>{
151
+ const tokenRes = await fetch(`https://${region}.api.cognitive.microsoft.com/sts/v1.0/issueToken`, {
152
+ method: 'POST',
153
+ headers: {
154
+ 'Ocp-Apim-Subscription-Key': key
155
+ }
156
+ }).then((value)=>{
157
+ return value.text();
158
+ }).catch((error)=>{
159
+ console.log('Error : ', error);
160
+ return undefined;
161
+ });
162
+ return tokenRes;
163
+ };
164
+
165
+ });
166
+
167
+ parcelRegister("gvTLl", function(module, exports) {
168
+
169
+ $parcel$export(module.exports, "selectVoice", () => $5679d80e89b3df01$export$4bf371fc4fa74a28);
170
+ const $5679d80e89b3df01$export$4bf371fc4fa74a28 = (voices, locale, customVoice, agentData)=>{
171
+ let voice = null;
172
+ // Check if a custom voice is defined in the props
173
+ if (customVoice) {
174
+ if (customVoice.voice) {
175
+ // Search voice with its full name (ex: AriaNeural, GuyNeural)
176
+ const neuralVoice = new RegExp(customVoice.voice, 'iu');
177
+ voice = voices.find(({ name: name })=>neuralVoice.test(name) || name === customVoice.voice);
178
+ } else if (customVoice.gender) // Search voice depending on given gender and locale
179
+ voice = voices.find(({ gender: gender, lang: lang })=>{
180
+ var _customVoice_gender;
181
+ return gender.toLowerCase() === (customVoice === null || customVoice === void 0 ? void 0 : (_customVoice_gender = customVoice.gender) === null || _customVoice_gender === void 0 ? void 0 : _customVoice_gender.toLowerCase()) && lang === locale;
182
+ });
183
+ }
184
+ // Get voice depending on locale and gender
185
+ if (!voice) voice = voices.find(({ gender: gender, lang: lang })=>{
186
+ var _agentData_gender;
187
+ return gender.toLowerCase() === ((agentData === null || agentData === void 0 ? void 0 : (_agentData_gender = agentData.gender) === null || _agentData_gender === void 0 ? void 0 : _agentData_gender.toLowerCase()) || 'female') && lang === locale;
188
+ });
189
+ // No voice found, fall back to US default voices : female => Aria / male => Guy
190
+ if (!voice) {
191
+ var _agentData_gender;
192
+ const genderedVoice = (agentData === null || agentData === void 0 ? void 0 : (_agentData_gender = agentData.gender) === null || _agentData_gender === void 0 ? void 0 : _agentData_gender.toLowerCase()) === 'female' ? 'AriaNeural' : 'GuyNeural';
193
+ const neuralVoice = new RegExp(genderedVoice, 'iu');
194
+ voice = voices.find(({ name: name })=>neuralVoice.test(name));
195
+ }
196
+ return voice;
197
+ };
198
+
199
+ });
200
+
201
+ parcelRegister("iiIh5", function(module, exports) {
202
+
203
+ $parcel$export(module.exports, "default", () => $ad561f5c61e38c20$export$2e2bcd8739ae039);
204
+
205
+
206
+
207
+
208
+ var $kpW3P = parcelRequire("kpW3P");
209
+
210
+ var $k2lV6 = parcelRequire("k2lV6");
211
+
212
+ var $7WHA7 = parcelRequire("7WHA7");
213
+
214
+ var $gvTLl = parcelRequire("gvTLl");
215
+
216
+ var $cWW4y = parcelRequire("cWW4y");
217
+
218
+ var $7wztJ = parcelRequire("7wztJ");
219
+ const $ad561f5c61e38c20$var$SynthesisManager = ({ ponyfill: ponyfill, isRetorikNews: isRetorikNews })=>{
220
+ const dispatch = (0, $4yQHp$reactredux.useDispatch)();
221
+ const cancel = (0, $4yQHp$reactredux.useSelector)((state)=>state.speechReducer.cancel);
222
+ const streamingQueue = (0, $4yQHp$reactredux.useSelector)((state)=>state.speechReducer.streamingQueue);
223
+ const voice = (0, $4yQHp$reactredux.useSelector)((state)=>state.speechReducer.voice);
224
+ const customVoice = (0, $4yQHp$reactredux.useSelector)((state)=>state.speechReducer.customVoice);
225
+ const activeRecognitionState = (0, $4yQHp$reactredux.useSelector)((state)=>state.speechReducer.activeRecognitionState);
226
+ const externalTextToSpeech = (0, $4yQHp$reactredux.useSelector)((state)=>state.speechReducer.externalTextToSpeech);
227
+ const isMicrophoneAllowed = (0, $4yQHp$reactredux.useSelector)((state)=>state.speechReducer.isMicrophoneAllowed);
228
+ const mode = (0, $4yQHp$reactredux.useSelector)((state)=>state.speechReducer.mode);
229
+ const route = (0, $4yQHp$reactredux.useSelector)((state)=>state.viewReducer.route);
230
+ const locale = (0, $4yQHp$reactredux.useSelector)((state)=>state.localeReducer.locale);
231
+ const replacementLocales = (0, $4yQHp$reactredux.useSelector)((state)=>state.localeReducer.replacementLocales);
232
+ const agentData = (0, $4yQHp$reactredux.useSelector)((state)=>state.retorikReducer.agentData);
233
+ const appAvailable = (0, $4yQHp$reactredux.useSelector)((state)=>state.retorikReducer.appAvailable);
234
+ const preventExpectedInputHint = (0, $4yQHp$reactredux.useSelector)((state)=>state.retorikReducer.configuration.preventExpectedInputHint);
235
+ const speechSynthesisOptions = (0, $4yQHp$reactredux.useSelector)((state)=>state.retorikReducer.configuration.speechSynthesisOptions);
236
+ const sendTrace = (0, $k2lV6.useTelemetry)().sendTrace;
237
+ const [utterance, setUtterance] = (0, $4yQHp$react.useState)(null);
238
+ const [nextUtterance, setNextUtterance] = (0, $4yQHp$react.useState)(null);
239
+ const [forceSpeechCaching, setForceSpeechCaching] = (0, $4yQHp$react.useState)(false);
240
+ const isNewsViewRef = (0, $4yQHp$react.useRef)(!!isRetorikNews);
241
+ const lastListTextPlayedRef = (0, $4yQHp$react.useRef)('');
242
+ const streamingQueueRef = (0, $4yQHp$react.useRef)([]);
243
+ const currentActivityRef = (0, $4yQHp$react.useRef)(null);
244
+ /**
245
+ * Check activity locale in case of voice change during the speech, to keep the language defined in activity
246
+ * instead of switching languages between answers that are written in the same language
247
+ * @param {string} activityLocale
248
+ * @returns {SpeechSynthesisVoice | null}
249
+ */ const getVoiceAfterCheckingActivityLocale = (activityLocale)=>{
250
+ return activityLocale === locale ? voice : (0, $gvTLl.selectVoice)(ponyfill.speechSynthesis.getVoices(), activityLocale, customVoice, agentData);
251
+ };
252
+ /**
253
+ * Check if the activity is a list one, to prevent text re-reading on state update
254
+ * @param {CreateUtteranceParams} params
255
+ * @returns {SpeechSynthesisUtterance}
256
+ */ const checkActivityAndCreateUtterance = (params)=>{
257
+ if (params.activity.attachmentLayout && params.activity.attachmentLayout.toLowerCase() === 'davilist') {
258
+ const textToSpeak = params.activity.speak || params.activity.text;
259
+ if (textToSpeak) {
260
+ if (textToSpeak === lastListTextPlayedRef.current) return (0, $cWW4y.checkSayAsWordsAndCreateUtterance)({
261
+ ...params,
262
+ voice: null
263
+ }, speechSynthesisOptions === null || speechSynthesisOptions === void 0 ? void 0 : speechSynthesisOptions.sayAs);
264
+ else lastListTextPlayedRef.current = textToSpeak;
265
+ }
266
+ }
267
+ return (0, $cWW4y.checkSayAsWordsAndCreateUtterance)(params, speechSynthesisOptions === null || speechSynthesisOptions === void 0 ? void 0 : speechSynthesisOptions.sayAs);
268
+ };
269
+ const resetData = ()=>{
270
+ var // Set all activities currently in the queue as ended
271
+ _streamingQueueRef_current;
272
+ (_streamingQueueRef_current = streamingQueueRef.current) === null || _streamingQueueRef_current === void 0 ? void 0 : _streamingQueueRef_current.forEach((activity)=>{
273
+ dispatch((0, $kpW3P.storeActions).activity.addEndedActivity(activity.id));
274
+ });
275
+ streamingQueueRef.current = [];
276
+ dispatch((0, $kpW3P.storeActions).speech.killCurrentStreaming());
277
+ currentActivityRef.current = null;
278
+ setUtterance(null);
279
+ setNextUtterance(null);
280
+ dispatch((0, $kpW3P.storeActions).speech.resetCancelCurrentUtterance());
281
+ dispatch((0, $kpW3P.storeActions).speech.setSpeaking(false));
282
+ dispatch((0, $kpW3P.storeActions).speech.setBoundaryData([]));
283
+ };
284
+ const checkReplacementLocaleAndGetUtterance = (activity, checkReplacement = true)=>{
285
+ const replacementLocale = checkReplacement ? (replacementLocales === null || replacementLocales === void 0 ? void 0 : replacementLocales[locale]) || locale : locale;
286
+ const params = {
287
+ activity: activity,
288
+ voice: getVoiceAfterCheckingActivityLocale(replacementLocale),
289
+ locale: replacementLocale
290
+ };
291
+ return checkActivityAndCreateUtterance(params);
292
+ };
293
+ /**
294
+ * Check if the microphone can be opened automatically
295
+ */ const checkDictateState = ()=>{
296
+ if (!preventExpectedInputHint && mode === (0, $kpW3P.Mode).vocal && activeRecognitionState === (0, $kpW3P.RecognitionState).Closed) {
297
+ if (!isMicrophoneAllowed) dispatch((0, $kpW3P.storeActions).speech.askPermission());
298
+ else dispatch((0, $kpW3P.storeActions).speech.toggleMicrophone(true));
299
+ }
300
+ };
301
+ /**
302
+ * On route change, reset all data and check if we are on the news view
303
+ */ (0, $4yQHp$react.useEffect)(()=>{
304
+ resetData();
305
+ if (!isRetorikNews) isNewsViewRef.current = route === (0, $kpW3P.Routes).News || route === (0, $kpW3P.Routes).NewsInVeille;
306
+ // Force speech caching when using Retorik News or when using news in veille
307
+ setForceSpeechCaching(isRetorikNews || route === (0, $kpW3P.Routes).NewsInVeille);
308
+ }, [
309
+ route
310
+ ]);
311
+ /**
312
+ * On cancel call, reset all data and kill current streaming
313
+ */ (0, $4yQHp$react.useEffect)(()=>{
314
+ cancel && resetData();
315
+ }, [
316
+ cancel
317
+ ]);
318
+ /**
319
+ * Play external speech immediately but don't add it to the history
320
+ */ (0, $4yQHp$react.useEffect)(()=>{
321
+ if (externalTextToSpeech) {
322
+ const activity = {
323
+ speak: externalTextToSpeech,
324
+ locale: locale
325
+ };
326
+ currentActivityRef.current = activity;
327
+ setUtterance(checkReplacementLocaleAndGetUtterance(activity, false));
328
+ }
329
+ }, [
330
+ externalTextToSpeech
331
+ ]);
332
+ const dispatchSpeechEvent = (start)=>{
333
+ const speechEvent = start ? new Event('retorikSpeakStart') : new Event('retorikSpeakStop');
334
+ document.dispatchEvent(speechEvent);
335
+ };
336
+ /**
337
+ * Called when utterance's "start" event is fired
338
+ */ const handleUtteranceStart = ()=>{
339
+ var _currentActivityRef_current, _currentActivityRef_current1, _currentActivityRef_current2, _streamingQueueRef_current__value;
340
+ sendTrace((0, $7WHA7.TraceType).utteranceStart, {
341
+ activityId: (_currentActivityRef_current = currentActivityRef.current) === null || _currentActivityRef_current === void 0 ? void 0 : _currentActivityRef_current.id,
342
+ text: ((_currentActivityRef_current1 = currentActivityRef.current) === null || _currentActivityRef_current1 === void 0 ? void 0 : _currentActivityRef_current1.speak) || ((_currentActivityRef_current2 = currentActivityRef.current) === null || _currentActivityRef_current2 === void 0 ? void 0 : _currentActivityRef_current2.text)
343
+ });
344
+ dispatch((0, $kpW3P.storeActions).speech.setSpeaking(true));
345
+ if (!isNewsViewRef.current && (currentActivityRef === null || currentActivityRef === void 0 ? void 0 : currentActivityRef.current)) {
346
+ dispatch((0, $kpW3P.storeActions).speech.setCurrentOrLastPlayedActivity(currentActivityRef.current));
347
+ currentActivityRef.current.id && dispatch((0, $kpW3P.storeActions).directline.dispatchMarkActivity({
348
+ id: currentActivityRef.current.id,
349
+ speaking: true
350
+ }));
351
+ }
352
+ dispatchSpeechEvent(true);
353
+ // Set next utterance to prepare synthesis data in order to improve fluidity
354
+ if (streamingQueueRef.current.length && !((_streamingQueueRef_current__value = streamingQueueRef.current[0].value) === null || _streamingQueueRef_current__value === void 0 ? void 0 : _streamingQueueRef_current__value.streamingCount)) {
355
+ const utt = checkReplacementLocaleAndGetUtterance(streamingQueueRef.current[0], false);
356
+ setNextUtterance((current)=>utt.text === (current === null || current === void 0 ? void 0 : current.text) ? null : utt);
357
+ } else setNextUtterance(null);
358
+ };
359
+ /**
360
+ * Called when utterance's "end" event is fired
361
+ */ const handleUtteranceEnd = ()=>{
362
+ var _currentActivityRef_current;
363
+ sendTrace((0, $7WHA7.TraceType).utteranceEnd, {
364
+ activityId: (_currentActivityRef_current = currentActivityRef.current) === null || _currentActivityRef_current === void 0 ? void 0 : _currentActivityRef_current.id
365
+ });
366
+ dispatch((0, $kpW3P.storeActions).speech.setSpeaking(false));
367
+ dispatchSpeechEvent(false);
368
+ if (isNewsViewRef.current) {
369
+ dispatch((0, $kpW3P.storeActions).utils.setRetorikNewsEnded(true));
370
+ currentActivityRef.current = null;
371
+ } else handleEnded();
372
+ };
373
+ const handleEnded = ()=>{
374
+ var _currentActivityRef_current, _streamingQueueRef_current;
375
+ // Add played activity id to context's endedActivities
376
+ if ((_currentActivityRef_current = currentActivityRef.current) === null || _currentActivityRef_current === void 0 ? void 0 : _currentActivityRef_current.id) {
377
+ dispatch((0, $kpW3P.storeActions).activity.addEndedActivity(currentActivityRef.current.id));
378
+ dispatch((0, $kpW3P.storeActions).directline.dispatchMarkActivity({
379
+ id: currentActivityRef.current.id,
380
+ speaking: false
381
+ }));
382
+ }
383
+ if ((_streamingQueueRef_current = streamingQueueRef.current) === null || _streamingQueueRef_current === void 0 ? void 0 : _streamingQueueRef_current.length) {
384
+ var _streamingQueueRef_current__value;
385
+ // Check if this is the message sent after streaming activities
386
+ if ((_streamingQueueRef_current__value = streamingQueueRef.current[0].value) === null || _streamingQueueRef_current__value === void 0 ? void 0 : _streamingQueueRef_current__value.streamingCount) {
387
+ var _streamingQueueRef_current1;
388
+ dispatch((0, $kpW3P.storeActions).activity.addEndedActivity(streamingQueueRef.current[0].id));
389
+ // If there is another activity after this message, play it. If not, let's check if the microphone should be opened
390
+ if (((_streamingQueueRef_current1 = streamingQueueRef.current) === null || _streamingQueueRef_current1 === void 0 ? void 0 : _streamingQueueRef_current1.length) > 1) {
391
+ const utt = checkReplacementLocaleAndGetUtterance(streamingQueueRef.current[1]);
392
+ currentActivityRef.current = streamingQueueRef.current[1];
393
+ setUtterance(utt);
394
+ dispatch((0, $kpW3P.storeActions).speech.removeFirstFromStreamingQueue(true));
395
+ } else {
396
+ streamingQueueRef.current[0].inputHint === 'expectingInput' && checkDictateState();
397
+ currentActivityRef.current = null;
398
+ setUtterance(null);
399
+ setNextUtterance(null);
400
+ dispatch((0, $kpW3P.storeActions).speech.removeFirstFromStreamingQueue(false));
401
+ }
402
+ } else {
403
+ const utt = checkReplacementLocaleAndGetUtterance(streamingQueueRef.current[0]);
404
+ currentActivityRef.current = streamingQueueRef.current[0];
405
+ setUtterance(utt);
406
+ dispatch((0, $kpW3P.storeActions).speech.removeFirstFromStreamingQueue(false));
407
+ }
408
+ } else {
409
+ var _currentActivityRef_current1;
410
+ ((_currentActivityRef_current1 = currentActivityRef.current) === null || _currentActivityRef_current1 === void 0 ? void 0 : _currentActivityRef_current1.inputHint) === 'expectingInput' && checkDictateState();
411
+ currentActivityRef.current = null;
412
+ setUtterance(null);
413
+ setNextUtterance(null);
414
+ }
415
+ };
416
+ /**
417
+ * Wait for app loading and voice selection to begin playing speech
418
+ */ (0, $4yQHp$react.useEffect)(()=>{
419
+ // Set ref from the state to use in events
420
+ streamingQueueRef.current = streamingQueue;
421
+ if (appAvailable && voice && streamingQueue.length && !currentActivityRef.current) handleEnded();
422
+ }, [
423
+ appAvailable,
424
+ voice,
425
+ streamingQueue
426
+ ]);
427
+ return /*#__PURE__*/ (0, $4yQHp$reactjsxruntime.jsx)((0, $7wztJ.default), {
428
+ ponyfill: ponyfill,
429
+ appAvailable: appAvailable,
430
+ utterance: utterance,
431
+ nextUtterance: nextUtterance,
432
+ forceSpeechCaching: forceSpeechCaching,
433
+ onStart: handleUtteranceStart,
434
+ onError: handleUtteranceEnd,
435
+ onEnd: handleUtteranceEnd
436
+ });
437
+ };
438
+ var $ad561f5c61e38c20$export$2e2bcd8739ae039 = $ad561f5c61e38c20$var$SynthesisManager;
439
+
440
+ });
441
+ parcelRegister("cWW4y", function(module, exports) {
442
+
443
+ $parcel$export(module.exports, "checkSayAsWordsAndCreateUtterance", () => $285c8810199513ef$export$f969af62bba9a48b);
444
+
445
+ var $3oRQE = parcelRequire("3oRQE");
446
+ /**
447
+ * Check if there are some replacement codes for this language, to improve speech synthesis, and then create the utterance
448
+ * @param {CreateUtteranceParams} params - data needed to create an utterance
449
+ * @param {SayAs} sayAs - string that should be replaced by their ipa codes
450
+ * @returns {SpeechSynthesisUtterance}
451
+ */ const $285c8810199513ef$export$f969af62bba9a48b = (params, sayAs)=>{
452
+ let sayAsWords = [];
453
+ if (sayAs) {
454
+ var _sayAs_common, _sayAs_localized_params_locale;
455
+ ((_sayAs_common = sayAs.common) === null || _sayAs_common === void 0 ? void 0 : _sayAs_common.length) && (sayAsWords = [
456
+ ...sayAs.common
457
+ ]);
458
+ sayAs.localized && ((_sayAs_localized_params_locale = sayAs.localized[params.locale]) === null || _sayAs_localized_params_locale === void 0 ? void 0 : _sayAs_localized_params_locale.length) && (sayAsWords = [
459
+ ...sayAsWords,
460
+ ...sayAs.localized[params.locale]
461
+ ]);
462
+ }
463
+ return (0, $3oRQE.default)({
464
+ ...params,
465
+ sayAsWords: sayAsWords
466
+ });
467
+ };
468
+
469
+ });
470
+ parcelRegister("3oRQE", function(module, exports) {
471
+
472
+ $parcel$export(module.exports, "default", () => $d441ea54333b2073$export$2e2bcd8739ae039);
473
+
474
+
475
+ const $d441ea54333b2073$var$buildSSML = (activity, locale, speechMarkdownParser, sayAsWords)=>{
476
+ let speech = activity.speak || activity.text;
477
+ // Replace character not recognized in Microsoft TTS
478
+ speech = speech.replaceAll("\u2019", "'");
479
+ let textParsedAsSSML = '';
480
+ try {
481
+ if (sayAsWords === null || sayAsWords === void 0 ? void 0 : sayAsWords.length) {
482
+ const wordsUsed = [];
483
+ sayAsWords.forEach((tuple)=>{
484
+ if (!wordsUsed.includes(tuple.text.toLocaleLowerCase(locale))) {
485
+ const regex = new RegExp(`\\b${tuple.text}\\b`, 'gi');
486
+ speech = speech.replaceAll(regex, `(${tuple.text})[ipa:"${tuple.ipa}"]`);
487
+ wordsUsed.push(tuple.text.toLocaleLowerCase(locale));
488
+ }
489
+ });
490
+ }
491
+ textParsedAsSSML = speechMarkdownParser.toSSML(speech);
492
+ } catch (e) {
493
+ console.warn('Retorik Framework > error in speechmarkdown parser : ', e);
494
+ }
495
+ return `<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="${locale}">` + textParsedAsSSML + '</speak>';
496
+ };
497
+ const $d441ea54333b2073$var$createUtterance = ({ activity: activity, voice: voice, locale: locale, sayAsWords: sayAsWords })=>{
498
+ // If there is no text to be read, create an empty utterance that will be put in the array of ended activities
499
+ if (!voice || !activity.speak && !activity.text) return new (0, $4yQHp$daviaiwebspeechcognitiveservicesdavi.SpeechSynthesisUtterance)('');
500
+ return new (0, $4yQHp$daviaiwebspeechcognitiveservicesdavi.SpeechSynthesisUtterance)($d441ea54333b2073$var$buildSSML(activity, locale, new (0, $4yQHp$daviaispeechmarkdowndavijs.SpeechMarkdown)({
501
+ platform: 'microsoft-azure',
502
+ includeSpeakTag: false,
503
+ globalVoiceAndLang: {
504
+ voice: voice.name,
505
+ lang: voice.name.toLowerCase().includes('multilingual') ? locale : undefined
506
+ }
507
+ }), sayAsWords));
508
+ };
509
+ var $d441ea54333b2073$export$2e2bcd8739ae039 = $d441ea54333b2073$var$createUtterance;
510
+
511
+ });
512
+
513
+
514
+ parcelRegister("7wztJ", function(module, exports) {
515
+
516
+ $parcel$export(module.exports, "default", () => $d31b268c3b702355$export$2e2bcd8739ae039);
517
+
518
+
519
+
520
+
521
+ var $kpW3P = parcelRequire("kpW3P");
522
+
523
+ var $hMfs5 = parcelRequire("hMfs5");
524
+
525
+ var $f7K3i = parcelRequire("f7K3i");
526
+
527
+ var $fa4j5 = parcelRequire("fa4j5");
528
+ const $d31b268c3b702355$var$DBManager = new (0, $f7K3i.default)();
529
+ const $d31b268c3b702355$var$tagsRemoverRegex = /<[^<>]+>/g;
530
+ const $d31b268c3b702355$var$RetorikSpeech = ({ ponyfill: ponyfill, onEnd: onEnd, onError: onError, onStart: onStart, utterance: utterance, nextUtterance: nextUtterance, appAvailable: appAvailable, forceSpeechCaching: forceSpeechCaching })=>{
531
+ const dispatch = (0, $4yQHp$reactredux.useDispatch)();
532
+ const locale = (0, $4yQHp$reactredux.useSelector)((state)=>state.localeReducer.locale);
533
+ const loaderClosed = (0, $4yQHp$reactredux.useSelector)((state)=>state.retorikReducer.loaderClosed);
534
+ const enableSpeechCaching = (0, $4yQHp$reactredux.useSelector)((state)=>state.retorikReducer.configuration.enableSpeechCaching);
535
+ const speechRecognitionOptions = (0, $4yQHp$reactredux.useSelector)((state)=>state.retorikReducer.configuration.speechRecognitionOptions);
536
+ const useOldRemote = (0, $4yQHp$reactredux.useSelector)((state)=>state.retorikReducer.configuration.useOldRemote);
537
+ const voice = (0, $4yQHp$reactredux.useSelector)((state)=>state.speechReducer.voice);
538
+ const muted = (0, $4yQHp$reactredux.useSelector)((state)=>state.speechReducer.muted);
539
+ const activeRecognitionState = (0, $4yQHp$reactredux.useSelector)((state)=>state.speechReducer.activeRecognitionState);
540
+ const boundaryRef = (0, $4yQHp$react.useRef)(null);
541
+ const visemeRef = (0, $4yQHp$react.useRef)(null);
542
+ const bookmarkRef = (0, $4yQHp$react.useRef)(null);
543
+ const audioRef = (0, $4yQHp$react.useRef)(null);
544
+ const speechRecognitionAudioRef = (0, $4yQHp$react.useRef)(null);
545
+ const microphoneOpenAudioRef = (0, $4yQHp$react.useRef)(null);
546
+ const microphoneCloseAudioRef = (0, $4yQHp$react.useRef)(null);
547
+ const [DBReady, setDBReady] = (0, $4yQHp$react.useState)(false);
548
+ const [playingBlob, setPlayingBlob] = (0, $4yQHp$react.useState)(false);
549
+ const nextUtteranceDataRef = (0, $4yQHp$react.useRef)(null);
550
+ const nextUtteranceTextRef = (0, $4yQHp$react.useRef)(null);
551
+ const nextUtteranceBoundariesRef = (0, $4yQHp$react.useRef)([]);
552
+ const nextUtteranceVisemesRef = (0, $4yQHp$react.useRef)([]);
553
+ const nextUtteranceBookmarksRef = (0, $4yQHp$react.useRef)([]);
554
+ const emptyTextUtteranceRef = (0, $4yQHp$react.useRef)(null);
555
+ (0, $4yQHp$react.useEffect)(()=>{
556
+ $d31b268c3b702355$var$DBManager.checkDB().then((result)=>setDBReady(result));
557
+ return ()=>{
558
+ stopCurrentPlaying();
559
+ (emptyTextUtteranceRef === null || emptyTextUtteranceRef === void 0 ? void 0 : emptyTextUtteranceRef.current) && clearTimeout(emptyTextUtteranceRef.current);
560
+ };
561
+ }, []);
562
+ const stopCurrentPlaying = ()=>{
563
+ if (appAvailable || loaderClosed) {
564
+ var _audioRef_current;
565
+ // Cancel synthesis if using synthesizer
566
+ if (!playingBlob) ponyfill.speechSynthesis.cancel();
567
+ resetNextUtteranceData();
568
+ if (audioRef.current && !((_audioRef_current = audioRef.current) === null || _audioRef_current === void 0 ? void 0 : _audioRef_current.paused)) {
569
+ audioRef.current.pause();
570
+ handleEnd();
571
+ }
572
+ }
573
+ };
574
+ const attachEvents = (tempUtterance, isMainUtterance)=>{
575
+ tempUtterance.onerror = (event)=>{
576
+ isMainUtterance ? handleError(event) : nextUtteranceDataRef.current = null;
577
+ };
578
+ tempUtterance.onsynthesiscompleted = ()=>{
579
+ const endBoundary = {
580
+ word: '',
581
+ startTime: 0,
582
+ endTime: 0,
583
+ boundaryType: 'EndBoundary'
584
+ };
585
+ if (isMainUtterance) {
586
+ const tempBoundaries = (boundaryRef === null || boundaryRef === void 0 ? void 0 : boundaryRef.current) || [];
587
+ boundaryRef.current = [
588
+ ...tempBoundaries,
589
+ endBoundary
590
+ ];
591
+ dispatch((0, $kpW3P.storeActions).speech.setBoundaryData([
592
+ ...tempBoundaries,
593
+ endBoundary
594
+ ]));
595
+ } else nextUtteranceBoundariesRef.current = [
596
+ ...nextUtteranceBoundariesRef.current,
597
+ endBoundary
598
+ ];
599
+ };
600
+ tempUtterance.onboundary = (event)=>{
601
+ if (event.boundaryType !== 'Viseme') {
602
+ const newBoundary = {
603
+ word: event.name,
604
+ startTime: event.elapsedTime,
605
+ endTime: event.elapsedTime + event.duration,
606
+ boundaryType: event.boundaryType
607
+ };
608
+ if (isMainUtterance) {
609
+ // Update the boundaryData state with the new data.
610
+ const tempBoundaries = (boundaryRef === null || boundaryRef === void 0 ? void 0 : boundaryRef.current) || [];
611
+ boundaryRef.current = [
612
+ ...tempBoundaries,
613
+ newBoundary
614
+ ];
615
+ dispatch((0, $kpW3P.storeActions).speech.setBoundaryData([
616
+ ...tempBoundaries,
617
+ newBoundary
618
+ ]));
619
+ } else nextUtteranceBoundariesRef.current = [
620
+ ...nextUtteranceBoundariesRef.current,
621
+ newBoundary
622
+ ];
623
+ }
624
+ };
625
+ tempUtterance.onviseme = (event)=>{
626
+ if (isMainUtterance) {
627
+ // Collect visemes locally - they will be dispatched when audio starts playing
628
+ const tempVisemes = (visemeRef === null || visemeRef === void 0 ? void 0 : visemeRef.current) || [];
629
+ visemeRef.current = [
630
+ ...tempVisemes,
631
+ event
632
+ ];
633
+ } else nextUtteranceVisemesRef.current = [
634
+ ...nextUtteranceVisemesRef.current,
635
+ event
636
+ ];
637
+ };
638
+ tempUtterance.onmark = (event)=>{
639
+ console.log('Retorik Framework > onmark event', event);
640
+ const bookmark = {
641
+ name: event.name,
642
+ time: event.elapsedTime
643
+ };
644
+ if (isMainUtterance) {
645
+ // Collect bookmarks locally - they will be dispatched when audio starts playing
646
+ const tempBookmarks = (bookmarkRef === null || bookmarkRef === void 0 ? void 0 : bookmarkRef.current) || [];
647
+ bookmarkRef.current = [
648
+ ...tempBookmarks,
649
+ bookmark
650
+ ];
651
+ } else nextUtteranceBookmarksRef.current = [
652
+ ...nextUtteranceBookmarksRef.current,
653
+ bookmark
654
+ ];
655
+ };
656
+ return tempUtterance;
657
+ };
658
+ const processNextData = (data)=>{
659
+ nextUtteranceDataRef.current = (data === null || data === void 0 ? void 0 : data.byteLength) && nextUtteranceTextRef.current ? {
660
+ text: nextUtteranceTextRef.current,
661
+ data: {
662
+ speechData: data,
663
+ boundaries: nextUtteranceBoundariesRef.current,
664
+ visemes: nextUtteranceVisemesRef.current,
665
+ bookmarks: nextUtteranceBookmarksRef.current
666
+ }
667
+ } : null;
668
+ // Reset boundary / viseme data
669
+ resetNextUtteranceData(true);
670
+ };
671
+ const resetNextUtteranceData = (keepArrayBufferData)=>{
672
+ !keepArrayBufferData && (nextUtteranceDataRef.current = null);
673
+ nextUtteranceTextRef.current = null;
674
+ nextUtteranceBoundariesRef.current = [];
675
+ nextUtteranceVisemesRef.current = [];
676
+ nextUtteranceBookmarksRef.current = [];
677
+ };
678
+ (0, $4yQHp$react.useEffect)(()=>{
679
+ if (utterance) {
680
+ if (utterance.text) {
681
+ if (audioRef === null || audioRef === void 0 ? void 0 : audioRef.current) {
682
+ var _nextUtteranceDataRef_current;
683
+ if (((_nextUtteranceDataRef_current = nextUtteranceDataRef.current) === null || _nextUtteranceDataRef_current === void 0 ? void 0 : _nextUtteranceDataRef_current.text) === utterance.text && nextUtteranceDataRef.current.data) {
684
+ boundaryRef.current = nextUtteranceDataRef.current.data.boundaries;
685
+ dispatch((0, $kpW3P.storeActions).speech.setBoundaryData(nextUtteranceDataRef.current.data.boundaries));
686
+ // Store visemes locally - they will be dispatched when audio starts playing
687
+ visemeRef.current = nextUtteranceDataRef.current.data.visemes;
688
+ processData(nextUtteranceDataRef.current.data.speechData, true);
689
+ } else // Play utterance whether by asking for a speech synthesis, or by retrieving data from indexedDB
690
+ playUtterance(attachEvents(utterance, true));
691
+ } else stopCurrentPlaying();
692
+ } else handleEmptyTextUtterance();
693
+ } else stopCurrentPlaying();
694
+ }, [
695
+ utterance
696
+ ]);
697
+ (0, $4yQHp$react.useEffect)(()=>{
698
+ // If there are data in nextUtteranceTextRef, this means the previous synthesis data retrieval is not finished, so we don't begin a new one
699
+ if ((nextUtterance === null || nextUtterance === void 0 ? void 0 : nextUtterance.text) && !nextUtteranceTextRef.current) {
700
+ const tempUtterance = attachEvents(nextUtterance);
701
+ nextUtteranceTextRef.current = nextUtterance.text;
702
+ ponyfill.speechSynthesis.synthesizeAndGetArrayData(tempUtterance, processNextData);
703
+ } else resetNextUtteranceData();
704
+ }, [
705
+ nextUtterance
706
+ ]);
707
+ const playUtterance = async (utt)=>{
708
+ if (DBReady && (enableSpeechCaching !== false || forceSpeechCaching) && utt) {
709
+ const dataFromIndexedDB = await $d31b268c3b702355$var$DBManager.getSpeechData(`${locale}.${voice === null || voice === void 0 ? void 0 : voice.name}.${utt.text.replace($d31b268c3b702355$var$tagsRemoverRegex, '')}`);
710
+ if (dataFromIndexedDB) {
711
+ boundaryRef.current = dataFromIndexedDB.boundaries;
712
+ dispatch((0, $kpW3P.storeActions).speech.setBoundaryData(dataFromIndexedDB.boundaries));
713
+ // Store visemes locally - they will be dispatched when audio starts playing
714
+ visemeRef.current = dataFromIndexedDB.visemes || [];
715
+ processData(dataFromIndexedDB.value, true);
716
+ } else ponyfill.speechSynthesis.synthesizeAndGetArrayData(utt, processData);
717
+ } else ponyfill.speechSynthesis.synthesizeAndGetArrayData(utt, processData);
718
+ };
719
+ const processData = (data, alreadyExistsInDB)=>{
720
+ if (data === null || data === void 0 ? void 0 : data.byteLength) {
721
+ const blob = new Blob([
722
+ data
723
+ ], {
724
+ type: 'audio/mp3'
725
+ });
726
+ !alreadyExistsInDB && (enableSpeechCaching !== false || forceSpeechCaching) && DBReady && (boundaryRef === null || boundaryRef === void 0 ? void 0 : boundaryRef.current) && utterance && $d31b268c3b702355$var$DBManager.addSpeechData({
727
+ id: `${locale}.${voice === null || voice === void 0 ? void 0 : voice.name}.${utterance.text.replace($d31b268c3b702355$var$tagsRemoverRegex, '')}`,
728
+ value: data,
729
+ boundaries: boundaryRef.current,
730
+ visemes: visemeRef.current || []
731
+ });
732
+ const url = URL.createObjectURL(blob);
733
+ if (audioRef === null || audioRef === void 0 ? void 0 : audioRef.current) {
734
+ setPlayingBlob(true);
735
+ audioRef.current.src = url;
736
+ audioRef.current.play().catch((e)=>console.warn(e));
737
+ }
738
+ } else handleEmptyTextUtterance();
739
+ };
740
+ const resetData = ()=>{
741
+ boundaryRef.current = [];
742
+ visemeRef.current = [];
743
+ dispatch((0, $kpW3P.storeActions).speech.setBoundaryData([]));
744
+ dispatch((0, $kpW3P.storeActions).speech.setVisemeData([]));
745
+ dispatch((0, $kpW3P.storeActions).speech.setBookmarkData([]));
746
+ setPlayingBlob(false);
747
+ };
748
+ const handleStart = ()=>{
749
+ if (appAvailable || loaderClosed) {
750
+ var _visemeRef_current;
751
+ // Dispatch visemes now that audio is playing, ensuring lip sync timing is correct
752
+ if ((_visemeRef_current = visemeRef.current) === null || _visemeRef_current === void 0 ? void 0 : _visemeRef_current.length) {
753
+ dispatch((0, $kpW3P.storeActions).speech.setVisemeData(visemeRef.current));
754
+ dispatch((0, $kpW3P.storeActions).speech.setBookmarkData(bookmarkRef.current || []));
755
+ }
756
+ onStart === null || onStart === void 0 ? void 0 : onStart();
757
+ }
758
+ };
759
+ const handleEnd = ()=>{
760
+ if (appAvailable || loaderClosed) {
761
+ onEnd === null || onEnd === void 0 ? void 0 : onEnd();
762
+ resetData();
763
+ } else dispatch((0, $kpW3P.storeActions).retorik.setLoaderClosed(true));
764
+ };
765
+ const handleError = (error)=>{
766
+ console.log('Retorik Framework > speech synthesis error ', error);
767
+ onError === null || onError === void 0 ? void 0 : onError();
768
+ resetData();
769
+ };
770
+ const handleEmptyTextUtterance = ()=>{
771
+ handleStart();
772
+ (emptyTextUtteranceRef === null || emptyTextUtteranceRef === void 0 ? void 0 : emptyTextUtteranceRef.current) && clearTimeout(emptyTextUtteranceRef.current);
773
+ emptyTextUtteranceRef.current = setTimeout(()=>{
774
+ handleEnd();
775
+ }, 50);
776
+ };
777
+ /**
778
+ * On call :
779
+ * - play 1 second muted sound to prime audio output
780
+ * - MANDATORY FOR SAFARI IN VOCAL MODE
781
+ */ const primeRetorikSpeech = ()=>{
782
+ if (audioRef.current) {
783
+ audioRef.current.play().catch((e)=>console.warn(e));
784
+ (speechRecognitionAudioRef === null || speechRecognitionAudioRef === void 0 ? void 0 : speechRecognitionAudioRef.current) && speechRecognitionAudioRef.current.play().catch((e)=>console.warn(e));
785
+ // Send animation start event to secure animation not playing on safari if permissions are not sufficient
786
+ window.dispatchEvent(new Event('retorikSpiritEnginePlay'));
787
+ }
788
+ };
789
+ /**
790
+ * Play sound on speech recognition activation if it isn't disabled in configuration
791
+ */ (0, $4yQHp$react.useEffect)(()=>{
792
+ var _speechRecognitionAudioRef_current;
793
+ if (useOldRemote) {
794
+ if (!!(speechRecognitionOptions === null || speechRecognitionOptions === void 0 ? void 0 : speechRecognitionOptions.enableActivationSound) && activeRecognitionState === (0, $kpW3P.RecognitionState).Listening) speechRecognitionAudioRef === null || speechRecognitionAudioRef === void 0 ? void 0 : (_speechRecognitionAudioRef_current = speechRecognitionAudioRef.current) === null || _speechRecognitionAudioRef_current === void 0 ? void 0 : _speechRecognitionAudioRef_current.play().catch((e)=>console.warn(e));
795
+ } else if (!!(speechRecognitionOptions === null || speechRecognitionOptions === void 0 ? void 0 : speechRecognitionOptions.enableActivationSound)) switch(activeRecognitionState){
796
+ case (0, $kpW3P.RecognitionState).Listening:
797
+ var _microphoneOpenAudioRef_current;
798
+ microphoneOpenAudioRef === null || microphoneOpenAudioRef === void 0 ? void 0 : (_microphoneOpenAudioRef_current = microphoneOpenAudioRef.current) === null || _microphoneOpenAudioRef_current === void 0 ? void 0 : _microphoneOpenAudioRef_current.play().catch((e)=>console.warn(e));
799
+ break;
800
+ case (0, $kpW3P.RecognitionState).Closing:
801
+ case (0, $kpW3P.RecognitionState).ForceClosing:
802
+ var _microphoneCloseAudioRef_current;
803
+ microphoneCloseAudioRef === null || microphoneCloseAudioRef === void 0 ? void 0 : (_microphoneCloseAudioRef_current = microphoneCloseAudioRef.current) === null || _microphoneCloseAudioRef_current === void 0 ? void 0 : _microphoneCloseAudioRef_current.play().catch((e)=>console.warn(e));
804
+ break;
805
+ default:
806
+ break;
807
+ }
808
+ }, [
809
+ useOldRemote,
810
+ activeRecognitionState,
811
+ speechRecognitionOptions
812
+ ]);
813
+ return /*#__PURE__*/ (0, $4yQHp$reactjsxruntime.jsxs)((0, ($parcel$interopDefault($4yQHp$react))).Fragment, {
814
+ children: [
815
+ /*#__PURE__*/ (0, $4yQHp$reactjsxruntime.jsx)("audio", {
816
+ ref: audioRef,
817
+ src: (0, $hMfs5.audioFiles).onesecond,
818
+ muted: appAvailable || loaderClosed ? muted : true,
819
+ onPlay: handleStart,
820
+ onEnded: handleEnd
821
+ }),
822
+ /*#__PURE__*/ (0, $4yQHp$reactjsxruntime.jsx)("audio", {
823
+ ref: speechRecognitionAudioRef,
824
+ src: (0, $hMfs5.audioFiles).speechrecognition,
825
+ preload: "auto",
826
+ muted: appAvailable || loaderClosed ? muted : true
827
+ }),
828
+ /*#__PURE__*/ (0, $4yQHp$reactjsxruntime.jsx)("audio", {
829
+ ref: microphoneOpenAudioRef,
830
+ src: (0, $hMfs5.audioFiles).microphoneopen,
831
+ preload: "auto",
832
+ muted: appAvailable || loaderClosed ? muted : true
833
+ }),
834
+ /*#__PURE__*/ (0, $4yQHp$reactjsxruntime.jsx)("audio", {
835
+ ref: microphoneCloseAudioRef,
836
+ src: (0, $hMfs5.audioFiles).microphoneclose,
837
+ preload: "auto",
838
+ muted: appAvailable || loaderClosed ? muted : true
839
+ }),
840
+ /*#__PURE__*/ (0, $4yQHp$reactjsxruntime.jsx)((0, $fa4j5.default), {
841
+ appAvailable: appAvailable,
842
+ handleValidation: primeRetorikSpeech
843
+ })
844
+ ]
845
+ });
846
+ };
847
+ var $d31b268c3b702355$export$2e2bcd8739ae039 = $d31b268c3b702355$var$RetorikSpeech;
848
+
849
+ });
850
+ parcelRegister("f7K3i", function(module, exports) {
851
+
852
+ $parcel$export(module.exports, "default", () => $e7fbc91b362e1033$export$2e2bcd8739ae039);
853
+ class $e7fbc91b362e1033$var$IndexedDbManager {
854
+ constructor(){
855
+ this.version = 1;
856
+ this.storeName = 'speechSynthesisData';
857
+ this.checkDB = async ()=>{
858
+ return new Promise((resolve)=>{
859
+ const request = indexedDB.open('retorik-framework-db', this.version);
860
+ request.onsuccess = ()=>{
861
+ resolve(true);
862
+ };
863
+ request.onerror = ()=>{
864
+ resolve(false);
865
+ };
866
+ request.onupgradeneeded = ()=>{
867
+ const db = request.result;
868
+ // If the data object store doesn't exist, create it
869
+ if (!db.objectStoreNames.contains(this.storeName)) db.createObjectStore(this.storeName, {
870
+ keyPath: 'id'
871
+ });
872
+ };
873
+ });
874
+ };
875
+ this.addSpeechData = async (data)=>{
876
+ return new Promise((resolve)=>{
877
+ const request = indexedDB.open('retorik-framework-db', this.version);
878
+ request.onsuccess = ()=>{
879
+ const db = request.result;
880
+ const tx = db.transaction(this.storeName, 'readwrite');
881
+ const store = tx.objectStore(this.storeName);
882
+ // Base 64 encode
883
+ data.id = window.btoa(encodeURI(data.id));
884
+ store.add(data);
885
+ resolve(true);
886
+ };
887
+ request.onerror = ()=>{
888
+ resolve(false);
889
+ };
890
+ });
891
+ };
892
+ this.getSpeechData = async (id)=>{
893
+ return new Promise((resolve)=>{
894
+ const request = indexedDB.open('retorik-framework-db', this.version);
895
+ request.onsuccess = ()=>{
896
+ const db = request.result;
897
+ const tx = db.transaction(this.storeName, 'readonly');
898
+ const store = tx.objectStore(this.storeName);
899
+ // Base 64 encode
900
+ const data = store.get(window.btoa(encodeURI(id)));
901
+ data.onsuccess = ()=>{
902
+ resolve(data.result);
903
+ };
904
+ };
905
+ request.onerror = ()=>{
906
+ resolve(null);
907
+ };
908
+ });
909
+ };
910
+ }
911
+ }
912
+ var $e7fbc91b362e1033$export$2e2bcd8739ae039 = $e7fbc91b362e1033$var$IndexedDbManager;
913
+
914
+ });
915
+
916
+
917
+
918
+
919
+
920
+ //# sourceMappingURL=SynthesisPonyfillManager.f9f9a915.js.map