feat: enhance selfie verification process with auto-start feature and improved error handling
This commit is contained in:
parent
5b2806f0bb
commit
19687320ee
|
@ -639,6 +639,7 @@ class FaceLivenessController extends GetxController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Verify that the captured image contains a face
|
// Verify that the captured image contains a face
|
||||||
Future<bool> _verifyFaceInImage(XFile image) async {
|
Future<bool> _verifyFaceInImage(XFile image) async {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'dart:developer' as dev;
|
import 'dart:developer' as dev;
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
@ -30,6 +31,9 @@ class SelfieVerificationController extends GetxController {
|
||||||
final isPerformingLivenessCheck = false.obs;
|
final isPerformingLivenessCheck = false.obs;
|
||||||
final isLivenessCheckPassed = false.obs;
|
final isLivenessCheckPassed = false.obs;
|
||||||
|
|
||||||
|
// New flag for auto starting verification
|
||||||
|
bool autoStartVerification = false;
|
||||||
|
|
||||||
// Face comparison results
|
// Face comparison results
|
||||||
final isComparingWithIDCard = false.obs;
|
final isComparingWithIDCard = false.obs;
|
||||||
final isMatchWithIDCard = false.obs;
|
final isMatchWithIDCard = false.obs;
|
||||||
|
@ -52,20 +56,54 @@ class SelfieVerificationController extends GetxController {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _initializeAfterDependencies() {
|
void _initializeAfterDependencies() {
|
||||||
// Listen for changes to selfieImage
|
// Listen for changes to selfieImage with improved null safety
|
||||||
ever(selfieImage, (XFile? image) {
|
ever(selfieImage, (XFile? image) {
|
||||||
if (image != null) {
|
dev.log(
|
||||||
// When a selfie is set (after liveness check),
|
'Selfie image changed: ${image?.path}',
|
||||||
// automatically verify it against ID card
|
name: 'SELFIE_VERIFICATION',
|
||||||
_processCapturedLivenessImage();
|
);
|
||||||
|
|
||||||
|
if (image != null && autoStartVerification) {
|
||||||
|
// When returning from liveness check with a selfie,
|
||||||
|
// immediately start verification with a delay for UI to update
|
||||||
|
autoStartVerification = false; // Reset flag
|
||||||
|
|
||||||
|
Future.delayed(Duration(milliseconds: 500), () {
|
||||||
|
startFaceVerification();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method to perform liveness detection
|
// Add public method to start verification process with better error handling
|
||||||
|
void startFaceVerification() {
|
||||||
|
if (selfieImage.value == null) {
|
||||||
|
dev.log(
|
||||||
|
'Cannot start verification - no selfie image!',
|
||||||
|
name: 'SELFIE_VERIFICATION',
|
||||||
|
);
|
||||||
|
selfieError.value = 'No selfie image available for verification';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isVerifyingFace.value || isComparingWithIDCard.value) {
|
||||||
|
dev.log('Verification already in progress', name: 'SELFIE_VERIFICATION');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev.log(
|
||||||
|
'Starting face verification with image: ${selfieImage.value!.path}',
|
||||||
|
name: 'SELFIE_VERIFICATION',
|
||||||
|
);
|
||||||
|
|
||||||
|
_processCapturedLivenessImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to perform liveness detection with improved navigation
|
||||||
void performLivenessDetection() async {
|
void performLivenessDetection() async {
|
||||||
try {
|
try {
|
||||||
isPerformingLivenessCheck.value = true;
|
isPerformingLivenessCheck.value = true;
|
||||||
|
autoStartVerification = true; // Set flag for auto verification
|
||||||
|
|
||||||
// Check if FaceLivenessController is already registered
|
// Check if FaceLivenessController is already registered
|
||||||
final bool hasExistingController =
|
final bool hasExistingController =
|
||||||
|
@ -79,38 +117,86 @@ class SelfieVerificationController extends GetxController {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register a new controller (will be done automatically by the widget)
|
// Register a new controller (will be done automatically by the widget)
|
||||||
final result = await Get.toNamed(AppRoutes.livenessDetection);
|
final result = await Get.toNamed(
|
||||||
|
AppRoutes.livenessDetection,
|
||||||
|
preventDuplicates: false, // Allow navigation to same route if needed
|
||||||
|
);
|
||||||
|
|
||||||
|
// Handle the result based on what was returned
|
||||||
if (result is XFile) {
|
if (result is XFile) {
|
||||||
// Liveness check passed and returned an image
|
// Liveness check passed and returned an image
|
||||||
|
dev.log(
|
||||||
|
'Received result from liveness detection, setting selfie image',
|
||||||
|
name: 'SELFIE_VERIFICATION',
|
||||||
|
);
|
||||||
|
|
||||||
selfieImage.value = result;
|
selfieImage.value = result;
|
||||||
isLivenessCheckPassed.value = true;
|
isLivenessCheckPassed.value = true;
|
||||||
|
isPerformingLivenessCheck.value = false;
|
||||||
|
|
||||||
// The _processCapturedLivenessImage will be called automatically
|
// The _processCapturedLivenessImage will be called automatically
|
||||||
// due to the ever() listener we set up in onInit
|
// due to the ever() listener we set up in onInit
|
||||||
|
} else if (result == 'navigation_handled') {
|
||||||
|
// Special case: navigation was handled by the captured selfie view
|
||||||
|
// The user was already navigated back to this screen
|
||||||
|
dev.log(
|
||||||
|
'Navigation handled by captured selfie view',
|
||||||
|
name: 'SELFIE_VERIFICATION',
|
||||||
|
);
|
||||||
|
isPerformingLivenessCheck.value = false;
|
||||||
|
// Don't reset other states since they should be set by the captured view
|
||||||
} else {
|
} else {
|
||||||
// User cancelled or something went wrong
|
// User cancelled or something went wrong
|
||||||
|
dev.log(
|
||||||
|
'No result from liveness detection, reset states',
|
||||||
|
name: 'SELFIE_VERIFICATION',
|
||||||
|
);
|
||||||
isPerformingLivenessCheck.value = false;
|
isPerformingLivenessCheck.value = false;
|
||||||
isLivenessCheckPassed.value = false;
|
isLivenessCheckPassed.value = false;
|
||||||
|
autoStartVerification = false;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
dev.log('Error in liveness detection: $e', name: 'SELFIE_VERIFICATION');
|
dev.log('Error in liveness detection: $e', name: 'SELFIE_VERIFICATION');
|
||||||
isPerformingLivenessCheck.value = false;
|
isPerformingLivenessCheck.value = false;
|
||||||
isLivenessCheckPassed.value = false;
|
isLivenessCheckPassed.value = false;
|
||||||
selfieError.value = 'Liveness check failed: $e';
|
selfieError.value = 'Liveness check failed: $e';
|
||||||
|
autoStartVerification = false; // Reset flag on error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process the captured image after liveness check
|
// Process the captured image after liveness check with better error handling
|
||||||
Future<void> _processCapturedLivenessImage() async {
|
Future<void> _processCapturedLivenessImage() async {
|
||||||
if (selfieImage.value == null) return;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (selfieImage.value == null) {
|
||||||
|
dev.log('No selfie image to process', name: 'SELFIE_VERIFICATION');
|
||||||
|
selfieError.value = 'Missing selfie image. Please try again.';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final imagePath = selfieImage.value!.path;
|
||||||
|
if (!File(imagePath).existsSync()) {
|
||||||
|
dev.log(
|
||||||
|
'Selfie image file does not exist: $imagePath',
|
||||||
|
name: 'SELFIE_VERIFICATION',
|
||||||
|
);
|
||||||
|
selfieError.value = 'Selfie image file not found. Please try again.';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
isVerifyingFace.value = true;
|
isVerifyingFace.value = true;
|
||||||
selfieError.value = '';
|
selfieError.value = '';
|
||||||
|
|
||||||
|
dev.log(
|
||||||
|
'Processing captured image for verification: $imagePath',
|
||||||
|
name: 'SELFIE_VERIFICATION',
|
||||||
|
);
|
||||||
|
|
||||||
// Now verify that the selfie contains a valid face
|
// Now verify that the selfie contains a valid face
|
||||||
final faces = await _edgeFunctionService.detectFaces(selfieImage.value!);
|
// Use a try-catch specifically for the face detection call
|
||||||
|
try {
|
||||||
|
final faces = await _edgeFunctionService.detectFaces(
|
||||||
|
selfieImage.value!,
|
||||||
|
);
|
||||||
|
|
||||||
if (faces.isEmpty) {
|
if (faces.isEmpty) {
|
||||||
selfieError.value = 'No face detected in your selfie';
|
selfieError.value = 'No face detected in your selfie';
|
||||||
|
@ -125,9 +211,15 @@ class SelfieVerificationController extends GetxController {
|
||||||
|
|
||||||
// Now compare with ID card if available
|
// Now compare with ID card if available
|
||||||
await _compareWithIdCard();
|
await _compareWithIdCard();
|
||||||
|
} catch (e) {
|
||||||
|
dev.log('Face detection API error: $e', name: 'SELFIE_VERIFICATION');
|
||||||
|
selfieError.value = 'Error detecting face: $e';
|
||||||
|
isVerifyingFace.value = false;
|
||||||
|
isSelfieValid.value = false;
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
dev.log('Error processing selfie: $e', name: 'SELFIE_VERIFICATION');
|
dev.log('Error processing selfie: $e', name: 'SELFIE_VERIFICATION');
|
||||||
selfieError.value = 'Error verifying face: $e';
|
selfieError.value = 'Error processing selfie: $e';
|
||||||
isVerifyingFace.value = false;
|
isVerifyingFace.value = false;
|
||||||
isSelfieValid.value = false;
|
isSelfieValid.value = false;
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -135,25 +227,42 @@ class SelfieVerificationController extends GetxController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare selfie with ID card
|
// Compare selfie with ID card with better null handling
|
||||||
Future<void> _compareWithIdCard() async {
|
Future<void> _compareWithIdCard() async {
|
||||||
if (selfieImage.value == null) {
|
if (selfieImage.value == null) {
|
||||||
dev.log(
|
dev.log(
|
||||||
'No selfie image available for comparison',
|
'No selfie image available for comparison',
|
||||||
name: 'SELFIE_VERIFICATION',
|
name: 'SELFIE_VERIFICATION',
|
||||||
);
|
);
|
||||||
|
selfieError.value = 'Missing selfie image for ID comparison';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
XFile idCardImage;
|
// Find controller if it exists, with better error handling
|
||||||
|
|
||||||
// find controller if it exists
|
|
||||||
|
|
||||||
if (idCardController == null) {
|
if (idCardController == null) {
|
||||||
// If we don't have an ID card controller, log and return
|
try {
|
||||||
Get.put<IdCardVerificationController>;
|
// Try to get the controller if it's registered
|
||||||
|
if (Get.isRegistered<IdCardVerificationController>()) {
|
||||||
|
idCardController = Get.find<IdCardVerificationController>();
|
||||||
|
} else {
|
||||||
|
dev.log(
|
||||||
|
'ID card controller not found, cannot compare faces',
|
||||||
|
name: 'SELFIE_VERIFICATION',
|
||||||
|
);
|
||||||
|
selfieError.value = 'ID card data not available for comparison';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
dev.log(
|
||||||
|
'Error getting ID card controller: $e',
|
||||||
|
name: 'SELFIE_VERIFICATION',
|
||||||
|
);
|
||||||
|
selfieError.value = 'ID card data not available for comparison';
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if ID card image exists
|
||||||
if (idCardController!.idCardImage.value == null) {
|
if (idCardController!.idCardImage.value == null) {
|
||||||
dev.log(
|
dev.log(
|
||||||
'No ID card image available for comparison',
|
'No ID card image available for comparison',
|
||||||
|
@ -163,7 +272,26 @@ class SelfieVerificationController extends GetxController {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
idCardImage = idCardController!.idCardImage.value!;
|
XFile idCardImage = idCardController!.idCardImage.value!;
|
||||||
|
|
||||||
|
// Verify both image files exist
|
||||||
|
if (!File(idCardImage.path).existsSync()) {
|
||||||
|
dev.log(
|
||||||
|
'ID card image file does not exist: ${idCardImage.path}',
|
||||||
|
name: 'SELFIE_VERIFICATION',
|
||||||
|
);
|
||||||
|
selfieError.value = 'ID card image file not found';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!File(selfieImage.value!.path).existsSync()) {
|
||||||
|
dev.log(
|
||||||
|
'Selfie image file does not exist: ${selfieImage.value!.path}',
|
||||||
|
name: 'SELFIE_VERIFICATION',
|
||||||
|
);
|
||||||
|
selfieError.value = 'Selfie image file not found';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
isComparingWithIDCard.value = true;
|
isComparingWithIDCard.value = true;
|
||||||
|
@ -234,6 +362,7 @@ class SelfieVerificationController extends GetxController {
|
||||||
isLivenessCheckPassed.value = false;
|
isLivenessCheckPassed.value = false;
|
||||||
isPerformingLivenessCheck.value = false;
|
isPerformingLivenessCheck.value = false;
|
||||||
hasConfirmedSelfie.value = false;
|
hasConfirmedSelfie.value = false;
|
||||||
|
autoStartVerification = false; // Reset auto verification flag
|
||||||
selfieError.value = '';
|
selfieError.value = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import 'package:sigap/src/features/auth/presentasion/pages/signup/step/selfie-ve
|
||||||
import 'package:sigap/src/features/auth/presentasion/pages/signup/step/selfie-verification/widgets/captured_selfie_view.dart';
|
import 'package:sigap/src/features/auth/presentasion/pages/signup/step/selfie-verification/widgets/captured_selfie_view.dart';
|
||||||
import 'package:sigap/src/features/auth/presentasion/pages/signup/step/selfie-verification/widgets/countdown_overlay_widget.dart';
|
import 'package:sigap/src/features/auth/presentasion/pages/signup/step/selfie-verification/widgets/countdown_overlay_widget.dart';
|
||||||
import 'package:sigap/src/features/auth/presentasion/pages/signup/step/selfie-verification/widgets/debug_panel.dart';
|
import 'package:sigap/src/features/auth/presentasion/pages/signup/step/selfie-verification/widgets/debug_panel.dart';
|
||||||
import 'package:sigap/src/features/auth/presentasion/pages/signup/step/selfie-verification/widgets/error_state_widget.dart';
|
|
||||||
import 'package:sigap/src/features/auth/presentasion/pages/signup/step/selfie-verification/widgets/instruction_banner.dart';
|
import 'package:sigap/src/features/auth/presentasion/pages/signup/step/selfie-verification/widgets/instruction_banner.dart';
|
||||||
import 'package:sigap/src/features/auth/presentasion/pages/signup/step/selfie-verification/widgets/verification_progress_widget.dart';
|
import 'package:sigap/src/features/auth/presentasion/pages/signup/step/selfie-verification/widgets/verification_progress_widget.dart';
|
||||||
import 'package:sigap/src/shared/widgets/state_screeen/state_screen.dart';
|
import 'package:sigap/src/shared/widgets/state_screeen/state_screen.dart';
|
||||||
|
|
|
@ -315,6 +315,23 @@ class SelfieVerificationStep extends StatelessWidget {
|
||||||
SelfieVerificationController controller,
|
SelfieVerificationController controller,
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
) {
|
) {
|
||||||
|
// Debug current state
|
||||||
|
|
||||||
|
// Check if we need to auto-start verification (when returning from liveness detection)
|
||||||
|
if (controller.selfieImage.value != null &&
|
||||||
|
controller.isLivenessCheckPassed.value &&
|
||||||
|
controller.autoStartVerification) {
|
||||||
|
// Log detection attempt
|
||||||
|
|
||||||
|
// Start verification after the UI is built
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
if (!controller.isVerifyingFace.value &&
|
||||||
|
!controller.isComparingWithIDCard.value) {
|
||||||
|
controller.startFaceVerification();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case VerificationStatus.initial:
|
case VerificationStatus.initial:
|
||||||
return _buildInitialState(controller, context);
|
return _buildInitialState(controller, context);
|
||||||
|
|
|
@ -3,6 +3,7 @@ import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:sigap/src/features/auth/presentasion/controllers/signup/step/selfie-verification/face_liveness_detection_controller.dart';
|
import 'package:sigap/src/features/auth/presentasion/controllers/signup/step/selfie-verification/face_liveness_detection_controller.dart';
|
||||||
import 'package:sigap/src/features/auth/presentasion/controllers/signup/step/selfie-verification/selfie_verification_controller.dart';
|
import 'package:sigap/src/features/auth/presentasion/controllers/signup/step/selfie-verification/selfie_verification_controller.dart';
|
||||||
import 'package:sigap/src/utils/constants/colors.dart';
|
import 'package:sigap/src/utils/constants/colors.dart';
|
||||||
|
@ -613,7 +614,7 @@ class _CapturedSelfieViewState extends State<CapturedSelfieView>
|
||||||
color: TColors.primary,
|
color: TColors.primary,
|
||||||
),
|
),
|
||||||
const SizedBox(width: TSizes.sm),
|
const SizedBox(width: TSizes.sm),
|
||||||
const Text(
|
Text(
|
||||||
'Try Again',
|
'Try Again',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
|
@ -631,14 +632,19 @@ class _CapturedSelfieViewState extends State<CapturedSelfieView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update continue button handler to use ValueNotifier
|
// Fix the continue button handler to navigate directly to the selfie verification step
|
||||||
Future<void> _handleContinueButton() async {
|
Future<void> _handleContinueButton() async {
|
||||||
if (!mounted || isDisposed) return;
|
if (!mounted || isDisposed) return;
|
||||||
|
|
||||||
widget.controller.disposeCamera();
|
try {
|
||||||
|
if (widget.controller.capturedImage == null) {
|
||||||
|
dev.log('Error: No captured image available', name: 'LIVENESS_DEBUG');
|
||||||
|
errorMessage.value = 'No image was captured. Please try again.';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
isComparingWithID.value = true;
|
isComparingWithID.value = true;
|
||||||
|
|
||||||
try {
|
|
||||||
if (widget.selfieController != null) {
|
if (widget.selfieController != null) {
|
||||||
errorMessage.value = null;
|
errorMessage.value = null;
|
||||||
|
|
||||||
|
@ -647,26 +653,54 @@ class _CapturedSelfieViewState extends State<CapturedSelfieView>
|
||||||
name: 'LIVENESS_DEBUG',
|
name: 'LIVENESS_DEBUG',
|
||||||
);
|
);
|
||||||
|
|
||||||
if (widget.controller.capturedImage != null) {
|
// Create a copy of the captured image path to ensure it remains valid
|
||||||
|
final imagePath = widget.controller.capturedImage!.path;
|
||||||
|
dev.log('Captured image path: $imagePath', name: 'LIVENESS_DEBUG');
|
||||||
|
|
||||||
|
// Create a new XFile instance from the path
|
||||||
|
final xFile = XFile(imagePath);
|
||||||
|
|
||||||
|
// Set the liveness flag first
|
||||||
|
widget.selfieController!.isLivenessCheckPassed.value = true;
|
||||||
|
|
||||||
|
// Set flag to automatically start verification upon returning
|
||||||
|
widget.selfieController!.autoStartVerification = true;
|
||||||
|
|
||||||
|
// Set the captured image in the selfie controller - do this last
|
||||||
|
widget.selfieController!.selfieImage.value = xFile;
|
||||||
|
|
||||||
dev.log(
|
dev.log(
|
||||||
'Setting captured image on SelfieVerificationController',
|
'Successfully set image in selfie controller',
|
||||||
name: 'LIVENESS_DEBUG',
|
name: 'LIVENESS_DEBUG',
|
||||||
);
|
);
|
||||||
|
|
||||||
// Use Future.delayed to ensure UI updates before navigation
|
// Now dispose the camera after we've handled the image
|
||||||
|
widget.controller.disposeCamera();
|
||||||
|
|
||||||
|
// Update the controller to ensure changes propagate
|
||||||
|
widget.selfieController!.update();
|
||||||
|
|
||||||
|
// Wait a moment to ensure the image is properly set
|
||||||
await Future.delayed(Duration(milliseconds: 100));
|
await Future.delayed(Duration(milliseconds: 100));
|
||||||
|
|
||||||
widget.selfieController!.selfieImage.value =
|
// Navigate back to selfie verification step by removing liveness detection from stack
|
||||||
widget.controller.capturedImage;
|
|
||||||
|
|
||||||
if (mounted && !isDisposed) {
|
if (mounted && !isDisposed) {
|
||||||
Get.back(result: widget.controller.capturedImage);
|
// Use Get.offAll to clear the entire navigation stack and go to signup page
|
||||||
}
|
// The signup page will show the selfie verification step since we've set the image
|
||||||
|
Get.offAllNamed('/signup'); // Replace with your actual signup route
|
||||||
|
|
||||||
|
// Alternative: if you know the exact route name for selfie verification step
|
||||||
|
// Get.offNamed('/signup/selfie-verification');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
await Future.delayed(Duration(milliseconds: 100));
|
widget.controller.disposeCamera();
|
||||||
|
|
||||||
if (mounted && !isDisposed) {
|
if (mounted && !isDisposed) {
|
||||||
Get.back(result: widget.controller.capturedImage);
|
Get.back(
|
||||||
|
closeOverlays: true,
|
||||||
|
canPop: true,
|
||||||
|
result: widget.controller.capturedImage,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -678,7 +712,7 @@ class _CapturedSelfieViewState extends State<CapturedSelfieView>
|
||||||
if (mounted && !isDisposed) {
|
if (mounted && !isDisposed) {
|
||||||
isComparingWithID.value = false;
|
isComparingWithID.value = false;
|
||||||
errorMessage.value =
|
errorMessage.value =
|
||||||
'Failed to process the captured image. Please try again.';
|
'Failed to process the captured image: $e';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue