Showing
4 changed files
with
34 additions
and
14 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'; |
| @@ -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( |
-
Please register or login to post a comment