|
|
|
|
@ -40,7 +40,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);
|
|
|
|
|
@ -114,20 +114,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(
|
|
|
|
|
@ -336,50 +349,128 @@ 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");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//older code..
|
|
|
|
|
// 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();
|
|
|
|
|
// });
|
|
|
|
|
// }
|
|
|
|
|
// });
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
void showInfoDialog({required String message, VoidCallback? onTap}) {
|
|
|
|
|
showDialog(
|
|
|
|
|
context: navigatorKey.currentState!.overlay!.context,
|
|
|
|
|
@ -434,16 +525,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,
|
|
|
|
|
@ -469,45 +559,45 @@ class SwipeGeneralUtils {
|
|
|
|
|
|
|
|
|
|
NfcManager.instance.startSession(
|
|
|
|
|
onDiscovered: (NfcTag tag) async {
|
|
|
|
|
String identifier = '';
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if (Platform.isAndroid) {
|
|
|
|
|
// Try NfcA first (most common)
|
|
|
|
|
final nfcA = NfcAAndroid.from(tag);
|
|
|
|
|
if (nfcA != null) {
|
|
|
|
|
identifier = nfcA.tag.id.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
|
|
|
|
|
} else {
|
|
|
|
|
// Fallback to NfcB
|
|
|
|
|
final nfcB = NfcBAndroid.from(tag);
|
|
|
|
|
if (nfcB != null) {
|
|
|
|
|
identifier = nfcB.tag.id.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
|
|
|
|
|
String identifier = '';
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if (Platform.isAndroid) {
|
|
|
|
|
// Try NfcA first (most common)
|
|
|
|
|
final nfcA = NfcAAndroid.from(tag);
|
|
|
|
|
if (nfcA != null) {
|
|
|
|
|
identifier = nfcA.tag.id.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
|
|
|
|
|
} else {
|
|
|
|
|
// Fallback to NfcB
|
|
|
|
|
final nfcB = NfcBAndroid.from(tag);
|
|
|
|
|
if (nfcB != null) {
|
|
|
|
|
identifier = nfcB.tag.id.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// For iOS, try MiFare first
|
|
|
|
|
final mifare = MiFareIos.from(tag);
|
|
|
|
|
if (mifare != null) {
|
|
|
|
|
identifier = mifare.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
|
|
|
|
|
} else {
|
|
|
|
|
// Fallback to Iso15693 for iOS
|
|
|
|
|
final iso15693 = Iso15693Ios.from(tag);
|
|
|
|
|
if (iso15693 != null) {
|
|
|
|
|
identifier = iso15693.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
|
|
|
|
|
// For iOS, try MiFare first
|
|
|
|
|
final mifare = MiFareIos.from(tag);
|
|
|
|
|
if (mifare != null) {
|
|
|
|
|
identifier = mifare.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
|
|
|
|
|
} else {
|
|
|
|
|
// Fallback to Iso15693 for iOS
|
|
|
|
|
final iso15693 = Iso15693Ios.from(tag);
|
|
|
|
|
if (iso15693 != null) {
|
|
|
|
|
identifier = iso15693.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
print('Error reading NFC: $e');
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
print('Error reading NFC: $e');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
await NfcManager.instance.stopSession();
|
|
|
|
|
} catch (e) {
|
|
|
|
|
print('Error stopping NFC session: $e');
|
|
|
|
|
}
|
|
|
|
|
onRead!(identifier);
|
|
|
|
|
},
|
|
|
|
|
try {
|
|
|
|
|
await NfcManager.instance.stopSession();
|
|
|
|
|
} catch (e) {
|
|
|
|
|
print('Error stopping NFC session: $e');
|
|
|
|
|
}
|
|
|
|
|
onRead!(identifier);
|
|
|
|
|
},
|
|
|
|
|
pollingOptions: {NfcPollingOption.iso14443},
|
|
|
|
|
).catchError((err) {
|
|
|
|
|
print('NFC session error: $err');
|
|
|
|
|
|