@hexar/biometric-identity-sdk-react-native 1.1.15 → 1.1.17

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.
@@ -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,CAmNtE,CAAC;AAuBF,eAAe,qBAAqB,CAAC"}
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,CAiPtE,CAAC;AAuBF,eAAe,qBAAqB,CAAC"}
@@ -58,16 +58,25 @@ const ProfilePictureCapture = ({ onComplete, onError, onCancel, theme, language,
58
58
  setIsLoadingChallenges(true);
59
59
  try {
60
60
  const challenges = await fetchChallenges('active');
61
+ biometric_identity_sdk_core_1.logger.info('ProfilePictureCapture: Challenges loaded', {
62
+ challengeCount: challenges.length,
63
+ challenges: challenges.map(c => c.action)
64
+ });
61
65
  setCurrentChallenges(challenges);
62
66
  }
63
67
  catch (error) {
64
- biometric_identity_sdk_core_1.logger.warn('Failed to fetch challenges, VideoRecorder will use defaults');
68
+ biometric_identity_sdk_core_1.logger.warn('Failed to fetch challenges, VideoRecorder will use defaults', error);
65
69
  setCurrentChallenges([]);
66
70
  }
67
71
  setIsLoadingChallenges(false);
68
72
  };
69
73
  loadChallenges();
70
74
  }
75
+ else if (isInitialized) {
76
+ // If not using backend, still initialize with empty array (VideoRecorder will use defaults)
77
+ setCurrentChallenges([]);
78
+ setIsLoadingChallenges(false);
79
+ }
71
80
  }, [isInitialized, isUsingBackend, fetchChallenges]);
72
81
  const strings = (0, biometric_identity_sdk_core_1.getStrings)();
73
82
  const validateWithBackend = (0, react_1.useCallback)(async (videoResult) => {
@@ -142,6 +151,13 @@ const ProfilePictureCapture = ({ onComplete, onError, onCancel, theme, language,
142
151
  }
143
152
  }, [isInitialized, isUsingBackend, sdk]);
144
153
  const handleVideoComplete = (0, react_1.useCallback)(async (videoResult) => {
154
+ biometric_identity_sdk_core_1.logger.info('ProfilePictureCapture: Video recording completed', {
155
+ framesCount: videoResult.frames?.length || 0,
156
+ duration: videoResult.duration,
157
+ challengesCompleted: videoResult.challengesCompleted || [],
158
+ challengesCompletedCount: videoResult.challengesCompleted?.length || 0,
159
+ expectedChallengesCount: currentChallenges.length,
160
+ });
145
161
  setIsValidating(true);
146
162
  try {
147
163
  const result = await validateWithBackend(videoResult);
@@ -185,7 +201,7 @@ const ProfilePictureCapture = ({ onComplete, onError, onCancel, theme, language,
185
201
  };
186
202
  onError(biometricError);
187
203
  }
188
- }, [validateWithBackend, onComplete, onError, strings, language]);
204
+ }, [validateWithBackend, onComplete, onError, strings, language, currentChallenges]);
189
205
  const handleVideoCancel = (0, react_1.useCallback)(() => {
190
206
  if (onCancel) {
191
207
  onCancel();
@@ -198,6 +214,13 @@ const ProfilePictureCapture = ({ onComplete, onError, onCancel, theme, language,
198
214
  react_1.default.createElement(react_native_1.Text, { style: [styles.loadingText, { color: theme?.textColor || '#1e1b4b' }] }, strings.liveness.processing || strings.validation.checkingLiveness || 'Processing...'),
199
215
  react_1.default.createElement(react_native_1.Text, { style: [styles.loadingSubtext, { color: theme?.secondaryTextColor || '#64748b' }] }, strings.validation.almostDone || strings.common.loading || 'This may take a few seconds'))));
200
216
  }
217
+ // Wait for initialization and challenge loading before showing VideoRecorder
218
+ if (!isInitialized || (isUsingBackend && isLoadingChallenges)) {
219
+ return (react_1.default.createElement(react_native_1.SafeAreaView, { style: [styles.container, { backgroundColor: theme?.backgroundColor || '#FFFFFF' }] },
220
+ react_1.default.createElement(react_native_1.View, { style: styles.loadingContainer },
221
+ react_1.default.createElement(react_native_1.ActivityIndicator, { size: "large", color: theme?.primaryColor || '#4f46e5' }),
222
+ react_1.default.createElement(react_native_1.Text, { style: [styles.loadingText, { color: theme?.textColor || '#1e1b4b' }] }, strings.liveness.preparing || 'Preparing...'))));
223
+ }
201
224
  return (react_1.default.createElement(VideoRecorder_1.VideoRecorder, { theme: theme, language: language, smartMode: true, challenges: currentChallenges, sessionId: sdk.getSessionId() || undefined, onComplete: handleVideoComplete, onCancel: handleVideoCancel, onFetchChallenges: handleFetchChallenges }));
202
225
  };
