Navaron Bracke

fix pending permission request breaking the controller start sequence

... ... @@ -11,7 +11,8 @@ export 'src/enums/phone_type.dart';
export 'src/enums/torch_state.dart';
export 'src/mobile_scanner.dart';
export 'src/mobile_scanner_controller.dart';
export 'src/mobile_scanner_exception.dart';
export 'src/mobile_scanner_exception.dart'
hide PermissionRequestPendingException;
export 'src/mobile_scanner_platform_interface.dart';
export 'src/objects/address.dart';
export 'src/objects/barcode.dart';
... ...
... ... @@ -290,6 +290,8 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> {
zoomScale: 1.0,
);
}
} on PermissionRequestPendingException catch (_) {
// If a permission request was already pending, do nothing.
}
}
... ...
... ... @@ -39,3 +39,10 @@ class MobileScannerErrorDetails {
/// The error message from the [PlatformException].
final String? message;
}
/// This class represents an exception that is thrown
/// when the scanner was (re)started while a permission request was pending.
///
/// This exception type is only used internally,
/// and is not part of the public API.
class PermissionRequestPendingException implements Exception {}
... ...
... ... @@ -39,6 +39,18 @@ class MobileScannerWeb extends MobileScannerPlatform {
/// This container element is used by the barcode reader.
HTMLDivElement? _divElement;
/// This [Completer] is used to prevent additional calls to the [start] method.
///
/// To handle lifecycle changes properly,
/// the scanner is stopped when the application is inactive,
/// and restarted when the application gains focus.
///
/// However, when the camera permission is requested,
/// the application is put in the inactive state due to the permission popup gaining focus.
/// Thus, as long as the permission status is not known,
/// any calls to the [start] method are ignored.
Completer<void>? _cameraPermissionCompleter;
/// The stream controller for the media track settings stream.
final StreamController<MediaTrackSettings> _settingsController =
StreamController.broadcast();
... ... @@ -50,6 +62,11 @@ class MobileScannerWeb extends MobileScannerPlatform {
MobileScannerPlatform.instance = MobileScannerWeb();
}
bool get _hasPendingPermissionRequest {
return _cameraPermissionCompleter != null &&
!_cameraPermissionCompleter!.isCompleted;
}
@override
Stream<BarcodeCapture?> get barcodesStream => _barcodesController.stream;
... ... @@ -174,6 +191,13 @@ class MobileScannerWeb extends MobileScannerPlatform {
@override
Future<MobileScannerViewAttributes> start(StartOptions startOptions) async {
// If the permission request has not yet completed,
// the camera view is not ready yet.
// Prevent the permission popup from triggering a restart of the scanner.
if (_hasPendingPermissionRequest) {
throw PermissionRequestPendingException();
}
await _barcodeReader.maybeLoadLibrary(
alternateScriptUrl: _alternateScriptUrl,
);
... ...