qr scanner improvements

main_production_upgrade_ios
Sikander Saleem 6 days ago
parent c4b4c7f75f
commit d59a8f4d6f

@ -10,12 +10,13 @@
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.USE_BIOMETRIC"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.VIBRATE" />
<queries>
<intent>
@ -108,14 +109,20 @@
</intent-filter>
</receiver>
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver" />
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
<receiver
android:name="com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver"
android:exported="false" />
<receiver
android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver"
android:exported="false" />
<receiver
android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>

@ -6,6 +6,7 @@ import 'dart:typed_data';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_vibrate/flutter_vibrate.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:google_api_availability/google_api_availability.dart';
@ -79,6 +80,13 @@ class Utils {
return await Future.delayed(Duration(milliseconds: millis));
}
static void hapticFeedback() async {
bool canVibrate = await Vibrate.canVibrate;
if (canVibrate) {
Vibrate.feedback(FeedbackType.medium);
}
}
static bool isBeforeOrEqualCurrentTime(TimeOfDay t1, TimeOfDay t2) {
return t1.hour < t2.hour || (t1.hour == t2.hour && t1.minute <= t2.minute);
}
@ -428,45 +436,45 @@ class Utils {
NfcManager.instance.startSession(
onDiscovered: (NfcTag tag) async {
String identifier = '';
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('');
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');

@ -372,7 +372,7 @@ 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) {

@ -1,224 +1,6 @@
//Todo delete after testing
// import 'dart:async';
// import 'dart:io';
//
// import 'package:flutter/material.dart';
// import 'package:fluttertoast/fluttertoast.dart';
// import 'package:mobile_scanner/mobile_scanner.dart';
// import 'package:provider/provider.dart';
// import 'package:qr_code_scanner_plus/qr_code_scanner_plus.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/helper/utils.dart';
// import 'package:test_sa/models/device/asset.dart';
// import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
// import 'package:test_sa/modules/tm_module/device_transfer/search_device_page.dart';
// import 'package:test_sa/new_views/app_style/app_color.dart';
// import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
//
// import '../../../controllers/providers/api/devices_provider.dart';
// import '../../../models/device/asset_search.dart';
// import '../../../new_views/common_widgets/app_filled_button.dart';
//
// class AssetScanQr extends StatefulWidget {
// static const String id = "/asset-scan-qr";
//
// const AssetScanQr({Key? key, required this.title, this.multiSelection = false, this.enablePickManually = true}) : super(key: key);
// final String title;
// final bool multiSelection;
// final bool enablePickManually;
//
// @override
// _AssetScanQrState createState() => _AssetScanQrState();
// }
//
// class _AssetScanQrState extends State<AssetScanQr> {
// // Barcode result;
// // QRViewController? _controller;
// bool _scanDone = false;
// bool _scanning = false;
// final GlobalKey qrKey = GlobalKey(debugLabel: 'QR_scanner');
// late AssetProvider _devicesProvider;
//
// MobileScannerController? controller;
//
// @override
// void initState() {
// // TODO: implement initState
// super.initState();
// controller = MobileScannerController(
// detectionSpeed: DetectionSpeed.noDuplicates,
// formats: [],
// returnImage: false,
// torchEnabled: false,
// invertImage: false,
// autoZoom: true,
// );
// }
//
// @override
// void dispose() {
// super.dispose();
// controller?.dispose();
// _devicesProvider.searchReset();
// }
//
// _pickManually() async {
// controller?.pause();
// await Navigator.push(context, MaterialPageRoute(builder: (context) => SearchDevicePage(multiSelection: widget.multiSelection))).then((value) => controller?.stop());
// }
//
// _getDevice(String result, {bool isQr = false}) async {
// _devicesProvider.reset();
// await _devicesProvider.getAssets(
// search: DeviceSearch(assetNo: result, assetSerialNumber: ""),
// isQr: isQr,
// );
// return _devicesProvider.devices;
// }
//
// @override
// Widget build(BuildContext context) {
// _devicesProvider = Provider.of<AssetProvider>(context);
// return Scaffold(
// appBar: DefaultAppBar(title: widget.title),
// body: Column(
// children: [
// Stack(
// children: [
// MobileScanner(
// key: qrKey,
// tapToFocus: true,
// controller: controller,
// onDetect: (result) async {
// String? scanData = result.barcodes.first.rawValue;
// if (!_scanDone) {
// _scanDone = true;
// if (!widget.enablePickManually) {
// if (scanData != null) {
// Navigator.of(context).pop(Asset(assetNumber: scanData));
// } else {
// _scanDone = false;
// }
// } else {
// setState(() {
// _scanning = true;
// });
// final result = await _getDevice(scanData!, isQr: true);
// setState(() {
// _scanning = false;
// });
// if (result.isNotEmpty) {
// if (widget.multiSelection) {
// Navigator.of(context).pop(<Asset>[result[0]]);
// } else {
// Navigator.of(context).pop(result[0]);
// }
// } else {
// Utils.showToast("No Item Found. Try Again", toastGravity: ToastGravity.CENTER);
// _scanDone = false;
// }
// }
// }
// },
// ),
//
// // QRView(
// // key: qrKey,
// // onQRViewCreated: (QRViewController controller) {
// // setState(() {
// // _controller = controller;
// // });
// // controller.scannedDataStream.listen((scanData) async {
// // if (!_scanDone) {
// // _scanDone = true;
// // if (!widget.enablePickManually) {
// // if (scanData.code != null) {
// // Navigator.of(context).pop(Asset(assetNumber: scanData.code!));
// // } else {
// // _scanDone = false;
// // }
// // } else {
// // _controller?.pauseCamera();
// // setState(() {
// // _scanning = true;
// // });
// // final result = await _getDevice(scanData.code!, isQr: true);
// // setState(() {
// // _scanning = false;
// // });
// // if (result.isNotEmpty) {
// // if (widget.multiSelection) {
// // Navigator.of(context).pop(<Asset>[result[0]]);
// // } else {
// // Navigator.of(context).pop(result[0]);
// // }
// // } else {
// // Utils.showToast("No Item Found. Try Again", toastGravity: ToastGravity.CENTER);
// // _controller?.resumeCamera();
// // _scanDone = false;
// // }
// // }
// // }
// // });
// // },
// // ),
// Center(
// child: 'scan'.toSvgAsset(
// height: 283.toScreenHeight.toInt(),
// width: 283.toScreenWidth.toInt(),
// fit: BoxFit.fitHeight,
// ),
// ),
// if (_scanning)
// Container(
// width: 56.toScreenHeight,
// height: 56.toScreenHeight,
// padding: const EdgeInsets.all(8),
// decoration: const BoxDecoration(shape: BoxShape.circle, color: Colors.white),
// child: const CircularProgressIndicator(color: AppColor.primary10, strokeWidth: 3),
// ).center
// ],
// ).expanded,
// if (widget.enablePickManually)
// FooterActionButton.footerContainer(
// context: context,
// child: AppFilledButton(
// label: context.translation.pickManually,
// onPressed: _pickManually,
// ),
// ),
// ],
// ),
// // bottomSheet:
// // 16.height,
//
// // Container(
// // height: 82.toScreenHeight,
// // color: Colors.white,
// // width: MediaQuery.of(context).size.width,
// // child: Center(
// // child: SizedBox(
// // height: 50.toScreenHeight,
// // width: 358.toScreenWidth,
// // child: AppFilledButton(
// // label: context.translation.pickManually,
// // onPressed: _pickManually,
// // ),
// // ),
// // ),
// // )
// );
// }
// }
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:google_api_availability/google_api_availability.dart';
@ -371,7 +153,6 @@ class _AssetScanQrState extends State<AssetScanQr> {
);
_scanDone = false;
mobileController?.start();
qrController?.resumeCamera();
}
}
@ -380,9 +161,42 @@ class _AssetScanQrState extends State<AssetScanQr> {
controller.scannedDataStream.listen((scanData) async {
if (_scanDone) return;
if (scanData.code == null || scanData.code!.isEmpty) return;
await _handleScan(scanData.code!);
final code = scanData.code;
if (code == null || code.isEmpty) return;
_scanDone = true;
await qrController?.pauseCamera();
if (!widget.enablePickManually) {
Navigator.of(context).pop(Asset(assetNumber: code));
return;
}
setState(() {
_scanning = true;
});
final result = await _getDevice(code, isQr: true);
setState(() {
_scanning = false;
});
if (result.isNotEmpty) {
if (widget.multiSelection) {
Navigator.of(context).pop(<Asset>[result[0]]);
} else {
Navigator.of(context).pop(result[0]);
}
} else {
Utils.showToast(
"No Item Found. Try Again",
toastGravity: ToastGravity.CENTER,
);
_scanDone = false;
await qrController?.resumeCamera();
}
});
}

@ -5,6 +5,10 @@ import 'package:mobile_scanner/mobile_scanner.dart';
import 'package:qr_code_scanner_plus/qr_code_scanner_plus.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/helper/utils.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import '../buttons/app_icon_button.dart';
class ScanQr extends StatefulWidget {
@ -26,6 +30,7 @@ class _ScanQrState extends State<ScanQr> {
@override
void initState() {
// TODO: implement initState
super.initState();
_initScanner();
}
@ -64,6 +69,7 @@ class _ScanQrState extends State<ScanQr> {
if (scanData.code == null || scanData.code!.isEmpty) return;
_scanDone = true;
Utils.hapticFeedback();
Navigator.of(context).pop(scanData.code);
});
}
@ -77,50 +83,47 @@ class _ScanQrState extends State<ScanQr> {
@override
Widget build(BuildContext context) {
if (_isLoading) {
return const Scaffold(
body: Center(child: CircularProgressIndicator()),
);
}
return Scaffold(
body: Stack(
children: [
_isHuawei
? QRView(
key: qrKey,
onQRViewCreated: _onQrViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.white,
borderRadius: 12,
borderLength: 30,
borderWidth: 4,
cutOutSize: MediaQuery.of(context).size.width * 0.7,
),
)
: MobileScanner(
controller: mobileController,
onDetect: (capture) {
if (_scanDone) return;
final barcodes = capture.barcodes;
if (barcodes.isEmpty) return;
final value = barcodes.first.rawValue;
if (value == null || value.isEmpty) return;
_scanDone = true;
Navigator.of(context).pop(value);
body: _isLoading
? const CircularProgressIndicator(color: AppColor.primary10).center
: Stack(
children: [
_isHuawei
? QRView(
key: qrKey,
onQRViewCreated: _onQrViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.white,
borderRadius: 12,
borderLength: 30,
borderWidth: 4,
cutOutSize: MediaQuery.of(context).size.width * 0.7,
),
)
: MobileScanner(
controller: mobileController,
onDetect: (capture) {
if (_scanDone) return;
final barcodes = capture.barcodes;
if (barcodes.isEmpty) return;
final value = barcodes.first.rawValue;
if (value == null || value.isEmpty) return;
_scanDone = true;
Utils.hapticFeedback();
Navigator.of(context).pop(value);
},
),
_ScannerOverlay(
// scanDone: _scanDone,
onBack: () {
if (!_scanDone) _scanDone = true;
Navigator.of(context).pop();
},
showSvgOverlay: !_isHuawei,
),
_ScannerOverlay(
// scanDone: _scanDone,
onBack: () {
if (!_scanDone) _scanDone = true;
Navigator.of(context).pop();
},
showSvgOverlay: !_isHuawei,
),
],
),
],
),
);
}
}

@ -593,6 +593,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "5.2.0"
flutter_vibrate:
dependency: "direct main"
description:
name: flutter_vibrate
sha256: "6eea0e94dd7dc8c7872e994a1139d55a8640e32fd5898ff59ee8bd53b8dea3b3"
url: "https://pub.dev"
source: hosted
version: "1.4.0"
flutter_web_plugins:
dependency: transitive
description: flutter
@ -750,14 +758,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "6.14.0+300"
huawei_scan:
dependency: "direct main"
description:
name: huawei_scan
sha256: "71bc8ce2e90fa07c2d82829ce928ebe3e69b3326fb55d2e7a68f62d9efdef6dd"
url: "https://pub.dev"
source: hosted
version: "2.12.0+304"
image:
dependency: transitive
description:
@ -1941,4 +1941,4 @@ packages:
version: "3.1.3"
sdks:
dart: ">=3.11.0 <4.0.0"
flutter: ">=3.38.4"
flutter: ">=3.38.5"

@ -89,7 +89,7 @@ dependencies:
pie_chart: ^5.4.0
badges: ^3.1.1
# buttons_tabbar: ^1.1.2
# buttons_tabbar: ^1.1.2
flutter_custom_month_picker: ^0.1.3
local_auth: ^2.3.0
google_api_availability: ^5.0.1
@ -106,9 +106,9 @@ dependencies:
audio_waveforms: ^1.3.0
signalr_netcore: ^1.4.4
ellipsized_text: ^2.0.0
huawei_scan: ^2.12.0+304
local_auth_darwin: ^1.4.0
flutter_vibrate: ^1.4.0
dev_dependencies:
flutter_test:
sdk: flutter

Loading…
Cancel
Save