@sage-rsc/talking-head-react 1.0.21 → 1.0.22
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/{fbxAnimationLoader-CVM-Jv5Y.cjs → fbxAnimationLoader-Bs9Qd-Cz.cjs} +1 -1
- package/dist/{fbxAnimationLoader-DzYmybHd.js → fbxAnimationLoader-DRJgB6tB.js} +1 -1
- package/dist/{index-3_k5n4iL.js → index-B58d_xt0.js} +619 -606
- package/dist/{index-BeFzGp0g.cjs → index-BrvgGvOZ.cjs} +4 -4
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/components/CurriculumLearning.jsx +66 -26
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./index-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./index-BrvgGvOZ.cjs");exports.CurriculumLearning=i.CurriculumLearning;exports.TalkingHeadAvatar=i.TalkingHeadAvatar;exports.TalkingHeadComponent=i.TalkingHeadComponent;exports.animations=i.animations;exports.getActiveTTSConfig=i.getActiveTTSConfig;exports.getAnimation=i.getAnimation;exports.getVoiceOptions=i.getVoiceOptions;exports.hasAnimation=i.hasAnimation;
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -176,7 +176,17 @@ const CurriculumLearning = forwardRef(({
|
|
|
176
176
|
stateRef.current.currentQuestionIndex = 0;
|
|
177
177
|
stateRef.current.totalQuestions = currentLesson?.questions?.length || 0;
|
|
178
178
|
|
|
179
|
-
|
|
179
|
+
// Trigger custom action immediately (before avatar speaks) - includes first question
|
|
180
|
+
const firstQuestion = getCurrentQuestion();
|
|
181
|
+
callbacksRef.current.onCustomAction({
|
|
182
|
+
type: 'questionStart',
|
|
183
|
+
moduleIndex: stateRef.current.currentModuleIndex,
|
|
184
|
+
lessonIndex: stateRef.current.currentLessonIndex,
|
|
185
|
+
totalQuestions: stateRef.current.totalQuestions,
|
|
186
|
+
question: firstQuestion // Include first question in event
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
if (avatarRef.current) {
|
|
180
190
|
avatarRef.current.setMood("curious");
|
|
181
191
|
|
|
182
192
|
// Play custom animation if available
|
|
@@ -188,17 +198,18 @@ const CurriculumLearning = forwardRef(({
|
|
|
188
198
|
}
|
|
189
199
|
}
|
|
190
200
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
201
|
+
if (firstQuestion) {
|
|
202
|
+
// If there's a question, introduce it directly
|
|
203
|
+
if (firstQuestion.type === 'code_test') {
|
|
204
|
+
avatarRef.current.speakText(`Let's test your coding skills! Here's your first challenge: ${firstQuestion.question}`);
|
|
205
|
+
} else {
|
|
206
|
+
avatarRef.current.speakText(`Now let me ask you some questions. Here's the first one: ${firstQuestion.question}`);
|
|
207
|
+
}
|
|
208
|
+
} else {
|
|
209
|
+
avatarRef.current.speakText("Now let me ask you some questions to test your understanding.");
|
|
210
|
+
}
|
|
200
211
|
}
|
|
201
|
-
}, [animations.questionStart, getCurrentLesson]);
|
|
212
|
+
}, [animations.questionStart, getCurrentLesson, getCurrentQuestion]);
|
|
202
213
|
|
|
203
214
|
// Move to next question
|
|
204
215
|
const nextQuestion = useCallback(() => {
|
|
@@ -206,33 +217,44 @@ const CurriculumLearning = forwardRef(({
|
|
|
206
217
|
if (stateRef.current.currentQuestionIndex < (currentLesson?.questions?.length || 0) - 1) {
|
|
207
218
|
stateRef.current.currentQuestionIndex += 1;
|
|
208
219
|
|
|
209
|
-
|
|
210
|
-
|
|
220
|
+
// Trigger custom action BEFORE speaking (so UI can update immediately)
|
|
221
|
+
const nextQuestionObj = getCurrentQuestion();
|
|
222
|
+
callbacksRef.current.onCustomAction({
|
|
223
|
+
type: 'nextQuestion',
|
|
224
|
+
moduleIndex: stateRef.current.currentModuleIndex,
|
|
225
|
+
lessonIndex: stateRef.current.currentLessonIndex,
|
|
226
|
+
questionIndex: stateRef.current.currentQuestionIndex,
|
|
227
|
+
question: nextQuestionObj
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
if (avatarRef.current) {
|
|
231
|
+
avatarRef.current.setMood("happy");
|
|
211
232
|
avatarRef.current.setBodyMovement("idle");
|
|
212
233
|
|
|
213
234
|
// Play custom animation if available
|
|
214
235
|
if (animations.nextQuestion) {
|
|
215
|
-
|
|
236
|
+
try {
|
|
216
237
|
avatarRef.current.playAnimation(animations.nextQuestion, true);
|
|
217
|
-
|
|
238
|
+
} catch (error) {
|
|
218
239
|
console.warn('Failed to play nextQuestion animation:', error);
|
|
219
240
|
}
|
|
220
241
|
}
|
|
221
242
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
243
|
+
if (nextQuestionObj) {
|
|
244
|
+
// Speak the question text directly if it's a code test, otherwise introduce it
|
|
245
|
+
if (nextQuestionObj.type === 'code_test') {
|
|
246
|
+
avatarRef.current.speakText(`Here's your next coding challenge: ${nextQuestionObj.question}`);
|
|
247
|
+
} else {
|
|
248
|
+
avatarRef.current.speakText(`Here's the next question: ${nextQuestionObj.question}`);
|
|
249
|
+
}
|
|
250
|
+
} else {
|
|
251
|
+
avatarRef.current.speakText("Here's the next question.");
|
|
252
|
+
}
|
|
231
253
|
}
|
|
232
254
|
} else {
|
|
233
255
|
completeLesson();
|
|
234
256
|
}
|
|
235
|
-
}, [animations.nextQuestion, getCurrentLesson, completeLesson]);
|
|
257
|
+
}, [animations.nextQuestion, getCurrentLesson, completeLesson, getCurrentQuestion]);
|
|
236
258
|
|
|
237
259
|
// Move to next lesson
|
|
238
260
|
const nextLesson = useCallback(() => {
|
|
@@ -352,8 +374,26 @@ const CurriculumLearning = forwardRef(({
|
|
|
352
374
|
: `Not quite right, but don't worry! ${currentQuestion.explanation || ''} Let's move on to the next question.`;
|
|
353
375
|
avatarRef.current.speakText(failureMessage);
|
|
354
376
|
}
|
|
377
|
+
|
|
378
|
+
// Automatically move to next question after avatar finishes speaking
|
|
379
|
+
// Estimate speaking time: ~150 characters per second, minimum 2 seconds
|
|
380
|
+
const messageLength = (isCorrect
|
|
381
|
+
? (currentQuestion.type === "code_test"
|
|
382
|
+
? `Great job! Your code passed all the tests! ${currentQuestion.explanation || ''}`
|
|
383
|
+
: `Excellent! That's correct! ${currentQuestion.explanation || ''}`)
|
|
384
|
+
: (currentQuestion.type === "code_test"
|
|
385
|
+
? `Your code didn't pass all the tests. ${currentQuestion.explanation || 'Try again!'}`
|
|
386
|
+
: `Not quite right, but don't worry! ${currentQuestion.explanation || ''} Let's move on to the next question.`)).length;
|
|
387
|
+
const estimatedTime = Math.max(2000, (messageLength / 150) * 1000) + 500; // Add 500ms buffer
|
|
388
|
+
|
|
389
|
+
setTimeout(() => {
|
|
390
|
+
nextQuestion();
|
|
391
|
+
}, estimatedTime);
|
|
392
|
+
} else {
|
|
393
|
+
// If avatar not ready, move to next question immediately
|
|
394
|
+
nextQuestion();
|
|
355
395
|
}
|
|
356
|
-
}, [animations.correct, animations.incorrect, getCurrentQuestion, checkAnswer]);
|
|
396
|
+
}, [animations.correct, animations.incorrect, getCurrentQuestion, checkAnswer, nextQuestion]);
|
|
357
397
|
|
|
358
398
|
// Handle code test result submission
|
|
359
399
|
const handleCodeTestResult = useCallback((testResult) => {
|