diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index ae995740..d597ec1d 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -10,12 +10,13 @@
-
-
+
+
-
+
+
@@ -108,14 +109,20 @@
-
-
-
+
+
+
-
-
+
+
-
+
diff --git a/lib/helper/utils.dart b/lib/helper/utils.dart
index 82d3f879..55d40f74 100644
--- a/lib/helper/utils.dart
+++ b/lib/helper/utils.dart
@@ -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');
diff --git a/lib/new_views/swipe_module/utils/swipe_general_utils.dart b/lib/new_views/swipe_module/utils/swipe_general_utils.dart
index 4eb96010..ee087dee 100644
--- a/lib/new_views/swipe_module/utils/swipe_general_utils.dart
+++ b/lib/new_views/swipe_module/utils/swipe_general_utils.dart
@@ -372,7 +372,7 @@ class SwipeGeneralUtils {
UserProvider userProvider = Provider.of(context, listen: false);
String qrCodeValue = await Navigator.of(context).push(
- MaterialPageRoute(builder: (_) => ScanQr()),
+ MaterialPageRoute(builder: (_) => const ScanQr()),
) as String;
if (qrCodeValue != null) {
diff --git a/lib/views/widgets/qr/asset_scan_qr.dart b/lib/views/widgets/qr/asset_scan_qr.dart
index 022cc559..10313de5 100644
--- a/lib/views/widgets/qr/asset_scan_qr.dart
+++ b/lib/views/widgets/qr/asset_scan_qr.dart
@@ -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 {
-// // 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(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([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([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 {
);
_scanDone = false;
mobileController?.start();
- qrController?.resumeCamera();
}
}
@@ -380,9 +161,42 @@ class _AssetScanQrState extends State {
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([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();
+ }
});
}
diff --git a/lib/views/widgets/qr/scan_qr.dart b/lib/views/widgets/qr/scan_qr.dart
index 0edec5ae..6e90674e 100644
--- a/lib/views/widgets/qr/scan_qr.dart
+++ b/lib/views/widgets/qr/scan_qr.dart
@@ -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 {
@override
void initState() {
+ // TODO: implement initState
super.initState();
_initScanner();
}
@@ -64,6 +69,7 @@ class _ScanQrState extends State {
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 {
@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,
- ),
- ],
- ),
+ ],
+ ),
);
}
}
diff --git a/pubspec.lock b/pubspec.lock
index 590577cc..5880d411 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -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"
diff --git a/pubspec.yaml b/pubspec.yaml
index eccb9416..d4b29e02 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -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