From 3cc7176c63987f77964513aa89037c352419df46 Mon Sep 17 00:00:00 2001 From: nextwo <1234> Date: Wed, 17 Jul 2024 23:58:43 +0300 Subject: [PATCH] scan asset ui --- assets/images/scan.svg | 3 + lib/l10n/app_ar.arb | 4 +- lib/l10n/app_en.arb | 4 +- .../common_widgets/custom_app_bar.dart | 43 +++++++ .../equipment/single_device_picker.dart | 3 +- lib/views/widgets/qr/scan_qr_widget.dart | 118 ++++++++++++++++++ pubspec.lock | 8 ++ pubspec.yaml | 1 + 8 files changed, 181 insertions(+), 3 deletions(-) create mode 100644 assets/images/scan.svg create mode 100644 lib/new_views/common_widgets/custom_app_bar.dart create mode 100644 lib/views/widgets/qr/scan_qr_widget.dart diff --git a/assets/images/scan.svg b/assets/images/scan.svg new file mode 100644 index 00000000..11cf848d --- /dev/null +++ b/assets/images/scan.svg @@ -0,0 +1,3 @@ + + + diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb index de1578a5..e48c80e1 100644 --- a/lib/l10n/app_ar.arb +++ b/lib/l10n/app_ar.arb @@ -384,5 +384,7 @@ "costCodeName" : "اسم رمز التكلفة", "installationDate" : "تاريخ التثبيت", "nextPmDate" : "موعد الزيارة الوقائية التالية", - "lastPmDate" : "موعد الزيارة الوقائية الأخيرة" + "lastPmDate" : "موعد الزيارة الوقائية الأخيرة", + "assetScan" : "مسح الجهاز", + "pickManually" : "اختر يدويا" } \ No newline at end of file diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 4679fa8f..01322a8a 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -387,5 +387,7 @@ "costCodeName" : "Cost Code Name", "installationDate" : "Installation Date", "nextPmDate" : "Next PM Date", - "lastPmDate" : "Last PM Date" + "lastPmDate" : "Last PM Date", + "assetScan" : "Asset Scan", + "pickManually" : "Pick Manually" } \ No newline at end of file diff --git a/lib/new_views/common_widgets/custom_app_bar.dart b/lib/new_views/common_widgets/custom_app_bar.dart new file mode 100644 index 00000000..c34e5cb3 --- /dev/null +++ b/lib/new_views/common_widgets/custom_app_bar.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.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 '../app_style/app_color.dart'; + +class CustomAppBar extends StatelessWidget implements PreferredSizeWidget { + final String title; + final List actions; + final double bottomCorner; + + const CustomAppBar({this.title, this.actions, this.bottomCorner, Key key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return AppBar( + automaticallyImplyLeading: false, + titleSpacing: 16, + title: Row( + children: [ + const Icon(Icons.arrow_back_ios).onPress(() { + Navigator.of(context).pop(); + }), + Text( + title ?? "", + style: AppTextStyles.heading3?.copyWith(fontWeight: FontWeight.w600, color: context.isDark ? AppColor.neutral30 : AppColor.neutral50), + ).expanded, + ], + ), + actions: actions, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + bottom: Radius.circular(bottomCorner??0), + ), + ), + ); + } + + @override + Size get preferredSize => Size.fromHeight(60.toScreenHeight); +} diff --git a/lib/views/widgets/equipment/single_device_picker.dart b/lib/views/widgets/equipment/single_device_picker.dart index 03fe90c9..3e58b5c6 100644 --- a/lib/views/widgets/equipment/single_device_picker.dart +++ b/lib/views/widgets/equipment/single_device_picker.dart @@ -20,6 +20,7 @@ import '../../../new_views/app_style/app_color.dart'; import '../../pages/device_transfer/asset_filter_screen.dart'; import '../../pages/device_transfer/asset_search_screen.dart'; import '../qr/scan_qr.dart'; +import '../qr/scan_qr_widget.dart'; class MyAssetsPage extends StatefulWidget { static final String id = "/single-device-Picker"; @@ -210,7 +211,7 @@ class _MyAssetsPageState extends State { child: "qr".toSvgAsset(height: 32, fit: BoxFit.fitHeight, color: Theme.of(context).scaffoldBackgroundColor), onPressed: () async { String result = await Navigator.of(context).push( - MaterialPageRoute(builder: (_) => const ScanQr()), + MaterialPageRoute(builder: (_) => ScanQrWidget(title: context.translation.assetScan,)), ) as String; _getDevice(result, isQr: true); }, diff --git a/lib/views/widgets/qr/scan_qr_widget.dart b/lib/views/widgets/qr/scan_qr_widget.dart new file mode 100644 index 00000000..4f4d6306 --- /dev/null +++ b/lib/views/widgets/qr/scan_qr_widget.dart @@ -0,0 +1,118 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:qr_code_scanner/qr_code_scanner.dart'; +import 'package:qr_code_tools/qr_code_tools.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 '../../../new_views/common_widgets/app_filled_button.dart'; +import '../../../new_views/common_widgets/custom_app_bar.dart'; + +class ScanQrWidget extends StatefulWidget { + const ScanQrWidget({Key key, this.title}) : super(key: key); + final String title; + + @override + _ScanQrWidgetState createState() => _ScanQrWidgetState(); +} + +class _ScanQrWidgetState extends State { + Barcode result; + QRViewController _controller; + bool _scanDone = false; + final GlobalKey qrKey = GlobalKey(debugLabel: 'QR_scanner'); + + // In order to get hot reload to work we need to pause the camera if the platform + // is android, or resume the camera if the platform is iOS. + @override + void reassemble() { + super.reassemble(); + if (Platform.isAndroid) { + _controller?.pauseCamera(); + } else if (Platform.isIOS) { + _controller?.resumeCamera(); + } + } + + @override + void dispose() { + super.dispose(); + _controller?.dispose(); + } + + + _pickManually() async { + final picker = ImagePicker(); + final pickedFile = await picker.pickImage(source: ImageSource.gallery); + + if (pickedFile != null) { + try { + String qrData = await QrCodeToolsPlugin.decodeFrom(pickedFile.path); + if (qrData != null && !_scanDone) { + setState(() { + _scanDone = true; + }); + Navigator.of(context).pop(qrData); + } + } catch (e) { + print('Error QR code: $e'); + } + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: SafeArea( + child: Stack( + children: [ + QRView( + key: qrKey, + onQRViewCreated: (QRViewController controller) { + setState(() { + _controller = controller; + }); + controller.scannedDataStream.listen((scanData) { + if (!_scanDone) { + _scanDone = true; + Navigator.of(context).pop(scanData.code); + } + }); + }, + ), + Center( + child: 'scan'.toSvgAsset( + height: 283.toScreenHeight.toInt(), + width: 283.toScreenWidth.toInt(), + fit: BoxFit.fitHeight, + ), + ), + SizedBox( + height: 60.toScreenHeight, + child: CustomAppBar( + title: widget.title ?? '', + bottomCorner: 12, + )), + ], + ), + ), + bottomSheet: 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, + ), + ), + ), + )); + } +} diff --git a/pubspec.lock b/pubspec.lock index 1fcfc4de..2cce00c4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1005,6 +1005,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + qr_code_tools: + dependency: "direct main" + description: + name: qr_code_tools + sha256: "837fe12708ae7d41786e4e07c57719682fb0bc6c2cfc40bc23232148424b1ca8" + url: "https://pub.dev" + source: hosted + version: "0.0.7" recase: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index c20a5a37..130212f9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -56,6 +56,7 @@ dependencies: firebase_core: ^2.4.0 firebase_messaging: ^14.2.0 qr_code_scanner: ^1.0.1 + qr_code_tools: ^0.0.7 flutter_sound: ^9.2.13 permission_handler: ^10.2.0 rive: ^0.9.1