Face Recognition with Liveness Detection for Web Support
This commit is contained in:
@@ -1511,8 +1511,9 @@ class _LogbookTab extends ConsumerWidget {
|
||||
if (logScheduleIds.contains(s.id)) return false;
|
||||
if (!s.endTime.isBefore(now)) return false;
|
||||
if (s.startTime.isBefore(range.start) ||
|
||||
!s.startTime.isBefore(range.end))
|
||||
!s.startTime.isBefore(range.end)) {
|
||||
return false;
|
||||
}
|
||||
// If the user rendered overtime on this calendar day, don't
|
||||
// mark the normal/night shift schedule as absent.
|
||||
final d = s.startTime;
|
||||
|
||||
@@ -9,6 +9,7 @@ import '../../providers/profile_provider.dart';
|
||||
import '../../providers/tickets_provider.dart';
|
||||
import '../../providers/user_offices_provider.dart';
|
||||
import '../../services/face_verification.dart' as face;
|
||||
import '../../widgets/face_verification_overlay.dart';
|
||||
import '../../widgets/multi_select_picker.dart';
|
||||
import '../../widgets/qr_verification_dialog.dart';
|
||||
import '../../widgets/responsive_body.dart';
|
||||
@@ -525,25 +526,19 @@ class _ProfileScreenState extends ConsumerState<ProfileScreen> {
|
||||
}
|
||||
|
||||
try {
|
||||
final result = await face.runFaceLiveness(context);
|
||||
if (result == null || !mounted) return;
|
||||
final result = await showFaceVerificationOverlay(
|
||||
context: context,
|
||||
ref: ref,
|
||||
// Profile test mode: no attendance record should be uploaded/skipped.
|
||||
attendanceLogId: null,
|
||||
uploadAttendanceResult: false,
|
||||
maxAttempts: 3,
|
||||
);
|
||||
|
||||
// Download enrolled photo via Supabase (authenticated, private bucket)
|
||||
final enrolledBytes = await ref
|
||||
.read(profileControllerProvider)
|
||||
.downloadFacePhoto(profile.id);
|
||||
if (enrolledBytes == null || !mounted) {
|
||||
if (mounted) {
|
||||
showErrorSnackBar(context, 'Could not load enrolled face photo.');
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!mounted || result == null) return;
|
||||
|
||||
// Compare captured vs enrolled
|
||||
final score = await face.compareFaces(result.imageBytes, enrolledBytes);
|
||||
|
||||
if (!mounted) return;
|
||||
if (score >= 0.60) {
|
||||
final score = result.matchScore ?? 0.0;
|
||||
if (result.verified) {
|
||||
showSuccessSnackBar(
|
||||
context,
|
||||
'Face matched! Similarity: ${(score * 100).toStringAsFixed(1)}%',
|
||||
|
||||
Reference in New Issue
Block a user