203
226
  exports.ProfilePictureCapture = ProfilePictureCapture;
@@ -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,CAi3BtD,CAAC;AA4OF,eAAe,aAAa,CAAC"}
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,CAi2BtD,CAAC;AA4OF,eAAe,aAAa,CAAC"}
@@ -320,30 +320,15 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
320
320
  return;
321
321
  }
322
322
  biometric_identity_sdk_core_1.logger.info('Using frames for completion:', finalFrames.length, 'frames');
323
- let finalCompletedChallenges = completedChallenges;
324
- if (smartMode && finalCompletedChallenges.length === 0) {
325
- const challengesToUse = challenges.length > 0 ? challenges : propChallenges || [];
326
- if (challengesToUse.length > 0) {
327
- finalCompletedChallenges = challengesToUse.map(c => c.action);
328
- }
329
- }
330
323
  const result = {
331
324
  frames: finalFrames,
332
325
  duration: actualDuration,
333
- instructionsFollowed: finalCompletedChallenges.length === challenges.length,
326
+ instructionsFollowed: completedChallenges.length === challenges.length,
334
327
  qualityScore: finalFrames.length > 0 ? Math.min(100, (finalFrames.length / 30) * 100) : 85,
335
- challengesCompleted: finalCompletedChallenges,
328
+ challengesCompleted: completedChallenges,
336
329
  sessionId,
337
330
  };
338
- biometric_identity_sdk_core_1.logger.info('Video recording completed:', {
339
- frames: result.frames.length,
340
- duration: (actualDuration / 1000).toFixed(1) + 's',
341
- challengesCompleted: result.challengesCompleted,
342
- challengesCompletedCount: result.challengesCompleted.length,
343
- smartMode,
344
- challengesLength: challenges.length,
345
- propChallengesLength: propChallenges?.length || 0
346
- });
331
+ biometric_identity_sdk_core_1.logger.info('Video recording completed:', result.frames.length, 'frames,', (actualDuration / 1000).toFixed(1) + 's');
347
332
  isRecordingRef.current = false;
348
333
  onComplete(result);
349
334
  }
@@ -353,7 +338,7 @@ const VideoRecorder = ({ theme, language, duration, instructions, challenges: pr
353
338
  setOverallProgress(0);
354
339
  handleRecordingError(error);
355
340
  }
356
- }, [frames, completedChallenges, challenges, propChallenges, sessionId, onComplete, resetAndRetry, handleRecordingError, strings, minDurationMs, phase, smartMode]);
341
+ }, [frames, completedChallenges, challenges, sessionId, onComplete, resetAndRetry, handleRecordingError, strings, minDurationMs, phase]);
357
342
  const startFrameCapture = (0, react_1.useCallback)(() => {
358
343
  if (cameraRef.current && device) {
359
344
  biometric_identity_sdk_core_1.logger.info('Starting frame capture');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hexar/biometric-identity-sdk-react-native",
3
- "version": "1.1.15",
3
+ "version": "1.1.17",
4
4
  "description": "React Native wrapper for Biometric Identity SDK",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -61,14 +61,22 @@ export const ProfilePictureCapture: React.FC<ProfilePictureCaptureProps> = ({
61
61
  setIsLoadingChallenges(true);
62
62
  try {
63
63
  const challenges = await fetchChallenges('active');
64
+ logger.info('ProfilePictureCapture: Challenges loaded', {
65
+ challengeCount: challenges.length,
66
+ challenges: challenges.map(c => c.action)
67
+ });
64
68
  setCurrentChallenges(challenges);
65
69
  } catch (error) {
66
- logger.warn('Failed to fetch challenges, VideoRecorder will use defaults');
70
+ logger.warn('Failed to fetch challenges, VideoRecorder will use defaults', error);
67
71
  setCurrentChallenges([]);
68
72
  }
69
73
  setIsLoadingChallenges(false);
70
74
  };
71
75
  loadChallenges();
76
+ } else if (isInitialized) {
77
+ // If not using backend, still initialize with empty array (VideoRecorder will use defaults)
78
+ setCurrentChallenges([]);
79
+ setIsLoadingChallenges(false);
72
80
  }
73
81
  }, [isInitialized, isUsingBackend, fetchChallenges]);
74
82
 
@@ -154,6 +162,14 @@ export const ProfilePictureCapture: React.FC<ProfilePictureCaptureProps> = ({
154
162
  }, [isInitialized, isUsingBackend, sdk]);
155
163
 
156
164
  const handleVideoComplete = useCallback(async (videoResult: VideoRecordingResult) => {
165
+ logger.info('ProfilePictureCapture: Video recording completed', {
166
+ framesCount: videoResult.frames?.length || 0,
167
+ duration: videoResult.duration,
168
+ challengesCompleted: videoResult.challengesCompleted || [],
169
+ challengesCompletedCount: videoResult.challengesCompleted?.length || 0,
170
+ expectedChallengesCount: currentChallenges.length,
171
+ });
172
+
157
173
  setIsValidating(true);
158
174
 
159
175
  try {
@@ -201,7 +217,7 @@ export const ProfilePictureCapture: React.FC<ProfilePictureCaptureProps> = ({
201
217
  } as BiometricError;
202
218
  onError(biometricError);
203
219
  }
204
- }, [validateWithBackend, onComplete, onError, strings, language]);
220
+ }, [validateWithBackend, onComplete, onError, strings, language, currentChallenges]);
205
221
 
