|
|
|
|
@ -5,6 +5,7 @@ import 'dart:io';
|
|
|
|
|
|
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
import 'package:flutter_nfc_kit/flutter_nfc_kit.dart';
|
|
|
|
|
import 'package:geolocator/geolocator.dart';
|
|
|
|
|
import 'package:google_api_availability/google_api_availability.dart';
|
|
|
|
|
import 'package:huawei_location/huawei_location.dart';
|
|
|
|
|
@ -16,6 +17,7 @@ import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
|
import 'package:test_sa/controllers/providers/api/user_provider.dart';
|
|
|
|
|
import 'package:test_sa/extensions/context_extension.dart';
|
|
|
|
|
import 'package:test_sa/extensions/int_extensions.dart';
|
|
|
|
|
import 'package:test_sa/extensions/string_extensions.dart';
|
|
|
|
|
import 'package:test_sa/extensions/text_extensions.dart';
|
|
|
|
|
import 'package:test_sa/extensions/widget_extensions.dart';
|
|
|
|
|
import 'package:test_sa/main.dart';
|
|
|
|
|
@ -23,6 +25,8 @@ import 'package:test_sa/new_views/app_style/app_color.dart';
|
|
|
|
|
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
|
|
|
|
|
import 'package:test_sa/new_views/swipe_module/dialoge/confirm_dialog.dart';
|
|
|
|
|
import 'package:test_sa/new_views/swipe_module/dialoge/nfc_reader_sheet.dart';
|
|
|
|
|
|
|
|
|
|
// import 'package:test_sa/new_views/swipe_module/dialoge/nfc_reader_sheet.dart';
|
|
|
|
|
import 'package:test_sa/new_views/swipe_module/enums/swipe_type.dart';
|
|
|
|
|
import 'package:test_sa/new_views/swipe_module/models/swipe_model.dart';
|
|
|
|
|
import 'package:test_sa/new_views/swipe_module/swipe_success_view.dart';
|
|
|
|
|
@ -38,7 +42,7 @@ class SwipeGeneralUtils {
|
|
|
|
|
|
|
|
|
|
static bool get isLoading => _isLoadingVisible;
|
|
|
|
|
|
|
|
|
|
void markFakeAttendance(dynamic sourceName, String lat, String long, @required BuildContext context) async {
|
|
|
|
|
void markFakeAttendance(dynamic sourceName, String lat, String long, {required BuildContext context}) async {
|
|
|
|
|
showLoading(context);
|
|
|
|
|
try {
|
|
|
|
|
hideLoading(navigatorKey.currentState!.overlay!.context);
|
|
|
|
|
@ -112,20 +116,33 @@ class SwipeGeneralUtils {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Widget attendanceTypeCard(String title, String icon, bool isEnabled, VoidCallback onPress, BuildContext context) {
|
|
|
|
|
|
|
|
|
|
return Container(
|
|
|
|
|
padding: const EdgeInsets.all(12),
|
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
|
color: isEnabled ?context.isDark ? AppColor.neutral60 : Colors.white : AppColor.background(context),
|
|
|
|
|
color: isEnabled
|
|
|
|
|
? context.isDark
|
|
|
|
|
? AppColor.neutral60
|
|
|
|
|
: Colors.white
|
|
|
|
|
: AppColor.background(context),
|
|
|
|
|
borderRadius: BorderRadius.circular(18),
|
|
|
|
|
border: Border.all(color:context.isDark ? AppColor.neutral60 : Colors.white70 , width: 2),
|
|
|
|
|
border: Border.all(color: context.isDark ? AppColor.neutral60 : Colors.white70, width: 2),
|
|
|
|
|
),
|
|
|
|
|
child: Column(
|
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
|
|
|
children: [
|
|
|
|
|
icon.toSvgAsset(color: isEnabled ?context.isDark ? AppColor.neutral30 : AppColor.neutral50 : Colors.grey.withOpacity(0.5)),
|
|
|
|
|
title.heading5(context).custom(color: isEnabled ?context.isDark ? AppColor.neutral30 : AppColor.neutral50 : Colors.grey.withOpacity(0.5)),
|
|
|
|
|
icon.toSvgAsset(
|
|
|
|
|
color: isEnabled
|
|
|
|
|
? context.isDark
|
|
|
|
|
? AppColor.neutral30
|
|
|
|
|
: AppColor.neutral50
|
|
|
|
|
: Colors.grey.withOpacity(0.5)),
|
|
|
|
|
title.heading5(context).custom(
|
|
|
|
|
color: isEnabled
|
|
|
|
|
? context.isDark
|
|
|
|
|
? AppColor.neutral30
|
|
|
|
|
: AppColor.neutral50
|
|
|
|
|
: Colors.grey.withOpacity(0.5)),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
).onPress(
|
|
|
|
|
@ -173,67 +190,130 @@ class SwipeGeneralUtils {
|
|
|
|
|
return (result[Permission.location] == PermissionStatus.granted || result[Permission.locationAlways] == PermissionStatus.granted);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void checkHuaweiLocationPermission({required SwipeTypeEnum attendanceType, required BuildContext context}) async {
|
|
|
|
|
// Permission_Handler permissionHandler = PermissionHandler();
|
|
|
|
|
LocationUtilities.isEnabled((bool isEnabled) async {
|
|
|
|
|
if (isEnabled) {
|
|
|
|
|
LocationUtilities.havePermission((bool permission) async {
|
|
|
|
|
if (permission) {
|
|
|
|
|
getHuaweiCurrentLocation(attendanceType: attendanceType, context: context);
|
|
|
|
|
} else {
|
|
|
|
|
bool has = await requestPermissions();
|
|
|
|
|
if (has) {
|
|
|
|
|
getHuaweiCurrentLocation(attendanceType: attendanceType, context: context);
|
|
|
|
|
} else {
|
|
|
|
|
showDialog(
|
|
|
|
|
context: context,
|
|
|
|
|
builder: (BuildContext cxt) => ConfirmDialog(
|
|
|
|
|
message: "You need to give location permission to mark attendance",
|
|
|
|
|
onTap: () {
|
|
|
|
|
Navigator.pop(context);
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
Future<void> checkHuaweiLocationPermission({
|
|
|
|
|
required SwipeTypeEnum attendanceType,
|
|
|
|
|
required BuildContext context,
|
|
|
|
|
}) async {
|
|
|
|
|
try {
|
|
|
|
|
// Check if location service is enabled
|
|
|
|
|
final isEnabled = await LocationUtilities.isEnabledAsync();
|
|
|
|
|
if (!isEnabled) {
|
|
|
|
|
showDialog(
|
|
|
|
|
context: context,
|
|
|
|
|
builder: (BuildContext cxt) => ConfirmDialog(
|
|
|
|
|
builder: (cxt) => ConfirmDialog(
|
|
|
|
|
message: "You need to enable location services to mark attendance",
|
|
|
|
|
onTap: () async {
|
|
|
|
|
Navigator.pop(context);
|
|
|
|
|
Navigator.pop(cxt);
|
|
|
|
|
await Geolocator.openLocationSettings();
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// if (await permissionHandler.hasLocationPermission()) {
|
|
|
|
|
// getHuaweiCurrentLocation(attendanceType);
|
|
|
|
|
// } else {
|
|
|
|
|
// bool has = await requestPermissions();
|
|
|
|
|
// if (has) {
|
|
|
|
|
// getHuaweiCurrentLocation(attendanceType);
|
|
|
|
|
// } else {
|
|
|
|
|
// showDialog(
|
|
|
|
|
// context: context,
|
|
|
|
|
// builder: (BuildContext cxt) => ConfirmDialog(
|
|
|
|
|
// message: "You need to give location permission to mark attendance",
|
|
|
|
|
// onTap: () {
|
|
|
|
|
// Navigator.pop(context);
|
|
|
|
|
// },
|
|
|
|
|
// ),
|
|
|
|
|
// );
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// Check permission
|
|
|
|
|
bool hasPermission = await LocationUtilities.havePermissionAsync();
|
|
|
|
|
|
|
|
|
|
// Request if not granted
|
|
|
|
|
if (!hasPermission) {
|
|
|
|
|
hasPermission = await requestPermissions();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!hasPermission) {
|
|
|
|
|
showDialog(
|
|
|
|
|
context: context,
|
|
|
|
|
builder: (cxt) => ConfirmDialog(
|
|
|
|
|
message: "You need to give location permission to mark attendance",
|
|
|
|
|
onTap: () {
|
|
|
|
|
Navigator.pop(cxt);
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// All good → get location
|
|
|
|
|
getHuaweiCurrentLocation(
|
|
|
|
|
attendanceType: attendanceType,
|
|
|
|
|
context: context,
|
|
|
|
|
);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
debugPrint("❌ Huawei location error: $e");
|
|
|
|
|
|
|
|
|
|
showDialog(
|
|
|
|
|
context: context,
|
|
|
|
|
builder: (cxt) => ConfirmDialog(
|
|
|
|
|
message: "Something went wrong. Please try again.",
|
|
|
|
|
onTap: () {
|
|
|
|
|
Navigator.pop(cxt);
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// void checkHuaweiLocationPermission({required SwipeTypeEnum attendanceType, required BuildContext context}) async {
|
|
|
|
|
// // Permission_Handler permissionHandler = PermissionHandler();
|
|
|
|
|
// LocationUtilities.isEnabled((bool isEnabled) async {
|
|
|
|
|
// if (isEnabled) {
|
|
|
|
|
// LocationUtilities.havePermission((bool permission) async {
|
|
|
|
|
// if (permission) {
|
|
|
|
|
// getHuaweiCurrentLocation(attendanceType: attendanceType, context: context);
|
|
|
|
|
// } else {
|
|
|
|
|
// bool has = await requestPermissions();
|
|
|
|
|
// if (has) {
|
|
|
|
|
// getHuaweiCurrentLocation(attendanceType: attendanceType, context: context);
|
|
|
|
|
// } else {
|
|
|
|
|
// showDialog(
|
|
|
|
|
// context: context,
|
|
|
|
|
// builder: (BuildContext cxt) => ConfirmDialog(
|
|
|
|
|
// message: "You need to give location permission to mark attendance",
|
|
|
|
|
// onTap: () {
|
|
|
|
|
// Navigator.pop(context);
|
|
|
|
|
// },
|
|
|
|
|
// ),
|
|
|
|
|
// );
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// });
|
|
|
|
|
// } else {
|
|
|
|
|
// showDialog(
|
|
|
|
|
// context: context,
|
|
|
|
|
// builder: (BuildContext cxt) => ConfirmDialog(
|
|
|
|
|
// message: "You need to enable location services to mark attendance",
|
|
|
|
|
// onTap: () async {
|
|
|
|
|
// Navigator.pop(context);
|
|
|
|
|
// await Geolocator.openLocationSettings();
|
|
|
|
|
// },
|
|
|
|
|
// ),
|
|
|
|
|
// );
|
|
|
|
|
// }
|
|
|
|
|
// });
|
|
|
|
|
//
|
|
|
|
|
// // if (await permissionHandler.hasLocationPermission()) {
|
|
|
|
|
// // getHuaweiCurrentLocation(attendanceType);
|
|
|
|
|
// // } else {
|
|
|
|
|
// // bool has = await requestPermissions();
|
|
|
|
|
// // if (has) {
|
|
|
|
|
// // getHuaweiCurrentLocation(attendanceType);
|
|
|
|
|
// // } else {
|
|
|
|
|
// // showDialog(
|
|
|
|
|
// // context: context,
|
|
|
|
|
// // builder: (BuildContext cxt) => ConfirmDialog(
|
|
|
|
|
// // message: "You need to give location permission to mark attendance",
|
|
|
|
|
// // onTap: () {
|
|
|
|
|
// // Navigator.pop(context);
|
|
|
|
|
// // },
|
|
|
|
|
// // ),
|
|
|
|
|
// // );
|
|
|
|
|
// // }
|
|
|
|
|
// // }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
void handleSwipeOperation({required SwipeTypeEnum swipeType, required double lat, required double long, required BuildContext context}) {
|
|
|
|
|
switch (swipeType) {
|
|
|
|
|
case SwipeTypeEnum.NFC:
|
|
|
|
|
log('showing nfc sheet');
|
|
|
|
|
handleNfcAttendance(latitude: lat, longitude: long, context: context);
|
|
|
|
|
return;
|
|
|
|
|
case SwipeTypeEnum.QR:
|
|
|
|
|
@ -253,61 +333,140 @@ class SwipeGeneralUtils {
|
|
|
|
|
UserProvider userProvider = Provider.of<UserProvider>(context, listen: false);
|
|
|
|
|
|
|
|
|
|
String qrCodeValue = await Navigator.of(context).push(
|
|
|
|
|
MaterialPageRoute(builder: (_) => ScanQr()),
|
|
|
|
|
MaterialPageRoute(builder: (_) => const ScanQr()),
|
|
|
|
|
) as String;
|
|
|
|
|
|
|
|
|
|
if (qrCodeValue != null) {
|
|
|
|
|
showLoading(context);
|
|
|
|
|
try {
|
|
|
|
|
final swipeModel = Swipe(
|
|
|
|
|
swipeTypeValue: SwipeTypeEnum.QR.getIntFromSwipeTypeEnum(),
|
|
|
|
|
value: qrCodeValue,
|
|
|
|
|
latitude: latitude,
|
|
|
|
|
longitude: longitude,
|
|
|
|
|
);
|
|
|
|
|
showLoading(context);
|
|
|
|
|
try {
|
|
|
|
|
final swipeModel = Swipe(
|
|
|
|
|
swipeTypeValue: SwipeTypeEnum.QR.getIntFromSwipeTypeEnum(),
|
|
|
|
|
value: qrCodeValue,
|
|
|
|
|
latitude: latitude,
|
|
|
|
|
longitude: longitude,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await userProvider.makeSwipe(model: swipeModel).then((swipeResponse) {
|
|
|
|
|
if (swipeResponse.isSuccess == true) {
|
|
|
|
|
hideLoading(context);
|
|
|
|
|
Navigator.pushNamed(context, SwipeSuccessView.routeName);
|
|
|
|
|
} else {
|
|
|
|
|
hideLoading(context);
|
|
|
|
|
showDialog(
|
|
|
|
|
barrierDismissible: true,
|
|
|
|
|
context: context,
|
|
|
|
|
builder: (cxt) => ConfirmDialog(
|
|
|
|
|
message: swipeResponse.message ?? "",
|
|
|
|
|
onTap: () {
|
|
|
|
|
Navigator.pop(context);
|
|
|
|
|
},
|
|
|
|
|
onCloseTap: () {},
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} catch (ex) {
|
|
|
|
|
log('$ex');
|
|
|
|
|
hideLoading(context);
|
|
|
|
|
//this need to confirm where it comes..
|
|
|
|
|
// handleException(ex, context, null);
|
|
|
|
|
}
|
|
|
|
|
await userProvider.makeSwipe(model: swipeModel).then((swipeResponse) {
|
|
|
|
|
if (swipeResponse.isSuccess == true) {
|
|
|
|
|
hideLoading(context);
|
|
|
|
|
Navigator.pushNamed(context, SwipeSuccessView.routeName);
|
|
|
|
|
} else {
|
|
|
|
|
hideLoading(context);
|
|
|
|
|
showDialog(
|
|
|
|
|
barrierDismissible: true,
|
|
|
|
|
context: context,
|
|
|
|
|
builder: (cxt) => ConfirmDialog(
|
|
|
|
|
message: swipeResponse.message ?? "",
|
|
|
|
|
onTap: () {
|
|
|
|
|
Navigator.pop(context);
|
|
|
|
|
},
|
|
|
|
|
onCloseTap: () {},
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} catch (ex) {
|
|
|
|
|
log('$ex');
|
|
|
|
|
hideLoading(context);
|
|
|
|
|
//this need to confirm where it comes..
|
|
|
|
|
// handleException(ex, context, null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future<void> handleNfcAttendance({double? latitude = 0, double? longitude = 0, required BuildContext context}) async {
|
|
|
|
|
// UserProvider _userProvider = Provider.of<UserProvider>(context,listen:false);
|
|
|
|
|
// if (Platform.isAndroid) {
|
|
|
|
|
// // Android: show custom bottom sheet with your scan/done UI
|
|
|
|
|
// showNfcReader(context, onNcfScan: (String? nfcId) async {
|
|
|
|
|
// if (nfcId == null || nfcId.isEmpty) return;
|
|
|
|
|
//
|
|
|
|
|
// try {
|
|
|
|
|
// await _processNfcAttendance(nfcId, latitude, longitude, context);
|
|
|
|
|
// } finally {
|
|
|
|
|
// _nfcScanning = false;
|
|
|
|
|
// }
|
|
|
|
|
// });
|
|
|
|
|
// }
|
|
|
|
|
// dart
|
|
|
|
|
// Add this field to the class (near the top, e.g. after the constructor)
|
|
|
|
|
bool _nfcScanning = false;
|
|
|
|
|
|
|
|
|
|
// dart
|
|
|
|
|
Future<void> handleNfcAttendance({
|
|
|
|
|
double? latitude = 0,
|
|
|
|
|
double? longitude = 0,
|
|
|
|
|
required BuildContext context,
|
|
|
|
|
}) async {
|
|
|
|
|
// if (_nfcScanning) return;
|
|
|
|
|
// _nfcScanning = true;
|
|
|
|
|
|
|
|
|
|
if (Platform.isIOS) {
|
|
|
|
|
readNFc(onRead: (String nfcId) async {
|
|
|
|
|
await _processNfcAttendance(nfcId, latitude, longitude, context);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
showNfcReader(context, onNcfScan: (String? nfcId) async {
|
|
|
|
|
await _processNfcAttendance(nfcId ?? '', latitude, longitude, context);
|
|
|
|
|
});
|
|
|
|
|
try {
|
|
|
|
|
var availability = await FlutterNfcKit.nfcAvailability;
|
|
|
|
|
if (availability != NFCAvailability.available) {
|
|
|
|
|
"NFC is not available on this device".showToast;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Platform.isAndroid) {
|
|
|
|
|
try {
|
|
|
|
|
showNfcReader(context, onNcfScan: (String? nfcId) async {
|
|
|
|
|
log('nfc id from sheet: $nfcId');
|
|
|
|
|
|
|
|
|
|
if (nfcId == null || nfcId.isEmpty) return;
|
|
|
|
|
try {
|
|
|
|
|
await _processNfcAttendance(nfcId, latitude, longitude, context);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
// handle per-scan error if needed
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} catch (e) {
|
|
|
|
|
debugPrint('Error showing NFC reader sheet: $e');
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
try {
|
|
|
|
|
NFCTag tag = await FlutterNfcKit.poll(
|
|
|
|
|
timeout: const Duration(seconds: 20),
|
|
|
|
|
iosAlertMessage: "Hold your card near the phone",
|
|
|
|
|
iosMultipleTagMessage: "Multiple cards detected. Please scan only one.",
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
String nfcId = tag.id.toUpperCase();
|
|
|
|
|
|
|
|
|
|
await FlutterNfcKit.finish();
|
|
|
|
|
|
|
|
|
|
await _processNfcAttendance(nfcId, latitude, longitude, context);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
if (!e.toString().contains("cancelled")) {
|
|
|
|
|
"Failed to read NFC card".showToast;
|
|
|
|
|
|
|
|
|
|
// ScaffoldMessenger.of(context).showSnackBar(
|
|
|
|
|
// const SnackBar(content: Text("Failed to read NFC card")),
|
|
|
|
|
// );
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
await FlutterNfcKit.finish();
|
|
|
|
|
} catch (_) {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
debugPrint("NFC error: $e");
|
|
|
|
|
} finally {
|
|
|
|
|
_nfcScanning = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Future<void> handleNfcAttendance({double? latitude = 0, double? longitude = 0, required BuildContext context}) async {
|
|
|
|
|
// bool _nfcScanning = false;
|
|
|
|
|
// // UserProvider _userProvider = Provider.of<UserProvider>(context,listen:false);
|
|
|
|
|
//
|
|
|
|
|
// if (Platform.isIOS) {
|
|
|
|
|
// readNFc(onRead: (String nfcId) async {
|
|
|
|
|
// await _processNfcAttendance(nfcId, latitude, longitude, context);
|
|
|
|
|
// });
|
|
|
|
|
// } else {
|
|
|
|
|
// showNfcReader(context, onNcfScan: (String? nfcId) async {
|
|
|
|
|
// await _processNfcAttendance(nfcId ?? '', latitude, longitude, context);
|
|
|
|
|
// });
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
Future<void> _processNfcAttendance(
|
|
|
|
|
String nfcId,
|
|
|
|
|
double? latitude,
|
|
|
|
|
@ -316,7 +475,12 @@ class SwipeGeneralUtils {
|
|
|
|
|
) async {
|
|
|
|
|
showLoading(context);
|
|
|
|
|
try {
|
|
|
|
|
final swipeModel = Swipe(swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(), value: nfcId, latitude: latitude, longitude: longitude);
|
|
|
|
|
final swipeModel = Swipe(
|
|
|
|
|
swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(),
|
|
|
|
|
value: nfcId,
|
|
|
|
|
latitude: latitude,
|
|
|
|
|
longitude: longitude,
|
|
|
|
|
);
|
|
|
|
|
UserProvider userProvider = Provider.of<UserProvider>(context, listen: false);
|
|
|
|
|
|
|
|
|
|
final swipeResponse = await userProvider.makeSwipe(model: swipeModel);
|
|
|
|
|
@ -333,50 +497,127 @@ class SwipeGeneralUtils {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handleSwipe({required SwipeTypeEnum swipeType, required bool isEnable, required BuildContext context}) async {
|
|
|
|
|
if (Platform.isAndroid && !(await isGoogleServicesAvailable())) {
|
|
|
|
|
checkHuaweiLocationPermission(attendanceType: swipeType, context: context);
|
|
|
|
|
} else {
|
|
|
|
|
LocationUtilities.isEnabled((bool isEnabled) {
|
|
|
|
|
if (isEnabled) {
|
|
|
|
|
LocationUtilities.havePermission((bool permission) {
|
|
|
|
|
if (permission) {
|
|
|
|
|
showLoading(context);
|
|
|
|
|
LocationUtilities.getCurrentLocation(
|
|
|
|
|
(Position position, bool isMocked) {
|
|
|
|
|
if (isMocked) {
|
|
|
|
|
hideLoading(context);
|
|
|
|
|
markFakeAttendance(swipeType.name, position.latitude.toString() ?? "", position.longitude.toString() ?? "", context);
|
|
|
|
|
} else {
|
|
|
|
|
hideLoading(context);
|
|
|
|
|
handleSwipeOperation(swipeType: swipeType, lat: position.latitude, long: position.longitude, context: context);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
() {
|
|
|
|
|
hideLoading(context);
|
|
|
|
|
confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working.");
|
|
|
|
|
},
|
|
|
|
|
context,
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
showInfoDialog(
|
|
|
|
|
message: "You need to give location permission to mark attendance",
|
|
|
|
|
onTap: () async {
|
|
|
|
|
await Geolocator.openAppSettings();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
showInfoDialog(
|
|
|
|
|
message: "You need to enable location services to mark attendance",
|
|
|
|
|
onTap: () async {
|
|
|
|
|
await Geolocator.openLocationSettings();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
Future<void> handleSwipe({
|
|
|
|
|
required SwipeTypeEnum swipeType,
|
|
|
|
|
required bool isEnable,
|
|
|
|
|
required BuildContext context,
|
|
|
|
|
}) async {
|
|
|
|
|
try {
|
|
|
|
|
if (Platform.isAndroid && !(await isGoogleServicesAvailable())) {
|
|
|
|
|
checkHuaweiLocationPermission(
|
|
|
|
|
attendanceType: swipeType,
|
|
|
|
|
context: context,
|
|
|
|
|
);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// Check if location is enabled
|
|
|
|
|
final isEnabled = await LocationUtilities.isEnabledAsync();
|
|
|
|
|
if (!isEnabled) {
|
|
|
|
|
showInfoDialog(
|
|
|
|
|
message: "You need to enable location services to mark attendance",
|
|
|
|
|
onTap: () async => await Geolocator.openLocationSettings(),
|
|
|
|
|
);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check permission
|
|
|
|
|
final hasPermission = await LocationUtilities.havePermissionAsync();
|
|
|
|
|
if (!hasPermission) {
|
|
|
|
|
showInfoDialog(
|
|
|
|
|
message: "You need to give location permission to mark attendance",
|
|
|
|
|
onTap: () async => await Geolocator.openAppSettings(),
|
|
|
|
|
);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Show loader
|
|
|
|
|
showLoading(context);
|
|
|
|
|
|
|
|
|
|
// Get location
|
|
|
|
|
await LocationUtilities.getCurrentLocation(
|
|
|
|
|
(Position position, bool isMocked) {
|
|
|
|
|
hideLoading(context);
|
|
|
|
|
|
|
|
|
|
if (isMocked) {
|
|
|
|
|
markFakeAttendance(
|
|
|
|
|
swipeType.name,
|
|
|
|
|
position.latitude.toString(),
|
|
|
|
|
position.longitude.toString(),
|
|
|
|
|
context: context,
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
handleSwipeOperation(
|
|
|
|
|
swipeType: swipeType,
|
|
|
|
|
lat: position.latitude,
|
|
|
|
|
long: position.longitude,
|
|
|
|
|
context: context,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
(String error) {
|
|
|
|
|
hideLoading(context);
|
|
|
|
|
|
|
|
|
|
confirmDialog(
|
|
|
|
|
context,
|
|
|
|
|
error.isNotEmpty ? error : "Unable to determine your location. Please try again.",
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
context,
|
|
|
|
|
);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
hideLoading(context);
|
|
|
|
|
confirmDialog(
|
|
|
|
|
context,
|
|
|
|
|
"Something went wrong. Please try again.",
|
|
|
|
|
);
|
|
|
|
|
debugPrint("❌ handleSwipe error: $e");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// void handleSwipe({required SwipeTypeEnum swipeType, required bool isEnable, required BuildContext context}) async {
|
|
|
|
|
// if (Platform.isAndroid && !(await isGoogleServicesAvailable())) {
|
|
|
|
|
// checkHuaweiLocationPermission(attendanceType: swipeType, context: context);
|
|
|
|
|
// } else {
|
|
|
|
|
// LocationUtilities.isEnabled((bool isEnabled) {
|
|
|
|
|
// if (isEnabled) {
|
|
|
|
|
// LocationUtilities.havePermission((bool permission) {
|
|
|
|
|
// if (permission) {
|
|
|
|
|
// showLoading(context);
|
|
|
|
|
// LocationUtilities.getCurrentLocation(
|
|
|
|
|
// (Position position, bool isMocked) {
|
|
|
|
|
// if (isMocked) {
|
|
|
|
|
// hideLoading(context);
|
|
|
|
|
// markFakeAttendance(swipeType.name, position.latitude.toString(), position.longitude.toString() ?? "", context: context);
|
|
|
|
|
// } else {
|
|
|
|
|
// hideLoading(context);
|
|
|
|
|
// handleSwipeOperation(swipeType: swipeType, lat: position.latitude, long: position.longitude, context: context);
|
|
|
|
|
// }
|
|
|
|
|
// },
|
|
|
|
|
// () {
|
|
|
|
|
// hideLoading(context);
|
|
|
|
|
// confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working.");
|
|
|
|
|
// },
|
|
|
|
|
// context,
|
|
|
|
|
// );
|
|
|
|
|
// } else {
|
|
|
|
|
// showInfoDialog(
|
|
|
|
|
// message: "You need to give location permission to mark attendance",
|
|
|
|
|
// onTap: () async {
|
|
|
|
|
// await Geolocator.openAppSettings();
|
|
|
|
|
// });
|
|
|
|
|
// }
|
|
|
|
|
// });
|
|
|
|
|
// } else {
|
|
|
|
|
// showInfoDialog(
|
|
|
|
|
// message: "You need to enable location services to mark attendance",
|
|
|
|
|
// onTap: () async {
|
|
|
|
|
// await Geolocator.openLocationSettings();
|
|
|
|
|
// });
|
|
|
|
|
// }
|
|
|
|
|
// });
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
void showInfoDialog({required String message, VoidCallback? onTap}) {
|
|
|
|
|
showDialog(
|
|
|
|
|
context: navigatorKey.currentState!.overlay!.context,
|
|
|
|
|
@ -431,16 +672,15 @@ class SwipeGeneralUtils {
|
|
|
|
|
),
|
|
|
|
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
|
|
|
|
clipBehavior: Clip.antiAliasWithSaveLayer,
|
|
|
|
|
builder: (BuildContext context) =>Padding(
|
|
|
|
|
builder: (BuildContext context) => Padding(
|
|
|
|
|
padding: EdgeInsets.only(
|
|
|
|
|
bottom: MediaQuery.of(context).viewInsets.bottom +
|
|
|
|
|
MediaQuery.of(context).padding.bottom,
|
|
|
|
|
bottom: MediaQuery.of(context).viewInsets.bottom + MediaQuery.of(context).padding.bottom,
|
|
|
|
|
),
|
|
|
|
|
child: Column(
|
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
|
children: [
|
|
|
|
|
context.translation.markAttendance.heading4(context).custom(color:context.isDark?AppColor.white50: AppColor.white936),
|
|
|
|
|
context.translation.markAttendance.heading4(context).custom(color: context.isDark ? AppColor.white50 : AppColor.white936),
|
|
|
|
|
8.height,
|
|
|
|
|
context.translation.selectMethodToMarkAttendance.bodyText2(context).custom(color: AppColor.neutral120),
|
|
|
|
|
12.height,
|
|
|
|
|
@ -456,39 +696,40 @@ class SwipeGeneralUtils {
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//older code..
|
|
|
|
|
void readNFc({Function(String)? onRead}) {
|
|
|
|
|
NfcManager.instance.startSession(
|
|
|
|
|
onDiscovered: (NfcTag tag) async {
|
|
|
|
|
String identifier = '';
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
final dynamic tagDynamic = tag;
|
|
|
|
|
final Map<String, dynamic> tagData = Map<String, dynamic>.from(tagDynamic.data as Map);
|
|
|
|
|
|
|
|
|
|
if (Platform.isAndroid) {
|
|
|
|
|
if (tagData.containsKey('nfca')) {
|
|
|
|
|
final nfcaData = tagData['nfca'] as Map<dynamic, dynamic>;
|
|
|
|
|
if (nfcaData.containsKey('identifier')) {
|
|
|
|
|
final List<int> idBytes = List<int>.from(nfcaData['identifier'] as List);
|
|
|
|
|
identifier = idBytes.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
|
|
|
|
|
String identifier = '';
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
final dynamic tagDynamic = tag;
|
|
|
|
|
final Map<String, dynamic> tagData = Map<String, dynamic>.from(tagDynamic.data as Map);
|
|
|
|
|
|
|
|
|
|
if (Platform.isAndroid) {
|
|
|
|
|
if (tagData.containsKey('nfca')) {
|
|
|
|
|
final nfcaData = tagData['nfca'] as Map<dynamic, dynamic>;
|
|
|
|
|
if (nfcaData.containsKey('identifier')) {
|
|
|
|
|
final List<int> idBytes = List<int>.from(nfcaData['identifier'] as List);
|
|
|
|
|
identifier = idBytes.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (tagData.containsKey('mifare')) {
|
|
|
|
|
final mifareData = tagData['mifare'] as Map<dynamic, dynamic>;
|
|
|
|
|
if (mifareData.containsKey('identifier')) {
|
|
|
|
|
final List<int> idBytes = List<int>.from(mifareData['identifier'] as List);
|
|
|
|
|
identifier = idBytes.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
|
|
|
|
|
} else {
|
|
|
|
|
if (tagData.containsKey('mifare')) {
|
|
|
|
|
final mifareData = tagData['mifare'] as Map<dynamic, dynamic>;
|
|
|
|
|
if (mifareData.containsKey('identifier')) {
|
|
|
|
|
final List<int> idBytes = List<int>.from(mifareData['identifier'] as List);
|
|
|
|
|
identifier = idBytes.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
print('Error reading NFC: $e');
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
print('Error reading NFC: $e');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NfcManager.instance.stopSession();
|
|
|
|
|
onRead!(identifier);
|
|
|
|
|
},
|
|
|
|
|
NfcManager.instance.stopSession();
|
|
|
|
|
onRead!(identifier);
|
|
|
|
|
},
|
|
|
|
|
pollingOptions: {NfcPollingOption.iso14443},
|
|
|
|
|
).catchError((err) {
|
|
|
|
|
print(err);
|
|
|
|
|
|