Navaron Bracke

put back web only workaround for now

@@ -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';
@@ -242,6 +242,13 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> { @@ -242,6 +242,13 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> {
242 ); 242 );
243 } 243 }
244 244
  245 + // Permission was denied, do nothing.
  246 + // When the controller is stopped,
  247 + // the error is reset so the permission can be requested again if possible.
  248 + if (value.error?.errorCode == MobileScannerErrorCode.permissionDenied) {
  249 + return;
  250 + }
  251 +
245 // Do nothing if the camera is already running. 252 // Do nothing if the camera is already running.
246 if (value.isRunning) { 253 if (value.isRunning) {
247 return; 254 return;
@@ -280,9 +287,6 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> { @@ -280,9 +287,6 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> {
280 ); 287 );
281 } 288 }
282 } on MobileScannerException catch (error) { 289 } on MobileScannerException catch (error) {
283 - // TODO: if the error code is `controllerAlreadyInitialized` ignore the error  
284 - // TODO: update the error reporting from the native side to report proper error codes.  
285 -  
286 // The initialization finished with an error. 290 // The initialization finished with an error.
287 // To avoid stale values, reset the output size, 291 // To avoid stale values, reset the output size,
288 // torch state and zoom scale to the defaults. 292 // torch state and zoom scale to the defaults.
@@ -297,6 +301,8 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> { @@ -297,6 +301,8 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> {
297 zoomScale: 1.0, 301 zoomScale: 1.0,
298 ); 302 );
299 } 303 }
  304 + } on PermissionRequestPendingException catch (_) {
  305 + // If a permission request was already pending, do nothing.
300 } 306 }
301 } 307 }
302 308
@@ -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 {}
@@ -38,6 +38,12 @@ class MobileScannerWeb extends MobileScannerPlatform { @@ -38,6 +38,12 @@ class MobileScannerWeb extends MobileScannerPlatform {
38 /// The container div element for the camera view. 38 /// The container div element for the camera view.
39 late HTMLDivElement _divElement; 39 late HTMLDivElement _divElement;
40 40
  41 + /// The flag that keeps track of whether a permission request is in progress.
  42 + ///
  43 + /// On the web, a permission request triggers a dialog, that in turn triggers a lifecycle change.
  44 + /// While the permission request is in progress, any attempts at (re)starting the camera should be ignored.
  45 + bool _permissionRequestInProgress = false;
  46 +
41 /// The stream controller for the media track settings stream. 47 /// The stream controller for the media track settings stream.
42 /// 48 ///
43 /// Currently, only the facing mode setting can be supported, 49 /// Currently, only the facing mode setting can be supported,
@@ -180,12 +186,17 @@ class MobileScannerWeb extends MobileScannerPlatform { @@ -180,12 +186,17 @@ class MobileScannerWeb extends MobileScannerPlatform {
180 } 186 }
181 187
182 try { 188 try {
  189 + _permissionRequestInProgress = true;
  190 +
183 // Retrieving the media devices requests the camera permission. 191 // Retrieving the media devices requests the camera permission.
184 final MediaStream videoStream = 192 final MediaStream videoStream =
185 await window.navigator.mediaDevices.getUserMedia(constraints).toDart; 193 await window.navigator.mediaDevices.getUserMedia(constraints).toDart;
186 194
  195 + _permissionRequestInProgress = false;
  196 +
187 return videoStream; 197 return videoStream;
188 } on DOMException catch (error, stackTrace) { 198 } on DOMException catch (error, stackTrace) {
  199 + _permissionRequestInProgress = false;
189 final String errorMessage = error.toString(); 200 final String errorMessage = error.toString();
190 201
191 MobileScannerErrorCode errorCode = MobileScannerErrorCode.genericError; 202 MobileScannerErrorCode errorCode = MobileScannerErrorCode.genericError;
@@ -245,15 +256,11 @@ class MobileScannerWeb extends MobileScannerPlatform { @@ -245,15 +256,11 @@ class MobileScannerWeb extends MobileScannerPlatform {
245 256
246 @override 257 @override
247 Future<MobileScannerViewAttributes> start(StartOptions startOptions) async { 258 Future<MobileScannerViewAttributes> start(StartOptions startOptions) async {
248 - // TODO: ignore double starts in the controller.  
249 - if (_barcodeReader != null) {  
250 - throw const MobileScannerException(  
251 - errorCode: MobileScannerErrorCode.controllerAlreadyInitialized,  
252 - errorDetails: MobileScannerErrorDetails(  
253 - message:  
254 - 'The scanner was already started. Call stop() before calling start() again.',  
255 - ),  
256 - ); 259 + // If the permission request has not yet completed,
  260 + // the camera view is not ready yet.
  261 + // Prevent the permission popup from triggering a restart of the scanner.
  262 + if (_permissionRequestInProgress) {
  263 + throw PermissionRequestPendingException();
257 } 264 }
258 265
259 _barcodeReader = ZXingBarcodeReader(); 266 _barcodeReader = ZXingBarcodeReader();
@@ -263,7 +270,6 @@ class MobileScannerWeb extends MobileScannerPlatform { @@ -263,7 +270,6 @@ class MobileScannerWeb extends MobileScannerPlatform {
263 ); 270 );
264 271
265 if (_barcodeReader?.isScanning ?? false) { 272 if (_barcodeReader?.isScanning ?? false) {
266 - // TODO: ignore double starts in the controller.  
267 throw const MobileScannerException( 273 throw const MobileScannerException(
268 errorCode: MobileScannerErrorCode.controllerAlreadyInitialized, 274 errorCode: MobileScannerErrorCode.controllerAlreadyInitialized,
269 errorDetails: MobileScannerErrorDetails( 275 errorDetails: MobileScannerErrorDetails(