Navaron Bracke

use a regular flag on the web for pending permission request

@@ -39,17 +39,11 @@ class MobileScannerWeb extends MobileScannerPlatform { @@ -39,17 +39,11 @@ 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. 42 + /// The flag that keeps track of whether a permission request is in progress.
43 /// 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; 44 + /// On the web, a permission request triggers a dialog, that in turn triggers a lifecycle change.
  45 + /// While the permission request is in progress, any attempts at (re)starting the camera should be ignored.
  46 + bool _permissionRequestInProgress = false;
53 47
54 /// The stream controller for the media track settings stream. 48 /// The stream controller for the media track settings stream.
55 /// 49 ///
@@ -67,11 +61,6 @@ class MobileScannerWeb extends MobileScannerPlatform { @@ -67,11 +61,6 @@ class MobileScannerWeb extends MobileScannerPlatform {
67 MobileScannerPlatform.instance = MobileScannerWeb(); 61 MobileScannerPlatform.instance = MobileScannerWeb();
68 } 62 }
69 63
70 - bool get _hasPendingPermissionRequest {  
71 - return _cameraPermissionCompleter != null &&  
72 - !_cameraPermissionCompleter!.isCompleted;  
73 - }  
74 -  
75 @override 64 @override
76 Stream<BarcodeCapture?> get barcodesStream => _barcodesController.stream; 65 Stream<BarcodeCapture?> get barcodesStream => _barcodesController.stream;
77 66
@@ -129,18 +118,15 @@ class MobileScannerWeb extends MobileScannerPlatform { @@ -129,18 +118,15 @@ class MobileScannerWeb extends MobileScannerPlatform {
129 } 118 }
130 119
131 try { 120 try {
132 - // Retrieving the video track requests the camera permission.  
133 - // If the completer is not null, the permission was never requested before.  
134 - _cameraPermissionCompleter ??= Completer<void>(); 121 + // Retrieving the media devices requests the camera permission.
  122 + _permissionRequestInProgress = true;
135 123
136 final MediaStream? videoStream = await window.navigator.mediaDevices 124 final MediaStream? videoStream = await window.navigator.mediaDevices
137 .getUserMedia(constraints) 125 .getUserMedia(constraints)
138 .toDart as MediaStream?; 126 .toDart as MediaStream?;
139 127
140 // At this point the permission is granted. 128 // At this point the permission is granted.
141 - if (!_cameraPermissionCompleter!.isCompleted) {  
142 - _cameraPermissionCompleter!.complete();  
143 - } 129 + _permissionRequestInProgress = false;
144 130
145 if (videoStream == null) { 131 if (videoStream == null) {
146 throw const MobileScannerException( 132 throw const MobileScannerException(
@@ -155,12 +141,6 @@ class MobileScannerWeb extends MobileScannerPlatform { @@ -155,12 +141,6 @@ class MobileScannerWeb extends MobileScannerPlatform {
155 141
156 return videoStream; 142 return videoStream;
157 } on DOMException catch (error, stackTrace) { 143 } on DOMException catch (error, stackTrace) {
158 - // At this point the permission request completed, although with an error,  
159 - // but the error is irrelevant for the completer.  
160 - if (!_cameraPermissionCompleter!.isCompleted) {  
161 - _cameraPermissionCompleter!.complete();  
162 - }  
163 -  
164 final String errorMessage = error.toString(); 144 final String errorMessage = error.toString();
165 145
166 MobileScannerErrorCode errorCode = MobileScannerErrorCode.genericError; 146 MobileScannerErrorCode errorCode = MobileScannerErrorCode.genericError;
@@ -173,6 +153,10 @@ class MobileScannerWeb extends MobileScannerPlatform { @@ -173,6 +153,10 @@ class MobileScannerWeb extends MobileScannerPlatform {
173 errorCode = MobileScannerErrorCode.permissionDenied; 153 errorCode = MobileScannerErrorCode.permissionDenied;
174 } 154 }
175 155
  156 + // At this point the permission request completed, although with an error,
  157 + // but the error is irrelevant.
  158 + _permissionRequestInProgress = false;
  159 +
176 throw MobileScannerException( 160 throw MobileScannerException(
177 errorCode: errorCode, 161 errorCode: errorCode,
178 errorDetails: MobileScannerErrorDetails( 162 errorDetails: MobileScannerErrorDetails(
@@ -231,7 +215,7 @@ class MobileScannerWeb extends MobileScannerPlatform { @@ -231,7 +215,7 @@ class MobileScannerWeb extends MobileScannerPlatform {
231 // If the permission request has not yet completed, 215 // If the permission request has not yet completed,
232 // the camera view is not ready yet. 216 // the camera view is not ready yet.
233 // Prevent the permission popup from triggering a restart of the scanner. 217 // Prevent the permission popup from triggering a restart of the scanner.
234 - if (_hasPendingPermissionRequest) { 218 + if (_permissionRequestInProgress) {
235 throw PermissionRequestPendingException(); 219 throw PermissionRequestPendingException();
236 } 220 }
237 221