Showing
1 changed file
with
0 additions
and
285 deletions
lib/src/web/zxing.dart
deleted
100644 → 0
| 1 | -import 'dart:async'; | ||
| 2 | -import 'dart:html'; | ||
| 3 | -import 'dart:typed_data'; | ||
| 4 | -import 'dart:ui'; | ||
| 5 | - | ||
| 6 | -import 'package:js/js.dart'; | ||
| 7 | -import 'package:mobile_scanner/src/enums/barcode_format.dart'; | ||
| 8 | -import 'package:mobile_scanner/src/enums/camera_facing.dart'; | ||
| 9 | -import 'package:mobile_scanner/src/objects/barcode.dart'; | ||
| 10 | -import 'package:mobile_scanner/src/web/base.dart'; | ||
| 11 | - | ||
| 12 | -@JS('ZXing.BrowserMultiFormatReader') | ||
| 13 | -@staticInterop | ||
| 14 | -class JsZXingBrowserMultiFormatReader { | ||
| 15 | - /// https://github.com/zxing-js/library/blob/1e9ccb3b6b28d75b9eef866dba196d8937eb4449/src/browser/BrowserMultiFormatReader.ts#L11 | ||
| 16 | - external factory JsZXingBrowserMultiFormatReader( | ||
| 17 | - dynamic hints, | ||
| 18 | - int timeBetweenScansMillis, | ||
| 19 | - ); | ||
| 20 | -} | ||
| 21 | - | ||
| 22 | -@JS() | ||
| 23 | -@anonymous | ||
| 24 | -abstract class ResultPoint { | ||
| 25 | - /// The x coordinate of the point. | ||
| 26 | - external double get x; | ||
| 27 | - | ||
| 28 | - /// The y coordinate of the point. | ||
| 29 | - external double get y; | ||
| 30 | -} | ||
| 31 | - | ||
| 32 | -@JS() | ||
| 33 | -@anonymous | ||
| 34 | -abstract class Result { | ||
| 35 | - /// raw text encoded by the barcode | ||
| 36 | - external String get text; | ||
| 37 | - | ||
| 38 | - /// Returns raw bytes encoded by the barcode, if applicable, otherwise null | ||
| 39 | - external Uint8ClampedList? get rawBytes; | ||
| 40 | - | ||
| 41 | - /// Representing the format of the barcode that was decoded | ||
| 42 | - external int? format; | ||
| 43 | - | ||
| 44 | - /// Returns the result points of the barcode. These points represent the corners of the barcode. | ||
| 45 | - external List<Object?> get resultPoints; | ||
| 46 | -} | ||
| 47 | - | ||
| 48 | -extension ResultExt on Result { | ||
| 49 | - Barcode toBarcode() { | ||
| 50 | - final corners = resultPoints | ||
| 51 | - .cast<ResultPoint>() | ||
| 52 | - .map((ResultPoint rp) => Offset(rp.x, rp.y)) | ||
| 53 | - .toList(); | ||
| 54 | - | ||
| 55 | - final rawBytes = this.rawBytes; | ||
| 56 | - return Barcode( | ||
| 57 | - rawValue: text, | ||
| 58 | - rawBytes: rawBytes != null ? Uint8List.fromList(rawBytes) : null, | ||
| 59 | - format: barcodeFormat, | ||
| 60 | - corners: corners, | ||
| 61 | - ); | ||
| 62 | - } | ||
| 63 | - | ||
| 64 | - /// https://github.com/zxing-js/library/blob/1e9ccb3b6b28d75b9eef866dba196d8937eb4449/src/core/BarcodeFormat.ts#L28 | ||
| 65 | - BarcodeFormat get barcodeFormat { | ||
| 66 | - switch (format) { | ||
| 67 | - case 0: | ||
| 68 | - return BarcodeFormat.aztec; | ||
| 69 | - case 1: | ||
| 70 | - return BarcodeFormat.codebar; | ||
| 71 | - case 2: | ||
| 72 | - return BarcodeFormat.code39; | ||
| 73 | - case 3: | ||
| 74 | - return BarcodeFormat.code93; | ||
| 75 | - case 4: | ||
| 76 | - return BarcodeFormat.code128; | ||
| 77 | - case 5: | ||
| 78 | - return BarcodeFormat.dataMatrix; | ||
| 79 | - case 6: | ||
| 80 | - return BarcodeFormat.ean8; | ||
| 81 | - case 7: | ||
| 82 | - return BarcodeFormat.ean13; | ||
| 83 | - case 8: | ||
| 84 | - return BarcodeFormat.itf; | ||
| 85 | - // case 9: | ||
| 86 | - // return BarcodeFormat.maxicode; | ||
| 87 | - case 10: | ||
| 88 | - return BarcodeFormat.pdf417; | ||
| 89 | - case 11: | ||
| 90 | - return BarcodeFormat.qrCode; | ||
| 91 | - // case 12: | ||
| 92 | - // return BarcodeFormat.rss14; | ||
| 93 | - // case 13: | ||
| 94 | - // return BarcodeFormat.rssExp; | ||
| 95 | - case 14: | ||
| 96 | - return BarcodeFormat.upcA; | ||
| 97 | - case 15: | ||
| 98 | - return BarcodeFormat.upcE; | ||
| 99 | - default: | ||
| 100 | - return BarcodeFormat.unknown; | ||
| 101 | - } | ||
| 102 | - } | ||
| 103 | -} | ||
| 104 | - | ||
| 105 | -extension ZXingBarcodeFormat on BarcodeFormat { | ||
| 106 | - int get zxingBarcodeFormat { | ||
| 107 | - switch (this) { | ||
| 108 | - case BarcodeFormat.aztec: | ||
| 109 | - return 0; | ||
| 110 | - case BarcodeFormat.codabar: | ||
| 111 | - return 1; | ||
| 112 | - case BarcodeFormat.code39: | ||
| 113 | - return 2; | ||
| 114 | - case BarcodeFormat.code93: | ||
| 115 | - return 3; | ||
| 116 | - case BarcodeFormat.code128: | ||
| 117 | - return 4; | ||
| 118 | - case BarcodeFormat.dataMatrix: | ||
| 119 | - return 5; | ||
| 120 | - case BarcodeFormat.ean8: | ||
| 121 | - return 6; | ||
| 122 | - case BarcodeFormat.ean13: | ||
| 123 | - return 7; | ||
| 124 | - case BarcodeFormat.itf: | ||
| 125 | - return 8; | ||
| 126 | - case BarcodeFormat.pdf417: | ||
| 127 | - return 10; | ||
| 128 | - case BarcodeFormat.qrCode: | ||
| 129 | - return 11; | ||
| 130 | - case BarcodeFormat.upcA: | ||
| 131 | - return 14; | ||
| 132 | - case BarcodeFormat.upcE: | ||
| 133 | - return 15; | ||
| 134 | - case BarcodeFormat.unknown: | ||
| 135 | - case BarcodeFormat.all: | ||
| 136 | - default: | ||
| 137 | - return -1; | ||
| 138 | - } | ||
| 139 | - } | ||
| 140 | -} | ||
| 141 | - | ||
| 142 | -typedef BarcodeDetectionCallback = void Function( | ||
| 143 | - Result? result, | ||
| 144 | - dynamic error, | ||
| 145 | -); | ||
| 146 | - | ||
| 147 | -extension JsZXingBrowserMultiFormatReaderExt | ||
| 148 | - on JsZXingBrowserMultiFormatReader { | ||
| 149 | - external Promise<void> decodeFromVideoElementContinuously( | ||
| 150 | - VideoElement source, | ||
| 151 | - BarcodeDetectionCallback callbackFn, | ||
| 152 | - ); | ||
| 153 | - | ||
| 154 | - /// Continuously decodes from video input | ||
| 155 | - external void decodeContinuously( | ||
| 156 | - VideoElement element, | ||
| 157 | - BarcodeDetectionCallback callbackFn, | ||
| 158 | - ); | ||
| 159 | - | ||
| 160 | - external Promise<void> decodeFromStream( | ||
| 161 | - MediaStream stream, | ||
| 162 | - VideoElement videoSource, | ||
| 163 | - BarcodeDetectionCallback callbackFn, | ||
| 164 | - ); | ||
| 165 | - | ||
| 166 | - external Promise<void> decodeFromConstraints( | ||
| 167 | - dynamic constraints, | ||
| 168 | - VideoElement videoSource, | ||
| 169 | - BarcodeDetectionCallback callbackFn, | ||
| 170 | - ); | ||
| 171 | - | ||
| 172 | - external void stopContinuousDecode(); | ||
| 173 | - | ||
| 174 | - external VideoElement prepareVideoElement(VideoElement videoSource); | ||
| 175 | - | ||
| 176 | - /// Defines what the [videoElement] src will be. | ||
| 177 | - external void addVideoSource( | ||
| 178 | - VideoElement videoElement, | ||
| 179 | - MediaStream stream, | ||
| 180 | - ); | ||
| 181 | - | ||
| 182 | - external bool isVideoPlaying(VideoElement video); | ||
| 183 | - | ||
| 184 | - external void reset(); | ||
| 185 | - | ||
| 186 | - /// The HTML video element, used to display the camera stream. | ||
| 187 | - external VideoElement? videoElement; | ||
| 188 | - | ||
| 189 | - /// The stream output from camera. | ||
| 190 | - external MediaStream? stream; | ||
| 191 | -} | ||
| 192 | - | ||
| 193 | -/// Barcode reader that uses zxing-js library. | ||
| 194 | -class ZXingBarcodeReader extends WebBarcodeReaderBase | ||
| 195 | - with InternalStreamCreation, InternalTorchDetection { | ||
| 196 | - JsZXingBrowserMultiFormatReader? _reader; | ||
| 197 | - | ||
| 198 | - ZXingBarcodeReader({required super.videoContainer}); | ||
| 199 | - | ||
| 200 | - @override | ||
| 201 | - bool get isStarted => localMediaStream != null; | ||
| 202 | - | ||
| 203 | - @override | ||
| 204 | - Future<void> start({ | ||
| 205 | - required CameraFacing cameraFacing, | ||
| 206 | - List<BarcodeFormat>? formats, | ||
| 207 | - Duration? detectionTimeout, | ||
| 208 | - }) async { | ||
| 209 | - final JsMap? hints; | ||
| 210 | - if (formats != null && !formats.contains(BarcodeFormat.all)) { | ||
| 211 | - hints = JsMap(); | ||
| 212 | - final zxingFormats = | ||
| 213 | - formats.map((e) => e.zxingBarcodeFormat).where((e) => e > 0).toList(); | ||
| 214 | - // set hint DecodeHintType.POSSIBLE_FORMATS | ||
| 215 | - // https://github.com/zxing-js/library/blob/1e9ccb3b6b28d75b9eef866dba196d8937eb4449/src/core/DecodeHintType.ts#L28 | ||
| 216 | - hints.set(2, zxingFormats); | ||
| 217 | - } else { | ||
| 218 | - hints = null; | ||
| 219 | - } | ||
| 220 | - if (detectionTimeout != null) { | ||
| 221 | - frameInterval = detectionTimeout; | ||
| 222 | - } | ||
| 223 | - _reader = JsZXingBrowserMultiFormatReader( | ||
| 224 | - hints, | ||
| 225 | - frameInterval.inMilliseconds, | ||
| 226 | - ); | ||
| 227 | - videoContainer.children = [video]; | ||
| 228 | - | ||
| 229 | - final stream = await initMediaStream(cameraFacing); | ||
| 230 | - | ||
| 231 | - prepareVideoElement(video); | ||
| 232 | - if (stream != null) { | ||
| 233 | - await attachStreamToVideo(stream, video); | ||
| 234 | - } | ||
| 235 | - } | ||
| 236 | - | ||
| 237 | - @override | ||
| 238 | - void prepareVideoElement(VideoElement videoSource) { | ||
| 239 | - _reader?.prepareVideoElement(videoSource); | ||
| 240 | - } | ||
| 241 | - | ||
| 242 | - @override | ||
| 243 | - Future<void> attachStreamToVideo( | ||
| 244 | - MediaStream stream, | ||
| 245 | - VideoElement videoSource, | ||
| 246 | - ) async { | ||
| 247 | - _reader?.addVideoSource(videoSource, stream); | ||
| 248 | - _reader?.videoElement = videoSource; | ||
| 249 | - _reader?.stream = stream; | ||
| 250 | - localMediaStream = stream; | ||
| 251 | - await videoSource.play(); | ||
| 252 | - } | ||
| 253 | - | ||
| 254 | - StreamController<Barcode?>? controller; | ||
| 255 | - | ||
| 256 | - @override | ||
| 257 | - Future<void> stopDetectBarcodeContinuously() async { | ||
| 258 | - _reader?.stopContinuousDecode(); | ||
| 259 | - controller?.close(); | ||
| 260 | - controller = null; | ||
| 261 | - } | ||
| 262 | - | ||
| 263 | - @override | ||
| 264 | - Stream<Barcode?> detectBarcodeContinuously() { | ||
| 265 | - controller ??= StreamController<Barcode?>(); | ||
| 266 | - controller!.onListen = () async { | ||
| 267 | - _reader?.decodeContinuously( | ||
| 268 | - video, | ||
| 269 | - allowInterop((result, error) { | ||
| 270 | - if (result != null) { | ||
| 271 | - controller?.add(result.toBarcode()); | ||
| 272 | - } | ||
| 273 | - }), | ||
| 274 | - ); | ||
| 275 | - }; | ||
| 276 | - controller!.onCancel = () => stopDetectBarcodeContinuously(); | ||
| 277 | - return controller!.stream; | ||
| 278 | - } | ||
| 279 | - | ||
| 280 | - @override | ||
| 281 | - Future<void> stop() async { | ||
| 282 | - _reader?.reset(); | ||
| 283 | - super.stop(); | ||
| 284 | - } | ||
| 285 | -} |
-
Please register or login to post a comment