import 'package:flutter/material.dart'; import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:manager_api_new/api.dart'; import 'package:mymuseum_visitapp/Components/SlideFromRouteRight.dart'; import 'package:mymuseum_visitapp/Helpers/translationHelper.dart'; import 'package:mymuseum_visitapp/Models/visitContext.dart'; import 'package:mymuseum_visitapp/Screens/section_page.dart'; import 'package:mymuseum_visitapp/app_context.dart'; import 'package:mymuseum_visitapp/constants.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:mobile_scanner/mobile_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 { final MobileScannerController controller = MobileScannerController(); bool isProcessing = false; @override void reassemble() { super.reassemble(); if (Platform.isAndroid) { controller.stop(); } controller.start(); } @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: MobileScanner( controller: controller, //allowDuplicates: false, onDetect: (barcodes) => _onDetect(barcodes), ), ), ), _buildControlButton( icon: Icons.flash_on, onTap: () => controller.toggleTorch(), alignment: Alignment.topRight, ), _buildControlButton( icon: Icons.flip_camera_android, onTap: () => controller.switchCamera(), alignment: Alignment.bottomRight, ), ], ), ); } Widget _buildControlButton({ required IconData icon, required VoidCallback onTap, required Alignment alignment, }) { return Align( alignment: alignment, child: Container( width: 45, height: 45, margin: const EdgeInsets.all(8), decoration: BoxDecoration( shape: BoxShape.rectangle, color: kMainColor1, borderRadius: BorderRadius.circular(20.0), ), child: InkWell( onTap: onTap, child: Icon(icon, color: Colors.white), ), ), ); } void _onDetect(BarcodeCapture capture) { if (isProcessing) return; final barcode = capture.barcodes.first; final code = barcode.rawValue ?? ""; if (barcode.format == BarcodeFormat.qrCode && code.isNotEmpty) { isProcessing = true; RegExp regExp = RegExp(r'^(?:https:\/\/web\.mymuseum\.be\/([^\/]+)\/([^\/]+)\/([^\/]+)|([^\/]+))$'); // myinfomate var match = regExp.firstMatch(code); String? instanceId = match?.group(1); String? configurationId = match?.group(2); String? sectionId = match?.group(3) ?? match?.group(4); if (match == null || sectionId == null) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("L'URL ne correspond pas au format attendu."), backgroundColor: kMainColor2), ); Navigator.of(context).pop(); return; } VisitAppContext visitAppContext = widget.appContext!.getContext(); if (visitAppContext.sectionIds == null || !visitAppContext.sectionIds!.contains(sectionId)) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(TranslationHelper.getFromLocale('invalidQRCode', visitAppContext)), backgroundColor: kMainColor2), ); Navigator.of(context).pop(); } else { dynamic rawSection = visitAppContext.currentSections!.firstWhere((cs) => cs!['id'] == sectionId)!; Navigator.of(context).pop(); Navigator.push( context, SlideFromRightRoute(page: SectionPage( configuration: visitAppContext.configuration!, rawSection: rawSection, visitAppContextIn: visitAppContext, sectionId: rawSection['id'], )), ); } } } @override void dispose() { controller.dispose(); super.dispose(); } } showScannerDialog(BuildContext context, AppContext appContext) { showDialog( context: context, builder: (BuildContext context) => AlertDialog( shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(10.0)), ), content: ScannerDialog(appContext: appContext), contentPadding: EdgeInsets.zero, ), ); }