From 2a481bb873ac1ba3936c187bade94107ac95b861 Mon Sep 17 00:00:00 2001 From: Fabian Freund Date: Tue, 2 Jun 2026 11:21:43 +0200 Subject: [PATCH] fix permission error notification --- .../widgets/add_proxy_method_sheet.dart | 6 +---- .../dialogs/qr_scanner_dialog.dart | 22 ++++++++++++++++++- .../presentation/screens/sync_settings.dart | 6 +---- .../widgets/qr_scanner_button.dart | 7 +----- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/apps/weblibre/lib/features/proxy/presentation/widgets/add_proxy_method_sheet.dart b/apps/weblibre/lib/features/proxy/presentation/widgets/add_proxy_method_sheet.dart index 1ea94bb4..d8b6780d 100644 --- a/apps/weblibre/lib/features/proxy/presentation/widgets/add_proxy_method_sheet.dart +++ b/apps/weblibre/lib/features/proxy/presentation/widgets/add_proxy_method_sheet.dart @@ -21,7 +21,6 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:qr_code_scanner_plus/qr_code_scanner_plus.dart'; import 'package:weblibre/core/branding/proxy_brands.dart'; import 'package:weblibre/features/proxy/data/models/proxy_profile_seed.dart'; import 'package:weblibre/features/proxy/domain/services/proxy_input_consumer.dart'; @@ -69,10 +68,7 @@ class AddProxyMethodSheet extends ConsumerWidget { } Future scanQr() async { - final result = await showDialog( - context: context, - builder: (_) => const QrScannerDialog(), - ); + final result = await showQrScannerDialog(context); final code = result?.code?.trim(); if (code == null || code.isEmpty) return; if (!context.mounted) return; diff --git a/apps/weblibre/lib/features/qr_scanner/presentation/dialogs/qr_scanner_dialog.dart b/apps/weblibre/lib/features/qr_scanner/presentation/dialogs/qr_scanner_dialog.dart index 92b76502..3ca2c7b3 100644 --- a/apps/weblibre/lib/features/qr_scanner/presentation/dialogs/qr_scanner_dialog.dart +++ b/apps/weblibre/lib/features/qr_scanner/presentation/dialogs/qr_scanner_dialog.dart @@ -21,9 +21,26 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:permission_handler/permission_handler.dart'; import 'package:qr_code_scanner_plus/qr_code_scanner_plus.dart'; import 'package:weblibre/utils/ui_helper.dart' as ui_helper; +Future showQrScannerDialog(BuildContext context) async { + final cameraPermission = await Permission.camera.request(); + + if (!context.mounted) return null; + + if (!cameraPermission.isGranted) { + ui_helper.showErrorMessage(context, 'No Camera Permission granted'); + return null; + } + + return showDialog( + context: context, + builder: (_) => const QrScannerDialog(), + ); +} + class QrScannerDialog extends HookWidget { const QrScannerDialog({super.key}); @@ -33,6 +50,7 @@ class QrScannerDialog extends HookWidget { final qrController = useState(null); final flashState = useState(false); + final permissionDeniedHandled = useRef(false); useEffect(() { StreamSubscription? sub; @@ -83,11 +101,13 @@ class QrScannerDialog extends HookWidget { qrController.value = controller; }, onPermissionSet: (controller, result) { - if (!result) { + if (!result && !permissionDeniedHandled.value) { + permissionDeniedHandled.value = true; ui_helper.showErrorMessage( context, 'No Camera Permission granted', ); + Navigator.of(context).pop(); } }, ), diff --git a/apps/weblibre/lib/features/sync/presentation/screens/sync_settings.dart b/apps/weblibre/lib/features/sync/presentation/screens/sync_settings.dart index e722d971..86e0aca2 100644 --- a/apps/weblibre/lib/features/sync/presentation/screens/sync_settings.dart +++ b/apps/weblibre/lib/features/sync/presentation/screens/sync_settings.dart @@ -24,7 +24,6 @@ import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_mozilla_components/flutter_mozilla_components.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:qr_code_scanner_plus/qr_code_scanner_plus.dart'; import 'package:weblibre/core/logger.dart'; import 'package:weblibre/core/providers/format.dart'; import 'package:weblibre/features/qr_scanner/presentation/dialogs/qr_scanner_dialog.dart'; @@ -146,10 +145,7 @@ class SyncSettingsScreen extends HookConsumerWidget { ), trailing: const Icon(Icons.chevron_right), onTap: () async { - final barcode = await showDialog( - context: context, - builder: (_) => const QrScannerDialog(), - ); + final barcode = await showQrScannerDialog(context); final code = barcode?.code; if (code == null || code.isEmpty) return; diff --git a/apps/weblibre/lib/presentation/widgets/qr_scanner_button.dart b/apps/weblibre/lib/presentation/widgets/qr_scanner_button.dart index baa0dc15..f3a0f48a 100644 --- a/apps/weblibre/lib/presentation/widgets/qr_scanner_button.dart +++ b/apps/weblibre/lib/presentation/widgets/qr_scanner_button.dart @@ -32,12 +32,7 @@ class QrScannerButton extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { return IconButton( onPressed: () async { - final result = await showDialog( - context: context, - builder: (context) { - return const QrScannerDialog(); - }, - ); + final result = await showQrScannerDialog(context); onScanResult(result); },