@hexar/biometric-identity-sdk-react-native 1.1.18 → 1.1.20
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/components/ProfilePictureCapture.d.ts.map +1 -1
- package/dist/components/ProfilePictureCapture.js +0 -11
- package/dist/components/VideoRecorder.d.ts.map +1 -1
- package/dist/components/VideoRecorder.js +35 -20
- package/package.json +1 -1
- package/src/components/ProfilePictureCapture.tsx +0 -12
- package/src/components/VideoRecorder.tsx +37 -21
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProfilePictureCapture.d.ts","sourceRoot":"","sources":["../../src/components/ProfilePictureCapture.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AASxE,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAmC,cAAc,EAAsB,MAAM,oCAAoC,CAAC;AAGzJ,MAAM,WAAW,8BAA8B;IAC7C,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,CAAC,MAAM,EAAE,8BAA8B,KAAK,IAAI,CAAC;IAC7D,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IACzC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAED,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,0BAA0B,
|
|
1
|
+
{"version":3,"file":"ProfilePictureCapture.d.ts","sourceRoot":"","sources":["../../src/components/ProfilePictureCapture.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AASxE,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAmC,cAAc,EAAsB,MAAM,oCAAoC,CAAC;AAGzJ,MAAM,WAAW,8BAA8B;IAC7C,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,CAAC,MAAM,EAAE,8BAA8B,KAAK,IAAI,CAAC;IAC7D,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IACzC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAED,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,0BAA0B,CAqOtE,CAAC;AAuBF,eAAe,qBAAqB,CAAC"}
|
|
@@ -105,17 +105,6 @@ const ProfilePictureCapture = ({ onComplete, onError, onCancel, theme, language,
|
|
|
105
105
|
biometric_identity_sdk_core_1.logger.error('Session ID not available after attempting to generate');
|
|
106
106
|
throw new Error('VALIDATION_ERROR');
|
|
107
107
|
}
|
|
108
|
-
biometric_identity_sdk_core_1.logger.info('Validating profile picture with backend', {
|
|
109
|
-
sessionId,
|
|
110
|
-
framesCount: videoResult.frames.length,
|
|
111
|
-
duration: videoResult.duration,
|
|
112
|
-
isUsingBackend,
|
|
113
|
-
hasVideoFrames: !!videoResult.frames,
|
|
114
|
-
videoFramesType: typeof videoResult.frames,
|
|
115
|
-
firstFrameLength: videoResult.frames?.[0]?.length || 0,
|
|
116
|
-
challengesCompleted: videoResult.challengesCompleted || [],
|
|
117
|
-
challengesCompletedCount: videoResult.challengesCompleted?.length || 0,
|
|
118
|
-
});
|
|
119
108
|
if (!videoResult.frames || videoResult.frames.length === 0) {
|
|
120
109
|
throw new Error('No video frames available for validation');
|
|
121
110
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoRecorder.d.ts","sourceRoot":"","sources":["../../src/components/VideoRecorder.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAaxE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,iBAAiB,EAAmC,MAAM,oCAAoC,CAAC;AAE1I,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,YAAY,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACrC,0CAA0C;IAC1C,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wCAAwC;IACxC,UAAU,EAAE,CAAC,SAAS,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACtD,iCAAiC;IACjC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,gDAAgD;IAChD,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAiDD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,
|
|
1
|
+
{"version":3,"file":"VideoRecorder.d.ts","sourceRoot":"","sources":["../../src/components/VideoRecorder.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAaxE,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,iBAAiB,EAAmC,MAAM,oCAAoC,CAAC;AAE1I,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,YAAY,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACrC,0CAA0C;IAC1C,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wCAAwC;IACxC,UAAU,EAAE,CAAC,SAAS,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACtD,iCAAiC;IACjC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,gDAAgD;IAChD,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;CACtD;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAiDD,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAg6BtD,CAAC;AA4OF,eAAe,aAAa,CAAC"}
|
|
@@ -102,6 +102,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
102
102
|
const [challengeProgress, setChallengeProgress] = (0, react_1.useState)(0);
|
|
103
103
|
const [overallProgress, setOverallProgress] = (0, react_1.useState)(0);
|
|
104
104
|
const [completedChallenges, setCompletedChallenges] = (0, react_1.useState)([]);
|
|
105
|
+
const completedChallengesRef = (0, react_1.useRef)([]);
|
|
105
106
|
const [frames, setFrames] = (0, react_1.useState)([]);
|
|
106
107
|
const framesRef = (0, react_1.useRef)([]);
|
|
107
108
|
const [hasPermission, setHasPermission] = (0, react_1.useState)(false);
|
|
@@ -158,14 +159,6 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
158
159
|
let challengeList;
|
|
159
160
|
const currentStrings = (0, biometric_identity_sdk_core_1.getStrings)();
|
|
160
161
|
const instructionMap = getInstructionMap(currentStrings);
|
|
161
|
-
biometric_identity_sdk_core_1.logger.info('Initializing challenges', {
|
|
162
|
-
language,
|
|
163
|
-
hasStrings: !!currentStrings,
|
|
164
|
-
hasInstructions: !!currentStrings?.liveness?.instructions,
|
|
165
|
-
instructionMapKeys: Object.keys(instructionMap),
|
|
166
|
-
turnLeftTranslation: instructionMap['turn_left']?.text,
|
|
167
|
-
turnRightTranslation: instructionMap['turn_right']?.text
|
|
168
|
-
});
|
|
169
162
|
if (propChallenges && propChallenges.length > 0) {
|
|
170
163
|
challengeList = propChallenges.map(challenge => ({
|
|
171
164
|
...challenge,
|
|
@@ -280,6 +273,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
280
273
|
setFrames([]);
|
|
281
274
|
framesRef.current = [];
|
|
282
275
|
setCompletedChallenges([]);
|
|
276
|
+
completedChallengesRef.current = [];
|
|
283
277
|
setCurrentChallengeIndex(0);
|
|
284
278
|
setChallengeProgress(0);
|
|
285
279
|
setOverallProgress(0);
|
|
@@ -327,15 +321,22 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
327
321
|
return;
|
|
328
322
|
}
|
|
329
323
|
biometric_identity_sdk_core_1.logger.info('Using frames for completion:', finalFrames.length, 'frames');
|
|
324
|
+
const currentCompletedChallenges = completedChallengesRef.current.length > 0 ? completedChallengesRef.current : completedChallenges;
|
|
325
|
+
biometric_identity_sdk_core_1.logger.info('VideoRecorder: handleVideoComplete - completed challenges', {
|
|
326
|
+
refCount: completedChallengesRef.current.length,
|
|
327
|
+
stateCount: completedChallenges.length,
|
|
328
|
+
usingRef: completedChallengesRef.current.length > 0,
|
|
329
|
+
challengesCompleted: currentCompletedChallenges
|
|
330
|
+
});
|
|
330
331
|
const result = {
|
|
331
332
|
frames: finalFrames,
|
|
332
333
|
duration: actualDuration,
|
|
333
|
-
instructionsFollowed:
|
|
334
|
+
instructionsFollowed: currentCompletedChallenges.length === challenges.length,
|
|
334
335
|
qualityScore: finalFrames.length > 0 ? Math.min(100, (finalFrames.length / 30) * 100) : 85,
|
|
335
|
-
challengesCompleted:
|
|
336
|
+
challengesCompleted: currentCompletedChallenges,
|
|
336
337
|
sessionId,
|
|
337
338
|
};
|
|
338
|
-
biometric_identity_sdk_core_1.logger.info('Video recording completed:', result.frames.length, 'frames,', (actualDuration / 1000).toFixed(1) + 's');
|
|
339
|
+
biometric_identity_sdk_core_1.logger.info('Video recording completed:', result.frames.length, 'frames,', (actualDuration / 1000).toFixed(1) + 's', 'challenges:', currentCompletedChallenges.length);
|
|
339
340
|
isRecordingRef.current = false;
|
|
340
341
|
onComplete(result);
|
|
341
342
|
}
|
|
@@ -449,14 +450,15 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
449
450
|
biometric_identity_sdk_core_1.logger.error('Error stopping video recording:', error);
|
|
450
451
|
const actualDuration = Date.now() - recordingStartTime.current;
|
|
451
452
|
const currentFrames = framesRef.current.length > 0 ? framesRef.current : frames;
|
|
453
|
+
const currentCompletedChallenges = completedChallengesRef.current.length > 0 ? completedChallengesRef.current : completedChallenges;
|
|
452
454
|
if (actualDuration >= minDurationMs && currentFrames.length > 0) {
|
|
453
455
|
biometric_identity_sdk_core_1.logger.info('Stopping recording with frames:', currentFrames.length);
|
|
454
456
|
const result = {
|
|
455
457
|
frames: currentFrames,
|
|
456
458
|
duration: actualDuration,
|
|
457
|
-
instructionsFollowed:
|
|
459
|
+
instructionsFollowed: currentCompletedChallenges.length === challenges.length,
|
|
458
460
|
qualityScore: Math.min(100, (currentFrames.length / 30) * 100),
|
|
459
|
-
challengesCompleted:
|
|
461
|
+
challengesCompleted: currentCompletedChallenges,
|
|
460
462
|
sessionId,
|
|
461
463
|
};
|
|
462
464
|
onComplete(result);
|
|
@@ -466,9 +468,9 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
466
468
|
const result = {
|
|
467
469
|
frames: currentFrames.length > 0 ? currentFrames : [],
|
|
468
470
|
duration: actualDuration,
|
|
469
|
-
instructionsFollowed:
|
|
471
|
+
instructionsFollowed: currentCompletedChallenges.length === challenges.length,
|
|
470
472
|
qualityScore: currentFrames.length > 0 ? Math.min(100, (currentFrames.length / 30) * 100) : 0,
|
|
471
|
-
challengesCompleted:
|
|
473
|
+
challengesCompleted: currentCompletedChallenges,
|
|
472
474
|
sessionId,
|
|
473
475
|
};
|
|
474
476
|
onComplete(result);
|
|
@@ -486,13 +488,20 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
486
488
|
}
|
|
487
489
|
setPhase('processing');
|
|
488
490
|
setOverallProgress(100);
|
|
491
|
+
const currentCompletedChallenges = completedChallengesRef.current.length > 0 ? completedChallengesRef.current : completedChallenges;
|
|
492
|
+
biometric_identity_sdk_core_1.logger.info('VideoRecorder: stopRecording - completed challenges', {
|
|
493
|
+
refCount: completedChallengesRef.current.length,
|
|
494
|
+
stateCount: completedChallenges.length,
|
|
495
|
+
usingRef: completedChallengesRef.current.length > 0,
|
|
496
|
+
challengesCompleted: currentCompletedChallenges
|
|
497
|
+
});
|
|
489
498
|
biometric_identity_sdk_core_1.logger.info('Completing recording with frames:', currentFrames.length);
|
|
490
499
|
const result = {
|
|
491
500
|
frames: currentFrames.length > 0 ? currentFrames : [],
|
|
492
501
|
duration: actualDuration,
|
|
493
|
-
instructionsFollowed:
|
|
502
|
+
instructionsFollowed: currentCompletedChallenges.length === challenges.length,
|
|
494
503
|
qualityScore: currentFrames.length > 0 ? Math.min(100, (currentFrames.length / 30) * 100) : 0,
|
|
495
|
-
challengesCompleted:
|
|
504
|
+
challengesCompleted: currentCompletedChallenges,
|
|
496
505
|
sessionId,
|
|
497
506
|
};
|
|
498
507
|
setTimeout(() => {
|
|
@@ -501,11 +510,12 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
501
510
|
}
|
|
502
511
|
}, [frames, completedChallenges, challenges, sessionId, onComplete, minDurationMs, resetAndRetry, strings]);
|
|
503
512
|
const runChallenge = (0, react_1.useCallback)((index) => {
|
|
513
|
+
const currentCompletedChallenges = completedChallengesRef.current.length > 0 ? completedChallengesRef.current : completedChallenges;
|
|
504
514
|
biometric_identity_sdk_core_1.logger.info('VideoRecorder: runChallenge called', {
|
|
505
515
|
index,
|
|
506
516
|
challengesLength: challenges.length,
|
|
507
517
|
challengeActions: challenges.map(c => c.action),
|
|
508
|
-
completedChallengesCount:
|
|
518
|
+
completedChallengesCount: currentCompletedChallenges.length
|
|
509
519
|
});
|
|
510
520
|
if (index >= challenges.length) {
|
|
511
521
|
setOverallProgress(100);
|
|
@@ -528,13 +538,14 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
528
538
|
}
|
|
529
539
|
else {
|
|
530
540
|
const actualDuration = Date.now() - recordingStartTime.current;
|
|
541
|
+
const currentCompletedChallenges = completedChallengesRef.current.length > 0 ? completedChallengesRef.current : completedChallenges;
|
|
531
542
|
if (actualDuration >= minDurationMs && frames.length > 0) {
|
|
532
543
|
const result = {
|
|
533
544
|
frames,
|
|
534
545
|
duration: actualDuration,
|
|
535
|
-
instructionsFollowed:
|
|
546
|
+
instructionsFollowed: currentCompletedChallenges.length === challenges.length,
|
|
536
547
|
qualityScore: Math.min(100, (frames.length / 30) * 100),
|
|
537
|
-
challengesCompleted:
|
|
548
|
+
challengesCompleted: currentCompletedChallenges,
|
|
538
549
|
sessionId,
|
|
539
550
|
};
|
|
540
551
|
onComplete(result);
|
|
@@ -571,6 +582,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
571
582
|
clearInterval(progressInterval);
|
|
572
583
|
setCompletedChallenges(prev => {
|
|
573
584
|
const updated = [...prev, challenge.action];
|
|
585
|
+
completedChallengesRef.current = updated; // Keep ref in sync
|
|
574
586
|
biometric_identity_sdk_core_1.logger.info('VideoRecorder: Challenge completed', {
|
|
575
587
|
action: challenge.action,
|
|
576
588
|
index,
|
|
@@ -593,6 +605,9 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
|
|
|
593
605
|
setPhase('recording');
|
|
594
606
|
recordingStartTime.current = Date.now();
|
|
595
607
|
isRecordingRef.current = true;
|
|
608
|
+
// Reset completed challenges ref when starting new recording
|
|
609
|
+
completedChallengesRef.current = [];
|
|
610
|
+
setCompletedChallenges([]);
|
|
596
611
|
if (cameraRef.current && device) {
|
|
597
612
|
try {
|
|
598
613
|
videoRecordingRef.current = await cameraRef.current.startRecording({
|
package/package.json
CHANGED
|
@@ -112,18 +112,6 @@ export const ProfilePictureCapture: React.FC<ProfilePictureCaptureProps> = ({
|
|
|
112
112
|
throw new Error('VALIDATION_ERROR');
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
logger.info('Validating profile picture with backend', {
|
|
116
|
-
sessionId,
|
|
117
|
-
framesCount: videoResult.frames.length,
|
|
118
|
-
duration: videoResult.duration,
|
|
119
|
-
isUsingBackend,
|
|
120
|
-
hasVideoFrames: !!videoResult.frames,
|
|
121
|
-
videoFramesType: typeof videoResult.frames,
|
|
122
|
-
firstFrameLength: videoResult.frames?.[0]?.length || 0,
|
|
123
|
-
challengesCompleted: videoResult.challengesCompleted || [],
|
|
124
|
-
challengesCompletedCount: videoResult.challengesCompleted?.length || 0,
|
|
125
|
-
});
|
|
126
|
-
|
|
127
115
|
if (!videoResult.frames || videoResult.frames.length === 0) {
|
|
128
116
|
throw new Error('No video frames available for validation');
|
|
129
117
|
}
|
|
@@ -129,6 +129,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
129
129
|
const [challengeProgress, setChallengeProgress] = useState(0);
|
|
130
130
|
const [overallProgress, setOverallProgress] = useState(0);
|
|
131
131
|
const [completedChallenges, setCompletedChallenges] = useState<string[]>([]);
|
|
132
|
+
const completedChallengesRef = useRef<string[]>([]);
|
|
132
133
|
const [frames, setFrames] = useState<string[]>([]);
|
|
133
134
|
const framesRef = useRef<string[]>([]);
|
|
134
135
|
const [hasPermission, setHasPermission] = useState(false);
|
|
@@ -197,15 +198,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
197
198
|
let challengeList: ChallengeAction[];
|
|
198
199
|
const currentStrings = getStrings();
|
|
199
200
|
const instructionMap = getInstructionMap(currentStrings);
|
|
200
|
-
|
|
201
|
-
language,
|
|
202
|
-
hasStrings: !!currentStrings,
|
|
203
|
-
hasInstructions: !!currentStrings?.liveness?.instructions,
|
|
204
|
-
instructionMapKeys: Object.keys(instructionMap),
|
|
205
|
-
turnLeftTranslation: instructionMap['turn_left']?.text,
|
|
206
|
-
turnRightTranslation: instructionMap['turn_right']?.text
|
|
207
|
-
});
|
|
208
|
-
|
|
201
|
+
|
|
209
202
|
if (propChallenges && propChallenges.length > 0) {
|
|
210
203
|
challengeList = propChallenges.map(challenge => ({
|
|
211
204
|
...challenge,
|
|
@@ -327,6 +320,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
327
320
|
setFrames([]);
|
|
328
321
|
framesRef.current = [];
|
|
329
322
|
setCompletedChallenges([]);
|
|
323
|
+
completedChallengesRef.current = [];
|
|
330
324
|
setCurrentChallengeIndex(0);
|
|
331
325
|
setChallengeProgress(0);
|
|
332
326
|
setOverallProgress(0);
|
|
@@ -392,16 +386,24 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
392
386
|
|
|
393
387
|
logger.info('Using frames for completion:', finalFrames.length, 'frames');
|
|
394
388
|
|
|
389
|
+
const currentCompletedChallenges = completedChallengesRef.current.length > 0 ? completedChallengesRef.current : completedChallenges;
|
|
390
|
+
logger.info('VideoRecorder: handleVideoComplete - completed challenges', {
|
|
391
|
+
refCount: completedChallengesRef.current.length,
|
|
392
|
+
stateCount: completedChallenges.length,
|
|
393
|
+
usingRef: completedChallengesRef.current.length > 0,
|
|
394
|
+
challengesCompleted: currentCompletedChallenges
|
|
395
|
+
});
|
|
396
|
+
|
|
395
397
|
const result: VideoRecordingResult = {
|
|
396
398
|
frames: finalFrames,
|
|
397
399
|
duration: actualDuration,
|
|
398
|
-
instructionsFollowed:
|
|
400
|
+
instructionsFollowed: currentCompletedChallenges.length === challenges.length,
|
|
399
401
|
qualityScore: finalFrames.length > 0 ? Math.min(100, (finalFrames.length / 30) * 100) : 85,
|
|
400
|
-
challengesCompleted:
|
|
402
|
+
challengesCompleted: currentCompletedChallenges,
|
|
401
403
|
sessionId,
|
|
402
404
|
};
|
|
403
405
|
|
|
404
|
-
logger.info('Video recording completed:', result.frames.length, 'frames,', (actualDuration / 1000).toFixed(1) + 's');
|
|
406
|
+
logger.info('Video recording completed:', result.frames.length, 'frames,', (actualDuration / 1000).toFixed(1) + 's', 'challenges:', currentCompletedChallenges.length);
|
|
405
407
|
|
|
406
408
|
isRecordingRef.current = false;
|
|
407
409
|
onComplete(result);
|
|
@@ -522,14 +524,15 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
522
524
|
const actualDuration = Date.now() - recordingStartTime.current;
|
|
523
525
|
const currentFrames = framesRef.current.length > 0 ? framesRef.current : frames;
|
|
524
526
|
|
|
527
|
+
const currentCompletedChallenges = completedChallengesRef.current.length > 0 ? completedChallengesRef.current : completedChallenges;
|
|
525
528
|
if (actualDuration >= minDurationMs && currentFrames.length > 0) {
|
|
526
529
|
logger.info('Stopping recording with frames:', currentFrames.length);
|
|
527
530
|
const result: VideoRecordingResult = {
|
|
528
531
|
frames: currentFrames,
|
|
529
532
|
duration: actualDuration,
|
|
530
|
-
instructionsFollowed:
|
|
533
|
+
instructionsFollowed: currentCompletedChallenges.length === challenges.length,
|
|
531
534
|
qualityScore: Math.min(100, (currentFrames.length / 30) * 100),
|
|
532
|
-
challengesCompleted:
|
|
535
|
+
challengesCompleted: currentCompletedChallenges,
|
|
533
536
|
sessionId,
|
|
534
537
|
};
|
|
535
538
|
onComplete(result);
|
|
@@ -538,9 +541,9 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
538
541
|
const result: VideoRecordingResult = {
|
|
539
542
|
frames: currentFrames.length > 0 ? currentFrames : [],
|
|
540
543
|
duration: actualDuration,
|
|
541
|
-
instructionsFollowed:
|
|
544
|
+
instructionsFollowed: currentCompletedChallenges.length === challenges.length,
|
|
542
545
|
qualityScore: currentFrames.length > 0 ? Math.min(100, (currentFrames.length / 30) * 100) : 0,
|
|
543
|
-
challengesCompleted:
|
|
546
|
+
challengesCompleted: currentCompletedChallenges,
|
|
544
547
|
sessionId,
|
|
545
548
|
};
|
|
546
549
|
onComplete(result);
|
|
@@ -564,13 +567,20 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
564
567
|
setPhase('processing');
|
|
565
568
|
setOverallProgress(100);
|
|
566
569
|
|
|
570
|
+
const currentCompletedChallenges = completedChallengesRef.current.length > 0 ? completedChallengesRef.current : completedChallenges;
|
|
571
|
+
logger.info('VideoRecorder: stopRecording - completed challenges', {
|
|
572
|
+
refCount: completedChallengesRef.current.length,
|
|
573
|
+
stateCount: completedChallenges.length,
|
|
574
|
+
usingRef: completedChallengesRef.current.length > 0,
|
|
575
|
+
challengesCompleted: currentCompletedChallenges
|
|
576
|
+
});
|
|
567
577
|
logger.info('Completing recording with frames:', currentFrames.length);
|
|
568
578
|
const result: VideoRecordingResult = {
|
|
569
579
|
frames: currentFrames.length > 0 ? currentFrames : [],
|
|
570
580
|
duration: actualDuration,
|
|
571
|
-
instructionsFollowed:
|
|
581
|
+
instructionsFollowed: currentCompletedChallenges.length === challenges.length,
|
|
572
582
|
qualityScore: currentFrames.length > 0 ? Math.min(100, (currentFrames.length / 30) * 100) : 0,
|
|
573
|
-
challengesCompleted:
|
|
583
|
+
challengesCompleted: currentCompletedChallenges,
|
|
574
584
|
sessionId,
|
|
575
585
|
};
|
|
576
586
|
|
|
@@ -581,11 +591,12 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
581
591
|
}, [frames, completedChallenges, challenges, sessionId, onComplete, minDurationMs, resetAndRetry, strings]);
|
|
582
592
|
|
|
583
593
|
const runChallenge = useCallback((index: number) => {
|
|
594
|
+
const currentCompletedChallenges = completedChallengesRef.current.length > 0 ? completedChallengesRef.current : completedChallenges;
|
|
584
595
|
logger.info('VideoRecorder: runChallenge called', {
|
|
585
596
|
index,
|
|
586
597
|
challengesLength: challenges.length,
|
|
587
598
|
challengeActions: challenges.map(c => c.action),
|
|
588
|
-
completedChallengesCount:
|
|
599
|
+
completedChallengesCount: currentCompletedChallenges.length
|
|
589
600
|
});
|
|
590
601
|
|
|
591
602
|
if (index >= challenges.length) {
|
|
@@ -612,13 +623,14 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
612
623
|
stopRecording();
|
|
613
624
|
} else {
|
|
614
625
|
const actualDuration = Date.now() - recordingStartTime.current;
|
|
626
|
+
const currentCompletedChallenges = completedChallengesRef.current.length > 0 ? completedChallengesRef.current : completedChallenges;
|
|
615
627
|
if (actualDuration >= minDurationMs && frames.length > 0) {
|
|
616
628
|
const result: VideoRecordingResult = {
|
|
617
629
|
frames,
|
|
618
630
|
duration: actualDuration,
|
|
619
|
-
instructionsFollowed:
|
|
631
|
+
instructionsFollowed: currentCompletedChallenges.length === challenges.length,
|
|
620
632
|
qualityScore: Math.min(100, (frames.length / 30) * 100),
|
|
621
|
-
challengesCompleted:
|
|
633
|
+
challengesCompleted: currentCompletedChallenges,
|
|
622
634
|
sessionId,
|
|
623
635
|
};
|
|
624
636
|
onComplete(result);
|
|
@@ -663,6 +675,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
663
675
|
|
|
664
676
|
setCompletedChallenges(prev => {
|
|
665
677
|
const updated = [...prev, challenge.action];
|
|
678
|
+
completedChallengesRef.current = updated; // Keep ref in sync
|
|
666
679
|
logger.info('VideoRecorder: Challenge completed', {
|
|
667
680
|
action: challenge.action,
|
|
668
681
|
index,
|
|
@@ -687,6 +700,9 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
|
|
|
687
700
|
setPhase('recording');
|
|
688
701
|
recordingStartTime.current = Date.now();
|
|
689
702
|
isRecordingRef.current = true;
|
|
703
|
+
// Reset completed challenges ref when starting new recording
|
|
704
|
+
completedChallengesRef.current = [];
|
|
705
|
+
setCompletedChallenges([]);
|
|
690
706
|
|
|
691
707
|
if (cameraRef.current && device) {
|
|
692
708
|
try {
|