import 'dart:io'; import 'package:flutter/material.dart'; import 'package:google_api_availability/google_api_availability.dart'; 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 { const ScanQr({Key? key}) : super(key: key); @override State createState() => _ScanQrState(); } class _ScanQrState extends State { MobileScannerController? mobileController; QRViewController? qrController; final GlobalKey qrKey = GlobalKey(debugLabel: 'QR_scanner'); bool _scanDone = false; bool _isHuawei = false; bool _isLoading = true; @override void initState() { // TODO: implement initState super.initState(); _initScanner(); } Future _initScanner() async { _isHuawei = Platform.isAndroid && !(await isGoogleServicesAvailable()); if (!_isHuawei) { mobileController = MobileScannerController( detectionSpeed: DetectionSpeed.noDuplicates, formats: [], returnImage: false, torchEnabled: false, invertImage: false, autoZoom: true, ); } if (mounted) { setState(() { _isLoading = false; }); } } Future isGoogleServicesAvailable() async { GooglePlayServicesAvailability availability = await GoogleApiAvailability.instance.checkGooglePlayServicesAvailability(); String status = availability.toString().split('.').last; return status == "success"; } void _onQrViewCreated(QRViewController controller) { qrController = controller; controller.scannedDataStream.listen((scanData) { if (_scanDone) return; if (scanData.code == null || scanData.code!.isEmpty) return; _scanDone = true; Utils.hapticFeedback(); Navigator.of(context).pop(scanData.code); }); } @override void dispose() { mobileController?.dispose(); qrController?.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( 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, ), ], ), ); } } class _ScannerOverlay extends StatelessWidget { final VoidCallback onBack; final bool showSvgOverlay; const _ScannerOverlay({ Key? key, required this.onBack, this.showSvgOverlay = true, }) : super(key: key); @override Widget build(BuildContext context) { return SizedBox.expand( child: Stack( children: [ if (showSvgOverlay) Center( child: 'scan'.toSvgAsset( height: 283.toScreenHeight.toInt(), width: 283.toScreenWidth.toInt(), fit: BoxFit.fitHeight, ), ), Positioned( bottom: 80, // adjust if needed left: 0, right: 0, child: Center( child: Text( "Point camera at a QR code to scan", style: TextStyle( color: Colors.white.withOpacity(0.8), fontSize: 16, ), ), ), ), SafeArea( child: Padding( padding: const EdgeInsets.all(12.0), child: AIconButton( iconData: Icons.arrow_back, onPressed: onBack, ), ), ), ], ), ); } }