diff --git a/lib/android/qr_scanner/qr_scanner_provider.dart b/lib/android/qr_scanner/qr_scanner_provider.dart index 8c8e00ee..1aa93137 100644 --- a/lib/android/qr_scanner/qr_scanner_provider.dart +++ b/lib/android/qr_scanner/qr_scanner_provider.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:yubico_authenticator/app/state.dart'; +import 'package:yubico_authenticator/cancellation_exception.dart'; import 'qr_scanner_view.dart'; @@ -17,7 +18,8 @@ class AndroidQrScanner implements QrScanner { reverseTransitionDuration: const Duration(seconds: 0), ))); if (scannedCode == null) { - throw Exception('Null value from QR scanner'); + // user has cancelled the scan + throw CancellationException(); } return scannedCode; } diff --git a/lib/android/qr_scanner/qr_scanner_view.dart b/lib/android/qr_scanner/qr_scanner_view.dart index 1f7d2115..9208e870 100755 --- a/lib/android/qr_scanner/qr_scanner_view.dart +++ b/lib/android/qr_scanner/qr_scanner_view.dart @@ -82,12 +82,12 @@ class _QrScannerViewState extends State { void initState() { super.initState(); _status = ScanStatus.scanning; - SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive); + SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); } @override void dispose() { - SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, + SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge, overlays: SystemUiOverlay.values); super.dispose(); } @@ -95,8 +95,7 @@ class _QrScannerViewState extends State { @override Widget build(BuildContext context) { final screenSize = MediaQuery.of(context).size; - return SafeArea( - child: Scaffold( + return Scaffold( resizeToAvoidBottomInset: false, extendBodyBehindAppBar: true, extendBody: true, @@ -130,7 +129,7 @@ class _QrScannerViewState extends State { maintainSize: true, visible: _permissionsGranted, child: QRScannerZxingView( - key: _zxingViewKey, + key: _zxingViewKey, marginPct: 50, onDetect: (scannedData) => handleResult(scannedData), onViewInitialized: (bool permissionsGranted) { @@ -164,6 +163,6 @@ class _QrScannerViewState extends State { )), ], ), - )); + ); } } diff --git a/lib/app/logging.dart b/lib/app/logging.dart index 16ed3fea..23667e76 100755 --- a/lib/app/logging.dart +++ b/lib/app/logging.dart @@ -109,8 +109,10 @@ class LogWarningOverlay extends StatelessWidget { return const SizedBox(); } + var deviceBottomViewPadding = MediaQueryData.fromWindow(WidgetsBinding.instance.window).viewPadding.bottom; return Padding( - padding: const EdgeInsets.fromLTRB(0, 0, 0, 20), + padding: + EdgeInsets.fromLTRB(5, 0, 5, deviceBottomViewPadding + 15), child: Align( alignment: Alignment.bottomCenter, child: IgnorePointer( @@ -119,9 +121,10 @@ class LogWarningOverlay extends StatelessWidget { textDirection: TextDirection.ltr, textAlign: TextAlign.center, style: const TextStyle( - color: Colors.red, - fontWeight: FontWeight.bold, - ), + color: Colors.red, + fontWeight: FontWeight.bold, + height: 1.5, + fontSize: 16), ), ), ), diff --git a/lib/app/views/app_page.dart b/lib/app/views/app_page.dart index 5c96f706..aa487502 100755 --- a/lib/app/views/app_page.dart +++ b/lib/app/views/app_page.dart @@ -47,35 +47,39 @@ class AppPage extends ConsumerWidget { }, ); - Widget _buildScrollView() => SafeArea( - bottom: false, - child: SingleChildScrollView( - child: Center( - child: SizedBox( - width: 700, - child: Column( - children: [ - child, - if (actions.isNotEmpty) - Align( - alignment: - centered ? Alignment.center : Alignment.centerLeft, - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 16.0, horizontal: 18.0), - child: Wrap( - spacing: 4, - runSpacing: 4, - children: actions, - ), + Widget _buildScrollView() { + var bottomPadding = MediaQueryData.fromWindow(WidgetsBinding.instance.window).viewPadding.bottom; + return SafeArea( + bottom: bottomPadding > 24, + maintainBottomViewPadding: false, + child: SingleChildScrollView( + child: Center( + child: SizedBox( + width: 700, + child: Column( + children: [ + child, + if (actions.isNotEmpty) + Align( + alignment: + centered ? Alignment.center : Alignment.centerLeft, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 16.0, horizontal: 18.0), + child: Wrap( + spacing: 4, + runSpacing: 4, + children: actions, ), ), - ], - ), + ), + ], ), ), ), - ); + ), + ); + } Scaffold _buildScaffold(BuildContext context, WidgetRef ref, bool hasDrawer) { return Scaffold( diff --git a/lib/oath/views/add_account_page.dart b/lib/oath/views/add_account_page.dart index f90d6f99..2d8d6026 100755 --- a/lib/oath/views/add_account_page.dart +++ b/lib/oath/views/add_account_page.dart @@ -104,11 +104,14 @@ class _OathAddAccountPageState extends ConsumerState { } else { errorMessage = e.toString(); } - showMessage( - context, - '${AppLocalizations.of(context)!.oath_failed_reading_qr}: $errorMessage', - duration: const Duration(seconds: 4), - ); + + if (e is! CancellationException) { + showMessage( + context, + '${AppLocalizations.of(context)!.oath_failed_reading_qr}: $errorMessage', + duration: const Duration(seconds: 4), + ); + } setState(() { _qrState = _QrScanState.failed; });