@nualang/nualang-ui-components 0.1.1144 → 0.1.1145
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/dist/Dialogs/CreateQuestion/CreateQuestion.js +19 -8
- package/dist/Exercises/Pronouncer/Pronouncer.js +19 -35
- package/dist/Exercises/Roleplay/Games/ActItOutGameListeningAndSpeaking/ActItOutGame.js +20 -35
- package/dist/Exercises/Roleplay/Games/ActItOutGameSpeaking/ActItOutGame.js +20 -35
- package/dist/Forms/Settings/Settings.stories.js +1 -1
- package/dist/hooks/useRecognition.js +43 -6
- package/package.json +1 -1
|
@@ -61,10 +61,12 @@ function CreateQuestion({
|
|
|
61
61
|
const [question, setQuestion] = (0, _react.useState)(otherProps.question);
|
|
62
62
|
const [answer, setAnswer] = (0, _react.useState)(initialAnswerState);
|
|
63
63
|
const [answerList, setAnswerList] = (0, _react.useState)(otherProps.answers);
|
|
64
|
+
const [error, setError] = (0, _react.useState)("");
|
|
64
65
|
const handleAnswerInputChange = event => {
|
|
65
66
|
const target = event.target;
|
|
66
67
|
const value = target.type === "checkbox" ? target.checked : target.value;
|
|
67
68
|
const name = target.name;
|
|
69
|
+
setError("");
|
|
68
70
|
setAnswer(prevState => ({
|
|
69
71
|
...prevState,
|
|
70
72
|
[name]: value
|
|
@@ -72,11 +74,18 @@ function CreateQuestion({
|
|
|
72
74
|
};
|
|
73
75
|
const handleAddAnswer = () => {
|
|
74
76
|
if (answer && answer.text) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
const trimmedText = answer.text.trim().toLowerCase();
|
|
78
|
+
const isDuplicate = answerList.some(existingAnswer => existingAnswer.text.toLowerCase() === trimmedText);
|
|
79
|
+
if (isDuplicate) {
|
|
80
|
+
setError(t("duplicate_answer_desc"));
|
|
81
|
+
} else {
|
|
82
|
+
setAnswerList(prevAnswerList => [...prevAnswerList, {
|
|
83
|
+
...answer,
|
|
84
|
+
text: answer.text.trim()
|
|
85
|
+
}]);
|
|
86
|
+
setAnswer(initialAnswerState);
|
|
87
|
+
setError("");
|
|
88
|
+
}
|
|
80
89
|
}
|
|
81
90
|
};
|
|
82
91
|
const handleRemoveAnswer = index => {
|
|
@@ -101,7 +110,8 @@ function CreateQuestion({
|
|
|
101
110
|
};
|
|
102
111
|
const handleSubmit = () => {
|
|
103
112
|
const correctAnswers = answerList.filter(a => a.correct);
|
|
104
|
-
|
|
113
|
+
const duplicateAnswers = answerList.filter((a, index) => answerList.findIndex(b => b.text.toLowerCase() === a.text.toLowerCase()) !== index);
|
|
114
|
+
if (correctAnswers.length && question !== "" && !duplicateAnswers.length) {
|
|
105
115
|
onSubmit({
|
|
106
116
|
question: question.trim(),
|
|
107
117
|
answers: answerList
|
|
@@ -110,7 +120,7 @@ function CreateQuestion({
|
|
|
110
120
|
resetQuestionState();
|
|
111
121
|
}
|
|
112
122
|
} else {
|
|
113
|
-
alert(t("must_question_least_correct_answer"));
|
|
123
|
+
alert(!correctAnswers.length ? t("must_question_least_correct_answer") : t("duplicate_answer_desc"));
|
|
114
124
|
}
|
|
115
125
|
};
|
|
116
126
|
const handleOnDragEnd = result => {
|
|
@@ -170,6 +180,7 @@ function CreateQuestion({
|
|
|
170
180
|
item: true,
|
|
171
181
|
xs: 12
|
|
172
182
|
}, /*#__PURE__*/_react.default.createElement(_InputHelper.default, {
|
|
183
|
+
error: !!error,
|
|
173
184
|
t: t,
|
|
174
185
|
value: answer.text,
|
|
175
186
|
onChange: handleAnswerInputChange,
|
|
@@ -182,7 +193,7 @@ function CreateQuestion({
|
|
|
182
193
|
fullWidth: true,
|
|
183
194
|
variant: "outlined",
|
|
184
195
|
characters: forLangCharacters ? forLangCharacters : null,
|
|
185
|
-
helperText: answer.text && answer.text.trim() !== "" ? t("answer_helper_text") : "",
|
|
196
|
+
helperText: error || (answer.text && answer.text.trim() !== "" ? t("answer_helper_text") : ""),
|
|
186
197
|
multiline: true
|
|
187
198
|
}))), /*#__PURE__*/_react.default.createElement(_reactBeautifulDnd.DragDropContext, {
|
|
188
199
|
onDragEnd: handleOnDragEnd
|
|
@@ -173,6 +173,7 @@ function Pronouncer({
|
|
|
173
173
|
cx
|
|
174
174
|
} = useStyles();
|
|
175
175
|
const [viewMoreTranslations, setViewMoreTranslations] = (0, _react.useState)(false);
|
|
176
|
+
const [currentPhraseText, setCurrentPhraseText] = (0, _react.useState)("");
|
|
176
177
|
const {
|
|
177
178
|
isSocketConnected,
|
|
178
179
|
recognitionState,
|
|
@@ -181,7 +182,12 @@ function Pronouncer({
|
|
|
181
182
|
resetTranscript,
|
|
182
183
|
clearAttemptAudio,
|
|
183
184
|
indicateEndStream
|
|
184
|
-
} = (0, _useRecognition.default)(
|
|
185
|
+
} = (0, _useRecognition.default)({
|
|
186
|
+
currentPhraseText,
|
|
187
|
+
trackRecommendedEvent,
|
|
188
|
+
exerciseName,
|
|
189
|
+
learnLang
|
|
190
|
+
});
|
|
185
191
|
const {
|
|
186
192
|
interimTranscript,
|
|
187
193
|
finalTranscript,
|
|
@@ -192,7 +198,6 @@ function Pronouncer({
|
|
|
192
198
|
attemptAudioURL,
|
|
193
199
|
audioBlob
|
|
194
200
|
} = recognitionState;
|
|
195
|
-
const [currentAttemptAudioURL, setCurrentAttemptAudioURL] = (0, _react.useState)("");
|
|
196
201
|
const handleMic = expectedTranscript => {
|
|
197
202
|
const speechContexts = expectedTranscript ? [{
|
|
198
203
|
phrases: [...(expectedTranscript.length < 100 ? [(0, _utils.removeExtraWhiteSpaces)(expectedTranscript)] : (0, _utils.removeExtraWhiteSpaces)(expectedTranscript).split(" "))],
|
|
@@ -200,42 +205,16 @@ function Pronouncer({
|
|
|
200
205
|
}] : null;
|
|
201
206
|
const model = expectedTranscript && expectedTranscript.length < 50 ? "latest_short" : "default";
|
|
202
207
|
|
|
203
|
-
// Stop Recording required to get final confidence score
|
|
204
|
-
toggleListen(learnLang, speechContexts, model);
|
|
208
|
+
// Stop Recording required to get final confidence score and trigger event if needed
|
|
209
|
+
toggleListen(learnLang, speechContexts, model, true);
|
|
205
210
|
};
|
|
206
211
|
(0, _react.useEffect)(() => {
|
|
207
|
-
if
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
handleContinue(false, currentPhrase);
|
|
212
|
-
} else if (attemptAudioURL && attemptAudioURL !== currentAttemptAudioURL) {
|
|
213
|
-
setCurrentAttemptAudioURL(attemptAudioURL);
|
|
214
|
-
const captureSpeechRecognitionNoTranscript = async () => {
|
|
215
|
-
const {
|
|
216
|
-
userAgent,
|
|
217
|
-
language,
|
|
218
|
-
mediaDevices
|
|
219
|
-
} = navigator;
|
|
220
|
-
const browser = (0, _utils.getBrowserInfo)(userAgent);
|
|
221
|
-
const machineInfo = (0, _utils.getMachineInfo)(userAgent);
|
|
222
|
-
const [availableMicrophones, activeMicrophone] = await (0, _utils.getMicrophoneInfo)(mediaDevices);
|
|
223
|
-
trackRecommendedEvent("speech_recognition_no_transcript", {
|
|
224
|
-
A1_phrase: `${currentPhrase.phrase}`,
|
|
225
|
-
A2_active_microphone: `${activeMicrophone}`,
|
|
226
|
-
A3_available_microphones: `${availableMicrophones}`,
|
|
227
|
-
A4_browser: `${browser}`,
|
|
228
|
-
A5_socket_state: isSocketConnected ? "connected" : "disconnected",
|
|
229
|
-
A6_machine_info: `${machineInfo}`,
|
|
230
|
-
A7_user_language: `${language}`,
|
|
231
|
-
A8_learn_language: `${learnLang}`,
|
|
232
|
-
A9_exercise: `${exerciseName}`
|
|
233
|
-
});
|
|
234
|
-
};
|
|
235
|
-
captureSpeechRecognitionNoTranscript().catch(console.error);
|
|
236
|
-
}
|
|
212
|
+
// Check if recording has ended and has detected at least one word
|
|
213
|
+
if (open && !recognizing && finalTranscript) {
|
|
214
|
+
// Submit attempt
|
|
215
|
+
handleContinue(false, currentPhrase);
|
|
237
216
|
}
|
|
238
|
-
}, [open, recognizing, finalTranscript
|
|
217
|
+
}, [open, recognizing, finalTranscript]);
|
|
239
218
|
const initialVoiceSpeed = topicInfo && topicInfo.voiceSpeed ? topicInfo.voiceSpeed : "";
|
|
240
219
|
const exerciseState = (0, _useExerciseState.default)({
|
|
241
220
|
open,
|
|
@@ -322,6 +301,11 @@ function Pronouncer({
|
|
|
322
301
|
checked,
|
|
323
302
|
setChecked
|
|
324
303
|
} = exerciseState;
|
|
304
|
+
(0, _react.useEffect)(() => {
|
|
305
|
+
if (currentPhrase.phrase) {
|
|
306
|
+
setCurrentPhraseText(currentPhrase.phrase);
|
|
307
|
+
}
|
|
308
|
+
}, [currentPhrase]);
|
|
325
309
|
const unattemptedQuestionTotal = questions.filter(q => !q.questionAttempted).length;
|
|
326
310
|
const joyrideSteps = [{
|
|
327
311
|
content: /*#__PURE__*/_react.default.createElement("h2", null, t("pronunciation_exercise_welcome")),
|
|
@@ -284,6 +284,7 @@ function RoleplayGame({
|
|
|
284
284
|
open
|
|
285
285
|
});
|
|
286
286
|
const scriptWithoutQuestions = roleplay.script.filter(scriptLine => !scriptLine?.question);
|
|
287
|
+
const [currentPhraseText, setCurrentPhraseText] = (0, _react.useState)("");
|
|
287
288
|
const {
|
|
288
289
|
isSocketConnected,
|
|
289
290
|
recognitionState,
|
|
@@ -291,7 +292,13 @@ function RoleplayGame({
|
|
|
291
292
|
resetTranscript,
|
|
292
293
|
indicateEndStream,
|
|
293
294
|
toggleListen
|
|
294
|
-
} = (0, _useRecognition.default)(
|
|
295
|
+
} = (0, _useRecognition.default)({
|
|
296
|
+
currentPhraseText,
|
|
297
|
+
trackRecommendedEvent,
|
|
298
|
+
exerciseName,
|
|
299
|
+
learnLang,
|
|
300
|
+
gameId
|
|
301
|
+
});
|
|
295
302
|
const {
|
|
296
303
|
interimTranscript,
|
|
297
304
|
finalTranscript,
|
|
@@ -304,7 +311,6 @@ function RoleplayGame({
|
|
|
304
311
|
} = recognitionState;
|
|
305
312
|
const [currentMessages, setCurrentMessages] = (0, _react.useState)([]);
|
|
306
313
|
const [celebratingNualaImage, setCelebratingNualaImage] = (0, _react.useState)(_nuala_1_celebrating.default);
|
|
307
|
-
const [currentAttemptAudioURL, setCurrentAttemptAudioURL] = (0, _react.useState)("");
|
|
308
314
|
const exerciseState = (0, _useExerciseState.default)({
|
|
309
315
|
t,
|
|
310
316
|
open,
|
|
@@ -417,8 +423,8 @@ function RoleplayGame({
|
|
|
417
423
|
}] : null;
|
|
418
424
|
const model = expectedTranscript && expectedTranscript.length < 50 ? "latest_short" : "default";
|
|
419
425
|
|
|
420
|
-
// Stop Recording required to get final confidence score
|
|
421
|
-
toggleListen(learnLang, speechContexts, model);
|
|
426
|
+
// Stop Recording required to get final confidence score and trigger event if needed
|
|
427
|
+
toggleListen(learnLang, speechContexts, model, true);
|
|
422
428
|
};
|
|
423
429
|
const getRandomNuala = () => {
|
|
424
430
|
let finished = false;
|
|
@@ -441,41 +447,20 @@ function RoleplayGame({
|
|
|
441
447
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
442
448
|
}, [actorHasBeenSelected]);
|
|
443
449
|
const nextScriptLine = roleplay && scriptWithoutQuestions && scriptWithoutQuestions[roleplayMessages.length] ? scriptWithoutQuestions[roleplayMessages.length] : "";
|
|
450
|
+
(0, _react.useEffect)(() => {
|
|
451
|
+
if (nextScriptLine) {
|
|
452
|
+
setCurrentPhraseText(nextScriptLine.text);
|
|
453
|
+
}
|
|
454
|
+
}, [nextScriptLine]);
|
|
444
455
|
const phraseWordList = nextScriptLine ? (0, _utils.removeExtraWhiteSpaces)((0, _utils.removeAllSymbols)(nextScriptLine.text)).split(" ") : [];
|
|
445
456
|
(0, _react.useEffect)(() => {
|
|
446
|
-
if
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
checkRoleplayPronunciation(finalTranscript, nextScriptLine.text);
|
|
451
|
-
} else if (attemptAudioURL && attemptAudioURL !== currentAttemptAudioURL) {
|
|
452
|
-
setCurrentAttemptAudioURL(attemptAudioURL);
|
|
453
|
-
const captureSpeechRecognitionNoTranscript = async () => {
|
|
454
|
-
const {
|
|
455
|
-
userAgent,
|
|
456
|
-
language,
|
|
457
|
-
mediaDevices
|
|
458
|
-
} = navigator;
|
|
459
|
-
const browser = (0, _utils.getBrowserInfo)(userAgent);
|
|
460
|
-
const machineInfo = (0, _utils.getMachineInfo)(userAgent);
|
|
461
|
-
const [availableMicrophones, activeMicrophone] = await (0, _utils.getMicrophoneInfo)(mediaDevices);
|
|
462
|
-
trackRecommendedEvent("speech_recognition_no_transcript", {
|
|
463
|
-
A1_phrase: `${nextScriptLine.text}`,
|
|
464
|
-
A2_active_microphone: `${activeMicrophone}`,
|
|
465
|
-
A3_available_microphones: `${availableMicrophones}`,
|
|
466
|
-
A4_browser: `${browser}`,
|
|
467
|
-
A5_socket_state: isSocketConnected ? "connected" : "disconnected",
|
|
468
|
-
A6_machine_info: `${machineInfo}`,
|
|
469
|
-
A7_user_language: `${language}`,
|
|
470
|
-
A8_learn_language: `${learnLang}`,
|
|
471
|
-
A9_exercise: `${exerciseName}-act-it-out-listening-speaking`
|
|
472
|
-
});
|
|
473
|
-
};
|
|
474
|
-
captureSpeechRecognitionNoTranscript().catch(console.error);
|
|
475
|
-
}
|
|
457
|
+
// Check if recording has ended and has detected at least one word
|
|
458
|
+
if (open && !recognizing && finalTranscript) {
|
|
459
|
+
// Submit attempt
|
|
460
|
+
checkRoleplayPronunciation(finalTranscript, nextScriptLine.text);
|
|
476
461
|
}
|
|
477
462
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
478
|
-
}, [open, recognizing, finalTranscript
|
|
463
|
+
}, [open, recognizing, finalTranscript]);
|
|
479
464
|
const isRoleplayScriptLoaded = roleplay && roleplay.script;
|
|
480
465
|
(0, _react.useEffect)(() => {
|
|
481
466
|
if (isRoleplayScriptLoaded) {
|
|
@@ -280,6 +280,7 @@ function RoleplayGame({
|
|
|
280
280
|
open
|
|
281
281
|
});
|
|
282
282
|
const scriptWithoutQuestions = roleplay.script.filter(scriptLine => !scriptLine?.question);
|
|
283
|
+
const [currentPhraseText, setCurrentPhraseText] = (0, _react.useState)("");
|
|
283
284
|
const {
|
|
284
285
|
isSocketConnected,
|
|
285
286
|
recognitionState,
|
|
@@ -287,7 +288,13 @@ function RoleplayGame({
|
|
|
287
288
|
resetTranscript,
|
|
288
289
|
indicateEndStream,
|
|
289
290
|
toggleListen
|
|
290
|
-
} = (0, _useRecognition.default)(
|
|
291
|
+
} = (0, _useRecognition.default)({
|
|
292
|
+
currentPhraseText,
|
|
293
|
+
trackRecommendedEvent,
|
|
294
|
+
exerciseName,
|
|
295
|
+
learnLang,
|
|
296
|
+
gameId
|
|
297
|
+
});
|
|
291
298
|
const {
|
|
292
299
|
interimTranscript,
|
|
293
300
|
finalTranscript,
|
|
@@ -301,7 +308,6 @@ function RoleplayGame({
|
|
|
301
308
|
const [currentMessages, setCurrentMessages] = (0, _react.useState)([]);
|
|
302
309
|
const [ariaLiveText, setAriaLiveText] = (0, _react.useState)("");
|
|
303
310
|
const [celebratingNualaImage, setCelebratingNualaImage] = (0, _react.useState)(_nuala_1_celebrating.default);
|
|
304
|
-
const [currentAttemptAudioURL, setCurrentAttemptAudioURL] = (0, _react.useState)("");
|
|
305
311
|
const exerciseState = (0, _useExerciseState.default)({
|
|
306
312
|
t,
|
|
307
313
|
open,
|
|
@@ -415,8 +421,8 @@ function RoleplayGame({
|
|
|
415
421
|
const model = expectedTranscript && expectedTranscript.length < 50 ? "latest_short" : "default";
|
|
416
422
|
setAriaLiveText("Listening...");
|
|
417
423
|
|
|
418
|
-
// Stop Recording required to get final confidence score
|
|
419
|
-
toggleListen(learnLang, speechContexts, model);
|
|
424
|
+
// Stop Recording required to get final confidence score and trigger event if needed
|
|
425
|
+
toggleListen(learnLang, speechContexts, model, true);
|
|
420
426
|
};
|
|
421
427
|
const getRandomNuala = () => {
|
|
422
428
|
let finished = false;
|
|
@@ -439,41 +445,20 @@ function RoleplayGame({
|
|
|
439
445
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
440
446
|
}, [actorHasBeenSelected]);
|
|
441
447
|
const nextScriptLine = roleplay && scriptWithoutQuestions && scriptWithoutQuestions[roleplayMessages.length] ? scriptWithoutQuestions[roleplayMessages.length] : "";
|
|
448
|
+
(0, _react.useEffect)(() => {
|
|
449
|
+
if (nextScriptLine) {
|
|
450
|
+
setCurrentPhraseText(nextScriptLine.text);
|
|
451
|
+
}
|
|
452
|
+
}, [nextScriptLine]);
|
|
442
453
|
const phraseWordList = nextScriptLine ? (0, _utils.removeExtraWhiteSpaces)((0, _utils.removeAllSymbols)(nextScriptLine.text)).split(" ") : [];
|
|
443
454
|
(0, _react.useEffect)(() => {
|
|
444
|
-
if
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
checkRoleplayPronunciation(finalTranscript, nextScriptLine.text);
|
|
449
|
-
} else if (attemptAudioURL && attemptAudioURL !== currentAttemptAudioURL) {
|
|
450
|
-
setCurrentAttemptAudioURL(attemptAudioURL);
|
|
451
|
-
const captureSpeechRecognitionNoTranscript = async () => {
|
|
452
|
-
const {
|
|
453
|
-
userAgent,
|
|
454
|
-
language,
|
|
455
|
-
mediaDevices
|
|
456
|
-
} = navigator;
|
|
457
|
-
const browser = (0, _utils.getBrowserInfo)(userAgent);
|
|
458
|
-
const machineInfo = (0, _utils.getMachineInfo)(userAgent);
|
|
459
|
-
const [availableMicrophones, activeMicrophone] = await (0, _utils.getMicrophoneInfo)(mediaDevices);
|
|
460
|
-
trackRecommendedEvent("speech_recognition_no_transcript", {
|
|
461
|
-
A1_phrase: `${nextScriptLine.text}`,
|
|
462
|
-
A2_active_microphone: `${activeMicrophone}`,
|
|
463
|
-
A3_available_microphones: `${availableMicrophones}`,
|
|
464
|
-
A4_browser: `${browser}`,
|
|
465
|
-
A5_socket_state: isSocketConnected ? "connected" : "disconnected",
|
|
466
|
-
A6_machine_info: `${machineInfo}`,
|
|
467
|
-
A7_user_language: `${language}`,
|
|
468
|
-
A8_learn_language: `${learnLang}`,
|
|
469
|
-
A9_exercise: `${exerciseName}-act-it-out-speaking`
|
|
470
|
-
});
|
|
471
|
-
};
|
|
472
|
-
captureSpeechRecognitionNoTranscript().catch(console.error);
|
|
473
|
-
}
|
|
455
|
+
// Check if recording has ended and has detected at least one word
|
|
456
|
+
if (open && !recognizing && finalTranscript) {
|
|
457
|
+
// Submit attempt
|
|
458
|
+
checkRoleplayPronunciation(finalTranscript, nextScriptLine.text);
|
|
474
459
|
}
|
|
475
460
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
476
|
-
}, [open, recognizing, finalTranscript
|
|
461
|
+
}, [open, recognizing, finalTranscript]);
|
|
477
462
|
const isRoleplayScriptLoaded = roleplay && roleplay.script;
|
|
478
463
|
(0, _react.useEffect)(() => {
|
|
479
464
|
if (isRoleplayScriptLoaded) {
|
|
@@ -280,7 +280,7 @@ Subscription.args = {
|
|
|
280
280
|
subscriptionStatus: "active",
|
|
281
281
|
updatedAt: 1630678018431
|
|
282
282
|
}, {
|
|
283
|
-
allowedDomains: 2[
|
|
283
|
+
allowedDomains: 2["ces-schools.com", "fathomtech.io"],
|
|
284
284
|
createdAt: 1630679041953,
|
|
285
285
|
createdBy: "39e46d34-9863-497f-b4f9-10e6a7875833",
|
|
286
286
|
createdByName: "Stephen",
|
|
@@ -40,7 +40,13 @@ const constraints = {
|
|
|
40
40
|
audio: true,
|
|
41
41
|
video: false
|
|
42
42
|
};
|
|
43
|
-
function useRecognition(
|
|
43
|
+
function useRecognition({
|
|
44
|
+
currentPhraseText,
|
|
45
|
+
trackRecommendedEvent,
|
|
46
|
+
learnLang,
|
|
47
|
+
exerciseName,
|
|
48
|
+
gameId
|
|
49
|
+
}) {
|
|
44
50
|
const browserSupportsSpeechRecognition = true;
|
|
45
51
|
const [recognitionState, setRecognitionState] = (0, _react.useState)({
|
|
46
52
|
interimTranscript: "",
|
|
@@ -176,7 +182,30 @@ function useRecognition() {
|
|
|
176
182
|
const indicateEndStream = () => {
|
|
177
183
|
socket.emit("endGoogleCloudStream", "");
|
|
178
184
|
};
|
|
179
|
-
const
|
|
185
|
+
const captureSpeechRecognitionNoTranscript = async () => {
|
|
186
|
+
const {
|
|
187
|
+
userAgent,
|
|
188
|
+
language,
|
|
189
|
+
mediaDevices
|
|
190
|
+
} = navigator;
|
|
191
|
+
const browser = (0, _index.getBrowserInfo)(userAgent);
|
|
192
|
+
const machineInfo = (0, _index.getMachineInfo)(userAgent);
|
|
193
|
+
const [availableMicrophones, activeMicrophone] = await (0, _index.getMicrophoneInfo)(mediaDevices);
|
|
194
|
+
const eventBody = {
|
|
195
|
+
A1_phrase: `${currentPhraseText}`,
|
|
196
|
+
A2_active_microphone: `${activeMicrophone}`,
|
|
197
|
+
A3_available_microphones: `${availableMicrophones}`,
|
|
198
|
+
A4_browser: `${browser}`,
|
|
199
|
+
A5_socket_state: isSocketConnected ? "connected" : "disconnected",
|
|
200
|
+
A6_machine_info: `${machineInfo}`,
|
|
201
|
+
A7_user_language: `${language}`,
|
|
202
|
+
A8_learn_language: `${learnLang}`,
|
|
203
|
+
A9_exercise: gameId ? `${exerciseName}-${gameId}` : `${exerciseName}`
|
|
204
|
+
};
|
|
205
|
+
console.log("Event Body:", eventBody);
|
|
206
|
+
trackRecommendedEvent("speech_recognition_no_transcript", eventBody);
|
|
207
|
+
};
|
|
208
|
+
const stopRecording = (keepSocketAlive, triggerEvent) => {
|
|
180
209
|
// indicate end stream to trigger interim transcript to return as final transcript
|
|
181
210
|
if (socket) {
|
|
182
211
|
indicateEndStream();
|
|
@@ -190,6 +219,14 @@ function useRecognition() {
|
|
|
190
219
|
...prevState,
|
|
191
220
|
isRecognizingDisabled: false
|
|
192
221
|
}));
|
|
222
|
+
const {
|
|
223
|
+
finalTranscript,
|
|
224
|
+
interimTranscript
|
|
225
|
+
} = recognitionState;
|
|
226
|
+
if (triggerEvent && (!finalTranscript || finalTranscript === "") && (!interimTranscript || interimTranscript === "")) {
|
|
227
|
+
captureSpeechRecognitionNoTranscript().catch(console.error);
|
|
228
|
+
console.log("Event triggered");
|
|
229
|
+
}
|
|
193
230
|
}, 2000);
|
|
194
231
|
};
|
|
195
232
|
(0, _react.useEffect)(() => {
|
|
@@ -280,12 +317,12 @@ function useRecognition() {
|
|
|
280
317
|
// No further action needed, as this already closes itself on error
|
|
281
318
|
});
|
|
282
319
|
};
|
|
283
|
-
const toggleListen = (lang, speechContexts, model) => {
|
|
320
|
+
const toggleListen = (lang, speechContexts, model, triggerEvent) => {
|
|
284
321
|
const {
|
|
285
322
|
recognizing
|
|
286
323
|
} = recognitionState;
|
|
287
324
|
if (recognizing) {
|
|
288
|
-
stop();
|
|
325
|
+
stop(triggerEvent);
|
|
289
326
|
} else {
|
|
290
327
|
start(lang, speechContexts, model);
|
|
291
328
|
}
|
|
@@ -302,7 +339,7 @@ function useRecognition() {
|
|
|
302
339
|
}, audioRecordingLimit);
|
|
303
340
|
startRecognition(_config.default.languages[lang?.toLowerCase()]?.Tag, speechContexts, model);
|
|
304
341
|
};
|
|
305
|
-
const stop =
|
|
342
|
+
const stop = triggerEvent => {
|
|
306
343
|
if (stopAudioRecordingTimeoutId) {
|
|
307
344
|
clearTimeout(stopAudioRecordingTimeoutId);
|
|
308
345
|
stopAudioRecordingTimeoutId = null;
|
|
@@ -312,7 +349,7 @@ function useRecognition() {
|
|
|
312
349
|
recognizing: false,
|
|
313
350
|
isRecognizingDisabled: true
|
|
314
351
|
}));
|
|
315
|
-
stopRecording(true);
|
|
352
|
+
stopRecording(true, triggerEvent);
|
|
316
353
|
};
|
|
317
354
|
const resetTranscript = () => {
|
|
318
355
|
setRecognitionState(prevState => ({
|