import 'package:flutter/material.dart'; import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:manager_api/api.dart'; import 'package:mymuseum_visitapp/Helpers/translationHelper.dart'; import 'package:mymuseum_visitapp/Models/visitContext.dart'; import 'package:mymuseum_visitapp/Screens/Article/article_page.dart'; import 'package:mymuseum_visitapp/Screens/Quizz/quizz_page.dart'; import 'package:mymuseum_visitapp/app_context.dart'; import 'package:mymuseum_visitapp/constants.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:qr_code_scanner/qr_code_scanner.dart'; class ScannerDialog extends StatefulWidget { const ScannerDialog({Key? key, required this.appContext}) : super(key: key); final AppContext? appContext; @override State createState() => _ScannerDialogState(); } class _ScannerDialogState extends State { Barcode? result; QRViewController? controller; final GlobalKey qrKey = GlobalKey(debugLabel: 'QR'); // 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(); } controller!.resumeCamera(); } @override Widget build(BuildContext context) { Size size = MediaQuery.of(context).size; return Container( height: size.height *0.5, width: size.width *0.9, child: Stack( children: [ Center( child: ClipRRect( borderRadius: BorderRadius.circular(10.0), child: _buildQrView(context), ) ), Positioned( top: 0, right: 0, child: Container( width: 45, height: 45, decoration: BoxDecoration( shape: BoxShape.rectangle, color: kBlue1, borderRadius: BorderRadius.circular(20.0), ), margin: const EdgeInsets.all(8), child: InkWell( onTap: () async { await controller?.toggleFlash(); setState(() {}); }, child: FutureBuilder( future: controller?.getFlashStatus(), builder: (context, snapshot) { return const Icon(Icons.flash_on, color: Colors.white); }, )), ), ), Positioned( bottom: 0, right: 0, child: Container( width: 45, height: 45, decoration: BoxDecoration( shape: BoxShape.rectangle, color: kBlue1, borderRadius: BorderRadius.circular(20.0), ), margin: const EdgeInsets.all(8), child: InkWell( onTap: () async { await controller?.flipCamera(); setState(() {}); }, child: FutureBuilder( future: controller?.getCameraInfo(), builder: (context, snapshot) { return const Icon(Icons.flip_camera_android, color: Colors.white); }, )), ), ), ], ), ); } Widget _buildQrView(BuildContext context) { // For this example we check how width or tall the device is and change the scanArea and overlay accordingly. var scanArea = (MediaQuery.of(context).size.width < 400 || MediaQuery.of(context).size.height < 400) ? 225.0 : 300.0; // To ensure the Scanner view is properly sizes after rotation // we need to listen for Flutter SizeChanged notification and update controller return QRView( key: qrKey, onQRViewCreated: _onQRViewCreated, overlay: QrScannerOverlayShape( borderColor: kBlue1, borderRadius: 10, borderLength: 25, borderWidth: 5, cutOutSize: 225.0), onPermissionSet: (ctrl, p) => _onPermissionSet(context, ctrl, p), ); } _onQRViewCreated(QRViewController controller) { setState(() { this.controller = controller; }); if (Platform.isAndroid) { controller.pauseCamera(); } controller.resumeCamera(); controller.scannedDataStream.listen((scanData) { setState(() { result = scanData; var code = result == null ? "" : result!.code.toString(); if(result!.format == BarcodeFormat.qrcode) { controller.pauseCamera(); //print("QR CODE FOUND"); /*ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('QR CODE FOUND - ${code.toString()}')), );*/ VisitAppContext visitAppContext = widget.appContext!.getContext(); if(!visitAppContext.sectionIds!.contains(code)) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(TranslationHelper.getFromLocale('invalidQRCode', widget.appContext!.getContext())), backgroundColor: kBlue2), ); Navigator.of(context).pop(); } else { SectionDTO section = visitAppContext.currentSections!.firstWhere((cs) => cs!.id == code)!; switch(section.type) { case SectionType.Article: Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) { return ArticlePage(visitAppContextIn: visitAppContext, articleId: code); }, ), ); break; case SectionType.Quizz: Navigator.pushReplacement( context, MaterialPageRoute( builder: (context) { return QuizzPage(visitAppContextIn: visitAppContext, sectionId: code); }, ), ); break; } } } }); }); } Future _onPermissionSet(BuildContext context, QRViewController ctrl, bool p) async { //log('${DateTime.now().toIso8601String()}_onPermissionSet $p'); if (!p) { var status = await Permission.camera.status; if(!status.isGranted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('no Permission')), ); // You can request multiple permissions at once. Map statuses = await [ Permission.camera, ].request(); print(statuses[Permission.camera]); print(status); } } } @override void dispose() { controller?.dispose(); super.dispose(); } } showScannerDialog (BuildContext context, AppContext appContext) { showDialog( builder: (BuildContext context) => AlertDialog( shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(10.0)) ), content: ScannerDialog(appContext: appContext), contentPadding: EdgeInsets.zero, ), context: context ); }