fix pending permission request breaking the controller start sequence
Showing
4 changed files
with
35 additions
and
1 deletions
| @@ -11,7 +11,8 @@ export 'src/enums/phone_type.dart'; | @@ -11,7 +11,8 @@ export 'src/enums/phone_type.dart'; | ||
| 11 | export 'src/enums/torch_state.dart'; | 11 | export 'src/enums/torch_state.dart'; |
| 12 | export 'src/mobile_scanner.dart'; | 12 | export 'src/mobile_scanner.dart'; |
| 13 | export 'src/mobile_scanner_controller.dart'; | 13 | export 'src/mobile_scanner_controller.dart'; |
| 14 | -export 'src/mobile_scanner_exception.dart'; | 14 | +export 'src/mobile_scanner_exception.dart' |
| 15 | + hide PermissionRequestPendingException; | ||
| 15 | export 'src/mobile_scanner_platform_interface.dart'; | 16 | export 'src/mobile_scanner_platform_interface.dart'; |
| 16 | export 'src/objects/address.dart'; | 17 | export 'src/objects/address.dart'; |
| 17 | export 'src/objects/barcode.dart'; | 18 | export 'src/objects/barcode.dart'; |
| @@ -290,6 +290,8 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> { | @@ -290,6 +290,8 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> { | ||
| 290 | zoomScale: 1.0, | 290 | zoomScale: 1.0, |
| 291 | ); | 291 | ); |
| 292 | } | 292 | } |
| 293 | + } on PermissionRequestPendingException catch (_) { | ||
| 294 | + // If a permission request was already pending, do nothing. | ||
| 293 | } | 295 | } |
| 294 | } | 296 | } |
| 295 | 297 |
| @@ -39,3 +39,10 @@ class MobileScannerErrorDetails { | @@ -39,3 +39,10 @@ class MobileScannerErrorDetails { | ||
| 39 | /// The error message from the [PlatformException]. | 39 | /// The error message from the [PlatformException]. |
| 40 | final String? message; | 40 | final String? message; |
| 41 | } | 41 | } |
| 42 | + | ||
| 43 | +/// This class represents an exception that is thrown | ||
| 44 | +/// when the scanner was (re)started while a permission request was pending. | ||
| 45 | +/// | ||
| 46 | +/// This exception type is only used internally, | ||
| 47 | +/// and is not part of the public API. | ||
| 48 | +class PermissionRequestPendingException implements Exception {} |
| @@ -39,6 +39,18 @@ class MobileScannerWeb extends MobileScannerPlatform { | @@ -39,6 +39,18 @@ class MobileScannerWeb extends MobileScannerPlatform { | ||
| 39 | /// This container element is used by the barcode reader. | 39 | /// This container element is used by the barcode reader. |
| 40 | HTMLDivElement? _divElement; | 40 | HTMLDivElement? _divElement; |
| 41 | 41 | ||
| 42 | + /// This [Completer] is used to prevent additional calls to the [start] method. | ||
| 43 | + /// | ||
| 44 | + /// To handle lifecycle changes properly, | ||
| 45 | + /// the scanner is stopped when the application is inactive, | ||
| 46 | + /// and restarted when the application gains focus. | ||
| 47 | + /// | ||
| 48 | + /// However, when the camera permission is requested, | ||
| 49 | + /// the application is put in the inactive state due to the permission popup gaining focus. | ||
| 50 | + /// Thus, as long as the permission status is not known, | ||
| 51 | + /// any calls to the [start] method are ignored. | ||
| 52 | + Completer<void>? _cameraPermissionCompleter; | ||
| 53 | + | ||
| 42 | /// The stream controller for the media track settings stream. | 54 | /// The stream controller for the media track settings stream. |
| 43 | final StreamController<MediaTrackSettings> _settingsController = | 55 | final StreamController<MediaTrackSettings> _settingsController = |
| 44 | StreamController.broadcast(); | 56 | StreamController.broadcast(); |
| @@ -50,6 +62,11 @@ class MobileScannerWeb extends MobileScannerPlatform { | @@ -50,6 +62,11 @@ class MobileScannerWeb extends MobileScannerPlatform { | ||
| 50 | MobileScannerPlatform.instance = MobileScannerWeb(); | 62 | MobileScannerPlatform.instance = MobileScannerWeb(); |
| 51 | } | 63 | } |
| 52 | 64 | ||
| 65 | + bool get _hasPendingPermissionRequest { | ||
| 66 | + return _cameraPermissionCompleter != null && | ||
| 67 | + !_cameraPermissionCompleter!.isCompleted; | ||
| 68 | + } | ||
| 69 | + | ||
| 53 | @override | 70 | @override |
| 54 | Stream<BarcodeCapture?> get barcodesStream => _barcodesController.stream; | 71 | Stream<BarcodeCapture?> get barcodesStream => _barcodesController.stream; |
| 55 | 72 | ||
| @@ -174,6 +191,13 @@ class MobileScannerWeb extends MobileScannerPlatform { | @@ -174,6 +191,13 @@ class MobileScannerWeb extends MobileScannerPlatform { | ||
| 174 | 191 | ||
| 175 | @override | 192 | @override |
| 176 | Future<MobileScannerViewAttributes> start(StartOptions startOptions) async { | 193 | Future<MobileScannerViewAttributes> start(StartOptions startOptions) async { |
| 194 | + // If the permission request has not yet completed, | ||
| 195 | + // the camera view is not ready yet. | ||
| 196 | + // Prevent the permission popup from triggering a restart of the scanner. | ||
| 197 | + if (_hasPendingPermissionRequest) { | ||
| 198 | + throw PermissionRequestPendingException(); | ||
| 199 | + } | ||
| 200 | + | ||
| 177 | await _barcodeReader.maybeLoadLibrary( | 201 | await _barcodeReader.maybeLoadLibrary( |
| 178 | alternateScriptUrl: _alternateScriptUrl, | 202 | alternateScriptUrl: _alternateScriptUrl, |
| 179 | ); | 203 | ); |
-
Please register or login to post a comment