Navaron Bracke

lift the video element creation out of the barcode reader; add length check for children removal

@@ -114,11 +114,11 @@ abstract class BarcodeReader { @@ -114,11 +114,11 @@ abstract class BarcodeReader {
114 /// Start the barcode reader and initialize the [videoStream]. 114 /// Start the barcode reader and initialize the [videoStream].
115 /// 115 ///
116 /// The [options] are used to configure the barcode reader. 116 /// The [options] are used to configure the barcode reader.
117 - /// The [containerElement] will become the parent of the video output element. 117 + /// The [videoElement] will become the video output element.
118 /// The [videoStream] is the input for the barcode reader and video preview element. 118 /// The [videoStream] is the input for the barcode reader and video preview element.
119 Future<void> start( 119 Future<void> start(
120 StartOptions options, { 120 StartOptions options, {
121 - required HTMLElement containerElement, 121 + required HTMLVideoElement videoElement,
122 required MediaStream videoStream, 122 required MediaStream videoStream,
123 }) { 123 }) {
124 throw UnimplementedError('start() has not been implemented.'); 124 throw UnimplementedError('start() has not been implemented.');
@@ -242,7 +242,7 @@ class MobileScannerWeb extends MobileScannerPlatform { @@ -242,7 +242,7 @@ class MobileScannerWeb extends MobileScannerPlatform {
242 242
243 await _barcodeReader.start( 243 await _barcodeReader.start(
244 startOptions, 244 startOptions,
245 - containerElement: _divElement!, 245 + videoElement: videoElement,
246 videoStream: videoStream, 246 videoStream: videoStream,
247 ); 247 );
248 } catch (error, stackTrace) { 248 } catch (error, stackTrace) {
@@ -321,7 +321,9 @@ class MobileScannerWeb extends MobileScannerPlatform { @@ -321,7 +321,9 @@ class MobileScannerWeb extends MobileScannerPlatform {
321 try { 321 try {
322 final HTMLCollection? divChildren = _divElement?.children; 322 final HTMLCollection? divChildren = _divElement?.children;
323 323
324 - if (divChildren != null) { 324 + // Since the exact element is unknown, remove all children.
  325 + // In practice, there should only be one child, the single video element.
  326 + if (divChildren != null && divChildren.length > 0) {
325 for (int i = 0; i < divChildren.length; i++) { 327 for (int i = 0; i < divChildren.length; i++) {
326 final Node? child = divChildren.item(i); 328 final Node? child = divChildren.item(i);
327 329
@@ -107,17 +107,13 @@ final class ZXingBarcodeReader extends BarcodeReader { @@ -107,17 +107,13 @@ final class ZXingBarcodeReader extends BarcodeReader {
107 107
108 /// Prepare the video element for the barcode reader. 108 /// Prepare the video element for the barcode reader.
109 /// 109 ///
110 - /// The given [videoElement] is attached to the DOM, by attaching it to the [containerElement]. 110 + /// The given [videoElement] is assumed to already be attached to the DOM at this point.
111 /// The camera video output is then attached to both the barcode reader (to detect barcodes), 111 /// The camera video output is then attached to both the barcode reader (to detect barcodes),
112 /// and the video element (to display the camera output). 112 /// and the video element (to display the camera output).
113 Future<void> _prepareVideoElement( 113 Future<void> _prepareVideoElement(
114 - web.HTMLVideoElement videoElement, {  
115 - required web.MediaStream videoStream,  
116 - required web.HTMLElement containerElement,  
117 - }) async {  
118 - // Attach the video element to the DOM, through its parent container.  
119 - containerElement.appendChild(videoElement);  
120 - 114 + web.HTMLVideoElement videoElement,
  115 + web.MediaStream videoStream,
  116 + ) async {
121 final JSPromise? result = _reader?.attachStreamToVideo.callAsFunction( 117 final JSPromise? result = _reader?.attachStreamToVideo.callAsFunction(
122 _reader as JSAny?, 118 _reader as JSAny?,
123 videoStream as JSAny, 119 videoStream as JSAny,
@@ -216,7 +212,7 @@ final class ZXingBarcodeReader extends BarcodeReader { @@ -216,7 +212,7 @@ final class ZXingBarcodeReader extends BarcodeReader {
216 @override 212 @override
217 Future<void> start( 213 Future<void> start(
218 StartOptions options, { 214 StartOptions options, {
219 - required web.HTMLElement containerElement, 215 + required web.HTMLVideoElement videoElement,
220 required web.MediaStream videoStream, 216 required web.MediaStream videoStream,
221 }) async { 217 }) async {
222 final int detectionTimeoutMs = options.detectionTimeoutMs; 218 final int detectionTimeoutMs = options.detectionTimeoutMs;
@@ -231,14 +227,7 @@ final class ZXingBarcodeReader extends BarcodeReader { @@ -231,14 +227,7 @@ final class ZXingBarcodeReader extends BarcodeReader {
231 detectionTimeoutMs.toJS, 227 detectionTimeoutMs.toJS,
232 ); 228 );
233 229
234 - final web.HTMLVideoElement videoElement =  
235 - web.document.createElement('video') as web.HTMLVideoElement;  
236 -  
237 - await _prepareVideoElement(  
238 - videoElement,  
239 - videoStream: videoStream,  
240 - containerElement: containerElement,  
241 - ); 230 + await _prepareVideoElement(videoElement, videoStream);
242 } 231 }
243 232
244 @override 233 @override