206
222
  const handleVideoCancel = useCallback(() => {
207
223
  if (onCancel) {
@@ -225,6 +241,20 @@ export const ProfilePictureCapture: React.FC<ProfilePictureCaptureProps> = ({
225
241
  );
226
242
  }
227
243
 
244
+ // Wait for initialization and challenge loading before showing VideoRecorder
245
+ if (!isInitialized || (isUsingBackend && isLoadingChallenges)) {
246
+ return (
247
+ <SafeAreaView style={[styles.container, { backgroundColor: theme?.backgroundColor || '#FFFFFF' }]}>
248
+ <View style={styles.loadingContainer}>
249
+ <ActivityIndicator size="large" color={theme?.primaryColor || '#4f46e5'} />
250
+ <Text style={[styles.loadingText, { color: theme?.textColor || '#1e1b4b' }]}>
251
+ {strings.liveness.preparing || 'Preparing...'}
252
+ </Text>
253
+ </View>
254
+ </SafeAreaView>
255
+ );
256
+ }
257
+
228
258
  return (
229
259
  <VideoRecorder
230
260
  theme={theme}
@@ -385,32 +385,16 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
385
385
 
386
386
  logger.info('Using frames for completion:', finalFrames.length, 'frames');
387
387
 
388
- let finalCompletedChallenges = completedChallenges;
389
- if (smartMode && finalCompletedChallenges.length === 0) {
390
- const challengesToUse = challenges.length > 0 ? challenges : propChallenges || [];
391
- if (challengesToUse.length > 0) {
392
- finalCompletedChallenges = challengesToUse.map(c => c.action);
393
- }
394
- }
395
-
396
388
  const result: VideoRecordingResult = {
397
389
  frames: finalFrames,
398
390
  duration: actualDuration,
399
- instructionsFollowed: finalCompletedChallenges.length === challenges.length,
391
+ instructionsFollowed: completedChallenges.length === challenges.length,
400
392
  qualityScore: finalFrames.length > 0 ? Math.min(100, (finalFrames.length / 30) * 100) : 85,
401
- challengesCompleted: finalCompletedChallenges,
393
+ challengesCompleted: completedChallenges,
402
394
  sessionId,
403
395
  };
404
396
 
405
- logger.info('Video recording completed:', {
406
- frames: result.frames.length,
407
- duration: (actualDuration / 1000).toFixed(1) + 's',
408
- challengesCompleted: result.challengesCompleted,
409
- challengesCompletedCount: result.challengesCompleted.length,
410
- smartMode,
411
- challengesLength: challenges.length,
412
- propChallengesLength: propChallenges?.length || 0
413
- });
397
+ logger.info('Video recording completed:', result.frames.length, 'frames,', (actualDuration / 1000).toFixed(1) + 's');
414
398
 
415
399
  isRecordingRef.current = false;
416
400
  onComplete(result);
@@ -420,7 +404,7 @@ export const VideoRecorder: React.FC<VideoRecorderProps> = ({
420
404
  setOverallProgress(0);
421
405
  handleRecordingError(error);
422
406
  }
423
- }, [frames, completedChallenges, challenges, propChallenges, sessionId, onComplete, resetAndRetry, handleRecordingError, strings, minDurationMs, phase, smartMode]);
407
+ }, [frames, completedChallenges, challenges, sessionId, onComplete, resetAndRetry, handleRecordingError, strings, minDurationMs, phase]);
424
408
 
425
409
  const startFrameCapture = useCallback(() => {
426
410
  if (cameraRef.current && device) {