You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
532 lines
20 KiB
Dart
532 lines
20 KiB
Dart
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'dart:developer';
|
|
import 'dart:io';
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:geolocator/geolocator.dart';
|
|
import 'package:google_api_availability/google_api_availability.dart';
|
|
import 'package:huawei_location/huawei_location.dart';
|
|
import 'package:intl/intl.dart';
|
|
import 'package:nfc_manager/nfc_manager.dart';
|
|
import 'package:nfc_manager/platform_tags.dart';
|
|
import 'package:permission_handler/permission_handler.dart';
|
|
import 'package:provider/provider.dart';
|
|
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/text_extensions.dart';
|
|
import 'package:test_sa/extensions/widget_extensions.dart';
|
|
import 'package:test_sa/main.dart';
|
|
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/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';
|
|
import 'package:test_sa/new_views/swipe_module/utils/location_utils.dart';
|
|
import 'package:test_sa/views/widgets/qr/scan_qr.dart';
|
|
import 'package:wifi_iot/wifi_iot.dart';
|
|
|
|
class SwipeGeneralUtils {
|
|
SwipeGeneralUtils._();
|
|
|
|
static SwipeGeneralUtils instance = SwipeGeneralUtils._();
|
|
static bool _isLoadingVisible = false;
|
|
|
|
static bool get isLoading => _isLoadingVisible;
|
|
|
|
void markFakeAttendance(dynamic sourceName, String lat, String long, @required BuildContext context) async {
|
|
showLoading(context);
|
|
try {
|
|
hideLoading(navigatorKey.currentState!.overlay!.context);
|
|
confirmDialog(navigatorKey.currentState!.overlay!.context, "Fake Location)");
|
|
} catch (ex) {
|
|
log('$ex');
|
|
hideLoading(context);
|
|
//handleException(ex, context, null);
|
|
}
|
|
}
|
|
|
|
void showLoading(BuildContext context) {
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
_isLoadingVisible = true;
|
|
showDialog(
|
|
context: context,
|
|
barrierColor: Colors.black.withOpacity(0.5),
|
|
useRootNavigator: false,
|
|
builder: (BuildContext context) => const AppLazyLoading(),
|
|
).then((value) {
|
|
_isLoadingVisible = false;
|
|
});
|
|
});
|
|
}
|
|
|
|
void hideLoading(BuildContext context) {
|
|
if (_isLoadingVisible) {
|
|
_isLoadingVisible = false;
|
|
Navigator.of(context).pop();
|
|
}
|
|
_isLoadingVisible = false;
|
|
}
|
|
|
|
static Future<String> getStringFromPrefs(String key) async {
|
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
return prefs.getString(key) ?? "";
|
|
}
|
|
|
|
void confirmDialog(cxt, String message, {VoidCallback? onTap}) {
|
|
showDialog(
|
|
context: cxt,
|
|
builder: (BuildContext cxt) => ConfirmDialog(message: message, onTap: onTap),
|
|
);
|
|
}
|
|
|
|
void showErrorDialog({String? message, required BuildContext context}) {
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => ConfirmDialog(message: message, title: 'Error', onTap: () => Navigator.pop(context)),
|
|
);
|
|
}
|
|
|
|
void showMDialog(context, {Widget? child, Color? backgroundColor, bool isDismissable = true, bool isBusniessCard = false}) async {
|
|
return showDialog(
|
|
context: context,
|
|
barrierDismissible: isDismissable,
|
|
builder: (context) {
|
|
return Dialog(
|
|
shape: isBusniessCard
|
|
? const RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.all(
|
|
Radius.circular(15.0),
|
|
),
|
|
)
|
|
: null,
|
|
backgroundColor: backgroundColor,
|
|
child: child,
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
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),
|
|
borderRadius: BorderRadius.circular(18),
|
|
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)),
|
|
],
|
|
),
|
|
).onPress(
|
|
() {
|
|
if (!isEnabled) return;
|
|
onPress();
|
|
},
|
|
);
|
|
}
|
|
|
|
//huawei permission part....
|
|
void getHuaweiCurrentLocation({SwipeTypeEnum? attendanceType, required BuildContext context}) async {
|
|
try {
|
|
showLoading(context);
|
|
FusedLocationProviderClient locationService = FusedLocationProviderClient()..initFusedLocationService();
|
|
LocationRequest locationRequest = LocationRequest();
|
|
locationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY;
|
|
locationRequest.interval = 500;
|
|
List<LocationRequest> locationRequestList = <LocationRequest>[locationRequest];
|
|
LocationSettingsRequest locationSettingsRequest = LocationSettingsRequest(requests: locationRequestList);
|
|
|
|
late StreamSubscription<Location> _streamSubscription;
|
|
int requestCode = (await (locationService.requestLocationUpdates(locationRequest)))!;
|
|
_streamSubscription = locationService.onLocationData!.listen(
|
|
(Location location) async {
|
|
hideLoading(context);
|
|
await locationService.removeLocationUpdates(requestCode);
|
|
handleSwipeOperation(swipeType: attendanceType!, context: context, lat: location.latitude ?? 0, long: location.longitude ?? 0);
|
|
requestCode = 0;
|
|
_streamSubscription.cancel();
|
|
},
|
|
);
|
|
} catch (error) {
|
|
log("HUAWEI LOCATION ERROR!!!!!");
|
|
log('$error');
|
|
hideLoading(context);
|
|
// handleException(error, context, null);
|
|
}
|
|
}
|
|
|
|
Future<bool> requestPermissions() async {
|
|
var result = await [
|
|
Permission.location,
|
|
].request();
|
|
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 {
|
|
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:
|
|
handleNfcAttendance(latitude: lat, longitude: long, context: context);
|
|
return;
|
|
case SwipeTypeEnum.QR:
|
|
performQrCodeAttendance(latitude: lat, longitude: long, context: context);
|
|
return;
|
|
case SwipeTypeEnum.Wifi:
|
|
performWifiAttendance(latitude: lat, long: long, context: context);
|
|
return;
|
|
}
|
|
}
|
|
|
|
String formatTimeOnly(DateTime dateTime) {
|
|
return DateFormat.Hms().format(dateTime);
|
|
}
|
|
|
|
Future<void> performQrCodeAttendance({double? latitude, double? longitude, required BuildContext context}) async {
|
|
UserProvider userProvider = Provider.of<UserProvider>(context, listen: false);
|
|
|
|
String qrCodeValue = await Navigator.of(context).push(
|
|
MaterialPageRoute(builder: (_) => ScanQr()),
|
|
) as String;
|
|
|
|
if (qrCodeValue != null) {
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
Future<void> handleNfcAttendance({double? latitude = 0, double? longitude = 0, required BuildContext context}) async {
|
|
// 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,
|
|
double? longitude,
|
|
BuildContext context,
|
|
) async {
|
|
showLoading(context);
|
|
try {
|
|
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);
|
|
|
|
if (swipeResponse.isSuccess == true) {
|
|
hideLoading(context);
|
|
Navigator.pushNamed(context, SwipeSuccessView.routeName);
|
|
} else {
|
|
hideLoading(context);
|
|
showErrorDialog(message: swipeResponse.message ?? "Unexpected error occurred", context: context);
|
|
}
|
|
} catch (errSwipeGeneralUtilsor) {
|
|
hideLoading(context);
|
|
}
|
|
}
|
|
|
|
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,
|
|
builder: (BuildContext cxt) => ConfirmDialog(
|
|
message: message,
|
|
onTap: () async {
|
|
Navigator.pop(navigatorKey.currentState!.overlay!.context);
|
|
onTap!();
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
List<Widget> availableAttendanceMethodList({required BuildContext context, required UserProvider userProvider, required bool isNfcSupported}) {
|
|
List<Widget> availableMethods = [];
|
|
if (userProvider.user!.enableNFC!) {
|
|
availableMethods.add(attendanceTypeCard(SwipeTypeEnum.NFC.name, 'nfc_icon', isNfcSupported, () {
|
|
Navigator.pop(context);
|
|
handleSwipe(swipeType: SwipeTypeEnum.NFC, isEnable: userProvider.user!.enableNFC!, context: navigatorKey.currentState!.overlay!.context);
|
|
}, context));
|
|
}
|
|
if (userProvider.user!.enableQR!) {
|
|
availableMethods.add(attendanceTypeCard(SwipeTypeEnum.QR.name, 'qr', userProvider.user!.enableQR!, () {
|
|
Navigator.pop(context);
|
|
handleSwipe(swipeType: SwipeTypeEnum.QR, isEnable: userProvider.user!.enableQR!, context: navigatorKey.currentState!.overlay!.context);
|
|
}, context));
|
|
}
|
|
if (kDebugMode) {
|
|
userProvider.user!.enableWifi = true;
|
|
}
|
|
|
|
if (userProvider.user!.enableWifi!) {
|
|
availableMethods.add(attendanceTypeCard(SwipeTypeEnum.Wifi.name, 'wifi_icon', userProvider.user!.enableWifi!, () {
|
|
Navigator.pop(context);
|
|
handleSwipe(swipeType: SwipeTypeEnum.Wifi, isEnable: userProvider.user!.enableWifi!, context: navigatorKey.currentState!.overlay!.context);
|
|
}, context));
|
|
}
|
|
return availableMethods;
|
|
}
|
|
|
|
void showSwipeTypeBottomSheetSheet({required bool isNfcSupported}) {
|
|
BuildContext context = navigatorKey.currentState!.overlay!.context;
|
|
UserProvider _userProvider = Provider.of<UserProvider>(context, listen: false);
|
|
|
|
showModalBottomSheet(
|
|
context: context,
|
|
shape: const RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.vertical(
|
|
top: Radius.circular(20),
|
|
),
|
|
),
|
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
|
clipBehavior: Clip.antiAliasWithSaveLayer,
|
|
builder: (BuildContext context) => Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
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,
|
|
GridView(
|
|
padding: const EdgeInsets.all(0),
|
|
shrinkWrap: true,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1, crossAxisSpacing: 12, mainAxisSpacing: 12),
|
|
children: availableAttendanceMethodList(context: context, userProvider: _userProvider, isNfcSupported: isNfcSupported)),
|
|
],
|
|
).paddingAll(16),
|
|
);
|
|
}
|
|
|
|
void readNFc({Function(String)? onRead}) {
|
|
NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
|
|
MifareUltralight f;
|
|
if (Platform.isAndroid) {
|
|
f = MifareUltralight(tag: tag, identifier: tag.data["nfca"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22);
|
|
} else {
|
|
f = MifareUltralight(tag: tag, identifier: tag.data["mifare"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22);
|
|
}
|
|
String identifier = f.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
|
|
NfcManager.instance.stopSession();
|
|
onRead!(identifier);
|
|
}).catchError((err) {
|
|
print(err);
|
|
});
|
|
}
|
|
|
|
//HUAWEI DECISION MAKING
|
|
Future<bool> isGoogleServicesAvailable() async {
|
|
GooglePlayServicesAvailability availability = await GoogleApiAvailability.instance.checkGooglePlayServicesAvailability();
|
|
String status = availability.toString().split('.').last;
|
|
if (status == "success") {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
Future<void> performWifiAttendance({required double latitude, required double long, required BuildContext context}) async {
|
|
String ssId = String.fromCharCodes(base64Decode("SE1HLU1PSEVNTQ=="));
|
|
String password = String.fromCharCodes(base64Decode("TTBoZW1tQDEyMTI="));
|
|
showLoading(context);
|
|
bool isConnected = await WiFiForIoTPlugin.connect(ssId, password: password, joinOnce: Platform.isIOS ? false : true, security: NetworkSecurity.WPA, withInternet: false);
|
|
|
|
if (Platform.isIOS) {
|
|
if (await WiFiForIoTPlugin.getSSID() == ssId) {
|
|
isConnected = true;
|
|
} else {
|
|
isConnected = false;
|
|
}
|
|
}
|
|
UserProvider userProvider = Provider.of<UserProvider>(context, listen: false);
|
|
|
|
if (isConnected) {
|
|
await WiFiForIoTPlugin.forceWifiUsage(true);
|
|
await Future.delayed(const Duration(seconds: 6));
|
|
try {
|
|
final swipeModel = Swipe(swipeTypeValue: SwipeTypeEnum.Wifi.getIntFromSwipeTypeEnum(), value: '', latitude: latitude, longitude: long);
|
|
|
|
final swipeResponse = await userProvider.makeSwipe(model: swipeModel);
|
|
await closeWifiRequest();
|
|
if (swipeResponse.isSuccess == true) {
|
|
hideLoading(context);
|
|
Navigator.pushNamed(context, SwipeSuccessView.routeName);
|
|
} else {
|
|
hideLoading(context);
|
|
await Future.delayed(const Duration(milliseconds: 250));
|
|
showErrorDialog(message: swipeResponse.message ?? "Unexpected error occurred", context: context);
|
|
}
|
|
} catch (errSwipeGeneralUtilsor) {
|
|
hideLoading(context);
|
|
await closeWifiRequest();
|
|
}
|
|
} else {
|
|
// if (userProvider.) {
|
|
hideLoading(context);
|
|
confirmDialog(context, "Come Near HMG Wifi");
|
|
// } else {
|
|
// await closeWifiRequest();
|
|
// }
|
|
await closeWifiRequest();
|
|
}
|
|
}
|
|
|
|
Future<bool> closeWifiRequest() async {
|
|
if (Platform.isAndroid) {
|
|
await WiFiForIoTPlugin.forceWifiUsage(false);
|
|
}
|
|
return await WiFiForIoTPlugin.disconnect();
|
|
}
|
|
}
|