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.
cloudsolutions-atoms/lib/new_views/swipe_module/utils/swipe_general_utils.dart

531 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 ? Colors.white : AppColor.white70,
borderRadius: BorderRadius.circular(18),
border: Border.all(color: AppColor.white70, width: 2),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
icon.toSvgAsset(color: isEnabled ? null : Colors.grey.withOpacity(0.5)),
title.heading5(context).custom(color: isEnabled ? 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);
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;
//TODO cancel this stream when listening done..
// _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),
),
),
clipBehavior: Clip.antiAliasWithSaveLayer,
builder: (BuildContext context) => Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
context.translation.markAttendance.heading4(context).custom(color: 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();
}
}