Committed by
GitHub
Merge branch 'master' into dependabot/gradle/android/androidx.camera-camera-camera2-1.2.1
Showing
19 changed files
with
175 additions
and
61 deletions
| @@ -11,7 +11,7 @@ jobs: | @@ -11,7 +11,7 @@ jobs: | ||
| 11 | analysis: | 11 | analysis: |
| 12 | runs-on: ubuntu-latest | 12 | runs-on: ubuntu-latest |
| 13 | steps: | 13 | steps: |
| 14 | - - uses: actions/checkout@v3.2.0 | 14 | + - uses: actions/checkout@v3.3.0 |
| 15 | - uses: actions/setup-java@v3.9.0 | 15 | - uses: actions/setup-java@v3.9.0 |
| 16 | with: | 16 | with: |
| 17 | java-version: 11 | 17 | java-version: 11 |
| @@ -28,7 +28,7 @@ jobs: | @@ -28,7 +28,7 @@ jobs: | ||
| 28 | formatting: | 28 | formatting: |
| 29 | runs-on: ubuntu-latest | 29 | runs-on: ubuntu-latest |
| 30 | steps: | 30 | steps: |
| 31 | - - uses: actions/checkout@v3.2.0 | 31 | + - uses: actions/checkout@v3.3.0 |
| 32 | - uses: actions/setup-java@v3.9.0 | 32 | - uses: actions/setup-java@v3.9.0 |
| 33 | with: | 33 | with: |
| 34 | java-version: 11 | 34 | java-version: 11 |
| @@ -7,7 +7,7 @@ | @@ -7,7 +7,7 @@ | ||
| 7 | release-please: | 7 | release-please: |
| 8 | runs-on: ubuntu-latest | 8 | runs-on: ubuntu-latest |
| 9 | steps: | 9 | steps: |
| 10 | - - uses: GoogleCloudPlatform/release-please-action@v3.7.1 | 10 | + - uses: GoogleCloudPlatform/release-please-action@v3.7.3 |
| 11 | with: | 11 | with: |
| 12 | token: ${{ secrets.GITHUB_TOKEN }} | 12 | token: ${{ secrets.GITHUB_TOKEN }} |
| 13 | release-type: simple | 13 | release-type: simple |
| 1 | +## Next | ||
| 2 | + | ||
| 3 | +Improvements: | ||
| 4 | +* [Web] Automatically inject js libraries | ||
| 5 | + | ||
| 1 | ## 3.0.0-beta.4 | 6 | ## 3.0.0-beta.4 |
| 2 | Fixes: | 7 | Fixes: |
| 3 | * Fixes a permission bug on Android where denying the permission would cause an infinite loop of permission requests. | 8 | * Fixes a permission bug on Android where denying the permission would cause an infinite loop of permission requests. |
| @@ -53,13 +53,6 @@ Ensure that you granted camera permission in XCode -> Signing & Capabilities: | @@ -53,13 +53,6 @@ Ensure that you granted camera permission in XCode -> Signing & Capabilities: | ||
| 53 | 53 | ||
| 54 | <img width="696" alt="Screenshot of XCode where Camera is checked" src="https://user-images.githubusercontent.com/24459435/193464115-d76f81d0-6355-4cb2-8bee-538e413a3ad0.png"> | 54 | <img width="696" alt="Screenshot of XCode where Camera is checked" src="https://user-images.githubusercontent.com/24459435/193464115-d76f81d0-6355-4cb2-8bee-538e413a3ad0.png"> |
| 55 | 55 | ||
| 56 | -### Web | ||
| 57 | -Add this to `web/index.html`: | ||
| 58 | - | ||
| 59 | -```html | ||
| 60 | -<script type="text/javascript" src="https://unpkg.com/@zxing/library@0.19.1"></script> | ||
| 61 | -``` | ||
| 62 | - | ||
| 63 | ## Usage | 56 | ## Usage |
| 64 | 57 | ||
| 65 | Import `package:mobile_scanner/mobile_scanner.dart`, and use the widget with or without the controller. | 58 | Import `package:mobile_scanner/mobile_scanner.dart`, and use the widget with or without the controller. |
| @@ -9,7 +9,7 @@ buildscript { | @@ -9,7 +9,7 @@ buildscript { | ||
| 9 | } | 9 | } |
| 10 | 10 | ||
| 11 | dependencies { | 11 | dependencies { |
| 12 | - classpath 'com.android.tools.build:gradle:7.3.1' | 12 | + classpath 'com.android.tools.build:gradle:7.4.0' |
| 13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" | 13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" |
| 14 | } | 14 | } |
| 15 | } | 15 | } |
| @@ -54,5 +54,5 @@ dependencies { | @@ -54,5 +54,5 @@ dependencies { | ||
| 54 | // implementation 'com.google.android.gms:play-services-mlkit-barcode-scanning:18.1.0' | 54 | // implementation 'com.google.android.gms:play-services-mlkit-barcode-scanning:18.1.0' |
| 55 | 55 | ||
| 56 | implementation 'androidx.camera:camera-camera2:1.2.1' | 56 | implementation 'androidx.camera:camera-camera2:1.2.1' |
| 57 | - implementation 'androidx.camera:camera-lifecycle:1.2.0' | 57 | + implementation 'androidx.camera:camera-lifecycle:1.2.1' |
| 58 | } | 58 | } |
| @@ -6,7 +6,7 @@ buildscript { | @@ -6,7 +6,7 @@ buildscript { | ||
| 6 | } | 6 | } |
| 7 | 7 | ||
| 8 | dependencies { | 8 | dependencies { |
| 9 | - classpath 'com.android.tools.build:gradle:7.3.1' | 9 | + classpath 'com.android.tools.build:gradle:7.4.0' |
| 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" | 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" |
| 11 | } | 11 | } |
| 12 | } | 12 | } |
| @@ -28,19 +28,23 @@ class _BarcodeListScannerWithControllerState | @@ -28,19 +28,23 @@ class _BarcodeListScannerWithControllerState | ||
| 28 | bool isStarted = true; | 28 | bool isStarted = true; |
| 29 | 29 | ||
| 30 | void _startOrStop() { | 30 | void _startOrStop() { |
| 31 | - if (isStarted) { | ||
| 32 | - controller.stop(); | ||
| 33 | - } else { | ||
| 34 | - controller.start().catchError((error) { | ||
| 35 | - if (mounted) { | ||
| 36 | - setState(() {}); | ||
| 37 | - } | 31 | + try { |
| 32 | + if (isStarted) { | ||
| 33 | + controller.stop(); | ||
| 34 | + } else { | ||
| 35 | + controller.start(); | ||
| 36 | + } | ||
| 37 | + setState(() { | ||
| 38 | + isStarted = !isStarted; | ||
| 38 | }); | 39 | }); |
| 40 | + } on Exception catch (e) { | ||
| 41 | + ScaffoldMessenger.of(context).showSnackBar( | ||
| 42 | + SnackBar( | ||
| 43 | + content: Text('Something went wrong! $e'), | ||
| 44 | + backgroundColor: Colors.red, | ||
| 45 | + ), | ||
| 46 | + ); | ||
| 39 | } | 47 | } |
| 40 | - | ||
| 41 | - setState(() { | ||
| 42 | - isStarted = !isStarted; | ||
| 43 | - }); | ||
| 44 | } | 48 | } |
| 45 | 49 | ||
| 46 | @override | 50 | @override |
| @@ -121,7 +125,7 @@ class _BarcodeListScannerWithControllerState | @@ -121,7 +125,7 @@ class _BarcodeListScannerWithControllerState | ||
| 121 | overflow: TextOverflow.fade, | 125 | overflow: TextOverflow.fade, |
| 122 | style: Theme.of(context) | 126 | style: Theme.of(context) |
| 123 | .textTheme | 127 | .textTheme |
| 124 | - .headline4! | 128 | + .headlineMedium! |
| 125 | .copyWith(color: Colors.white), | 129 | .copyWith(color: Colors.white), |
| 126 | ), | 130 | ), |
| 127 | ), | 131 | ), |
| @@ -28,19 +28,23 @@ class _BarcodeScannerWithControllerState | @@ -28,19 +28,23 @@ class _BarcodeScannerWithControllerState | ||
| 28 | bool isStarted = true; | 28 | bool isStarted = true; |
| 29 | 29 | ||
| 30 | void _startOrStop() { | 30 | void _startOrStop() { |
| 31 | - if (isStarted) { | ||
| 32 | - controller.stop(); | ||
| 33 | - } else { | ||
| 34 | - controller.start().catchError((error) { | ||
| 35 | - if (mounted) { | ||
| 36 | - setState(() {}); | ||
| 37 | - } | 31 | + try { |
| 32 | + if (isStarted) { | ||
| 33 | + controller.stop(); | ||
| 34 | + } else { | ||
| 35 | + controller.start(); | ||
| 36 | + } | ||
| 37 | + setState(() { | ||
| 38 | + isStarted = !isStarted; | ||
| 38 | }); | 39 | }); |
| 40 | + } on Exception catch (e) { | ||
| 41 | + ScaffoldMessenger.of(context).showSnackBar( | ||
| 42 | + SnackBar( | ||
| 43 | + content: Text('Something went wrong! $e'), | ||
| 44 | + backgroundColor: Colors.red, | ||
| 45 | + ), | ||
| 46 | + ); | ||
| 39 | } | 47 | } |
| 40 | - | ||
| 41 | - setState(() { | ||
| 42 | - isStarted = !isStarted; | ||
| 43 | - }); | ||
| 44 | } | 48 | } |
| 45 | 49 | ||
| 46 | @override | 50 | @override |
| @@ -127,7 +131,7 @@ class _BarcodeScannerWithControllerState | @@ -127,7 +131,7 @@ class _BarcodeScannerWithControllerState | ||
| 127 | overflow: TextOverflow.fade, | 131 | overflow: TextOverflow.fade, |
| 128 | style: Theme.of(context) | 132 | style: Theme.of(context) |
| 129 | .textTheme | 133 | .textTheme |
| 130 | - .headline4! | 134 | + .headlineMedium! |
| 131 | .copyWith(color: Colors.white), | 135 | .copyWith(color: Colors.white), |
| 132 | ), | 136 | ), |
| 133 | ), | 137 | ), |
| @@ -30,19 +30,23 @@ class _BarcodeScannerReturningImageState | @@ -30,19 +30,23 @@ class _BarcodeScannerReturningImageState | ||
| 30 | bool isStarted = true; | 30 | bool isStarted = true; |
| 31 | 31 | ||
| 32 | void _startOrStop() { | 32 | void _startOrStop() { |
| 33 | - if (isStarted) { | ||
| 34 | - controller.stop(); | ||
| 35 | - } else { | ||
| 36 | - controller.start().catchError((error) { | ||
| 37 | - if (mounted) { | ||
| 38 | - setState(() {}); | ||
| 39 | - } | 33 | + try { |
| 34 | + if (isStarted) { | ||
| 35 | + controller.stop(); | ||
| 36 | + } else { | ||
| 37 | + controller.start(); | ||
| 38 | + } | ||
| 39 | + setState(() { | ||
| 40 | + isStarted = !isStarted; | ||
| 40 | }); | 41 | }); |
| 42 | + } on Exception catch (e) { | ||
| 43 | + ScaffoldMessenger.of(context).showSnackBar( | ||
| 44 | + SnackBar( | ||
| 45 | + content: Text('Something went wrong! $e'), | ||
| 46 | + backgroundColor: Colors.red, | ||
| 47 | + ), | ||
| 48 | + ); | ||
| 41 | } | 49 | } |
| 42 | - | ||
| 43 | - setState(() { | ||
| 44 | - isStarted = !isStarted; | ||
| 45 | - }); | ||
| 46 | } | 50 | } |
| 47 | 51 | ||
| 48 | @override | 52 | @override |
| @@ -141,7 +145,7 @@ class _BarcodeScannerReturningImageState | @@ -141,7 +145,7 @@ class _BarcodeScannerReturningImageState | ||
| 141 | overflow: TextOverflow.fade, | 145 | overflow: TextOverflow.fade, |
| 142 | style: Theme.of(context) | 146 | style: Theme.of(context) |
| 143 | .textTheme | 147 | .textTheme |
| 144 | - .headline4! | 148 | + .headlineMedium! |
| 145 | .copyWith(color: Colors.white), | 149 | .copyWith(color: Colors.white), |
| 146 | ), | 150 | ), |
| 147 | ), | 151 | ), |
| @@ -82,7 +82,7 @@ class _BarcodeScannerWithScanWindowState | @@ -82,7 +82,7 @@ class _BarcodeScannerWithScanWindowState | ||
| 82 | overflow: TextOverflow.fade, | 82 | overflow: TextOverflow.fade, |
| 83 | style: Theme.of(context) | 83 | style: Theme.of(context) |
| 84 | .textTheme | 84 | .textTheme |
| 85 | - .headline4! | 85 | + .headlineMedium! |
| 86 | .copyWith(color: Colors.white), | 86 | .copyWith(color: Colors.white), |
| 87 | ), | 87 | ), |
| 88 | ), | 88 | ), |
| @@ -54,7 +54,7 @@ class _BarcodeScannerWithoutControllerState | @@ -54,7 +54,7 @@ class _BarcodeScannerWithoutControllerState | ||
| 54 | overflow: TextOverflow.fade, | 54 | overflow: TextOverflow.fade, |
| 55 | style: Theme.of(context) | 55 | style: Theme.of(context) |
| 56 | .textTheme | 56 | .textTheme |
| 57 | - .headline4! | 57 | + .headlineMedium! |
| 58 | .copyWith(color: Colors.white), | 58 | .copyWith(color: Colors.white), |
| 59 | ), | 59 | ), |
| 60 | ), | 60 | ), |
| @@ -109,7 +109,7 @@ class _BarcodeScannerWithZoomState extends State<BarcodeScannerWithZoom> | @@ -109,7 +109,7 @@ class _BarcodeScannerWithZoomState extends State<BarcodeScannerWithZoom> | ||
| 109 | overflow: TextOverflow.fade, | 109 | overflow: TextOverflow.fade, |
| 110 | style: Theme.of(context) | 110 | style: Theme.of(context) |
| 111 | .textTheme | 111 | .textTheme |
| 112 | - .headline4! | 112 | + .headlineMedium! |
| 113 | .copyWith(color: Colors.white), | 113 | .copyWith(color: Colors.white), |
| 114 | ), | 114 | ), |
| 115 | ), | 115 | ), |
| @@ -28,8 +28,6 @@ | @@ -28,8 +28,6 @@ | ||
| 28 | 28 | ||
| 29 | <title>example</title> | 29 | <title>example</title> |
| 30 | <link rel="manifest" href="manifest.json"> | 30 | <link rel="manifest" href="manifest.json"> |
| 31 | - <script src="https://cdn.jsdelivr.net/npm/jsqr@1.4.0/dist/jsQR.min.js"></script> | ||
| 32 | - <script type="text/javascript" src="https://unpkg.com/@zxing/library@0.19.1"></script> | ||
| 33 | </head> | 31 | </head> |
| 34 | <body> | 32 | <body> |
| 35 | <!-- This script installs service_worker.js to provide PWA functionality to | 33 | <!-- This script installs service_worker.js to provide PWA functionality to |
| @@ -8,6 +8,7 @@ import 'package:mobile_scanner/mobile_scanner_web.dart'; | @@ -8,6 +8,7 @@ import 'package:mobile_scanner/mobile_scanner_web.dart'; | ||
| 8 | import 'package:mobile_scanner/src/barcode_utility.dart'; | 8 | import 'package:mobile_scanner/src/barcode_utility.dart'; |
| 9 | import 'package:mobile_scanner/src/enums/camera_facing.dart'; | 9 | import 'package:mobile_scanner/src/enums/camera_facing.dart'; |
| 10 | import 'package:mobile_scanner/src/objects/barcode.dart'; | 10 | import 'package:mobile_scanner/src/objects/barcode.dart'; |
| 11 | +import 'package:mobile_scanner/src/web/utils.dart'; | ||
| 11 | 12 | ||
| 12 | /// This plugin is the web implementation of mobile_scanner. | 13 | /// This plugin is the web implementation of mobile_scanner. |
| 13 | /// It only supports QR codes. | 14 | /// It only supports QR codes. |
| @@ -25,6 +26,8 @@ class MobileScannerWebPlugin { | @@ -25,6 +26,8 @@ class MobileScannerWebPlugin { | ||
| 25 | ); | 26 | ); |
| 26 | final MobileScannerWebPlugin instance = MobileScannerWebPlugin(); | 27 | final MobileScannerWebPlugin instance = MobileScannerWebPlugin(); |
| 27 | 28 | ||
| 29 | + injectJSLibraries(barCodeReader.jsLibraries); | ||
| 30 | + | ||
| 28 | channel.setMethodCallHandler(instance.handleMethodCall); | 31 | channel.setMethodCallHandler(instance.handleMethodCall); |
| 29 | event.setController(instance.controller); | 32 | event.setController(instance.controller); |
| 30 | } | 33 | } |
| @@ -7,6 +7,24 @@ import 'package:mobile_scanner/src/enums/camera_facing.dart'; | @@ -7,6 +7,24 @@ import 'package:mobile_scanner/src/enums/camera_facing.dart'; | ||
| 7 | import 'package:mobile_scanner/src/objects/barcode.dart'; | 7 | import 'package:mobile_scanner/src/objects/barcode.dart'; |
| 8 | import 'package:mobile_scanner/src/web/media.dart'; | 8 | import 'package:mobile_scanner/src/web/media.dart'; |
| 9 | 9 | ||
| 10 | +class JsLibrary { | ||
| 11 | + /// The name of global variable where library is stored. | ||
| 12 | + /// Used to properly import the library if [usesRequireJs] flag is true | ||
| 13 | + final String contextName; | ||
| 14 | + final String url; | ||
| 15 | + | ||
| 16 | + /// If js code checks for 'define' variable. | ||
| 17 | + /// E.g. if at the beginning you see code like | ||
| 18 | + /// if (typeof define === "function" && define.amd) | ||
| 19 | + final bool usesRequireJs; | ||
| 20 | + | ||
| 21 | + const JsLibrary({ | ||
| 22 | + required this.contextName, | ||
| 23 | + required this.url, | ||
| 24 | + required this.usesRequireJs, | ||
| 25 | + }); | ||
| 26 | +} | ||
| 27 | + | ||
| 10 | abstract class WebBarcodeReaderBase { | 28 | abstract class WebBarcodeReaderBase { |
| 11 | /// Timer used to capture frames to be analyzed | 29 | /// Timer used to capture frames to be analyzed |
| 12 | Duration frameInterval = const Duration(milliseconds: 200); | 30 | Duration frameInterval = const Duration(milliseconds: 200); |
| @@ -21,6 +39,9 @@ abstract class WebBarcodeReaderBase { | @@ -21,6 +39,9 @@ abstract class WebBarcodeReaderBase { | ||
| 21 | int get videoWidth; | 39 | int get videoWidth; |
| 22 | int get videoHeight; | 40 | int get videoHeight; |
| 23 | 41 | ||
| 42 | + /// JS libraries to be injected into html page. | ||
| 43 | + List<JsLibrary> get jsLibraries; | ||
| 44 | + | ||
| 24 | /// Starts streaming video | 45 | /// Starts streaming video |
| 25 | Future<void> start({ | 46 | Future<void> start({ |
| 26 | required CameraFacing cameraFacing, | 47 | required CameraFacing cameraFacing, |
| @@ -20,11 +20,14 @@ class Code { | @@ -20,11 +20,14 @@ class Code { | ||
| 20 | external Uint8ClampedList get binaryData; | 20 | external Uint8ClampedList get binaryData; |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | +const jsqrLibrary = JsLibrary( | ||
| 24 | + contextName: 'jsQR', | ||
| 25 | + url: 'https://cdn.jsdelivr.net/npm/jsqr@1.4.0/dist/jsQR.min.js', | ||
| 26 | + usesRequireJs: true, | ||
| 27 | +); | ||
| 28 | + | ||
| 23 | /// Barcode reader that uses jsQR library. | 29 | /// Barcode reader that uses jsQR library. |
| 24 | /// jsQR supports only QR codes format. | 30 | /// jsQR supports only QR codes format. |
| 25 | -/// | ||
| 26 | -/// Include jsQR to your index.html file: | ||
| 27 | -/// <script src="https://cdn.jsdelivr.net/npm/jsqr@1.4.0/dist/jsQR.min.js"></script> | ||
| 28 | class JsQrCodeReader extends WebBarcodeReaderBase | 31 | class JsQrCodeReader extends WebBarcodeReaderBase |
| 29 | with InternalStreamCreation, InternalTorchDetection { | 32 | with InternalStreamCreation, InternalTorchDetection { |
| 30 | JsQrCodeReader({required super.videoContainer}); | 33 | JsQrCodeReader({required super.videoContainer}); |
| @@ -33,6 +36,9 @@ class JsQrCodeReader extends WebBarcodeReaderBase | @@ -33,6 +36,9 @@ class JsQrCodeReader extends WebBarcodeReaderBase | ||
| 33 | bool get isStarted => localMediaStream != null; | 36 | bool get isStarted => localMediaStream != null; |
| 34 | 37 | ||
| 35 | @override | 38 | @override |
| 39 | + List<JsLibrary> get jsLibraries => [jsqrLibrary]; | ||
| 40 | + | ||
| 41 | + @override | ||
| 36 | Future<void> start({ | 42 | Future<void> start({ |
| 37 | required CameraFacing cameraFacing, | 43 | required CameraFacing cameraFacing, |
| 38 | List<BarcodeFormat>? formats, | 44 | List<BarcodeFormat>? formats, |
lib/src/web/utils.dart
0 → 100644
| 1 | +import 'dart:async'; | ||
| 2 | +import 'dart:html' as html; | ||
| 3 | +import 'dart:js' show context; | ||
| 4 | + | ||
| 5 | +import 'package:js/js.dart'; | ||
| 6 | +import 'package:mobile_scanner/src/web/base.dart'; | ||
| 7 | + | ||
| 8 | +Future<void> loadScript(JsLibrary library) async { | ||
| 9 | + // ignore: avoid_dynamic_calls | ||
| 10 | + if (library.usesRequireJs && context['define']?['amd'] != null) { | ||
| 11 | + // see https://github.com/dart-lang/sdk/issues/33979 | ||
| 12 | + return loadScriptUsingRequireJS(library.contextName, library.url); | ||
| 13 | + } else { | ||
| 14 | + return loadScriptUsingScriptTag(library.url); | ||
| 15 | + } | ||
| 16 | +} | ||
| 17 | + | ||
| 18 | +Future<void> loadScriptUsingScriptTag(String url) { | ||
| 19 | + final script = html.ScriptElement() | ||
| 20 | + ..async = true | ||
| 21 | + ..defer = false | ||
| 22 | + ..crossOrigin = 'anonymous' | ||
| 23 | + ..type = 'text/javascript' | ||
| 24 | + // ignore: unsafe_html | ||
| 25 | + ..src = url; | ||
| 26 | + | ||
| 27 | + html.document.head!.append(script); | ||
| 28 | + | ||
| 29 | + return script.onLoad.first; | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +Future<void> loadScriptUsingRequireJS(String packageName, String url) { | ||
| 33 | + final Completer completer = Completer(); | ||
| 34 | + final String eventName = '_${packageName}Loaded'; | ||
| 35 | + | ||
| 36 | + context.callMethod( | ||
| 37 | + 'addEventListener', | ||
| 38 | + [eventName, allowInterop((_) => completer.complete())], | ||
| 39 | + ); | ||
| 40 | + | ||
| 41 | + final script = html.ScriptElement() | ||
| 42 | + ..type = 'text/javascript' | ||
| 43 | + ..async = false | ||
| 44 | + ..defer = false | ||
| 45 | + ..text = ''' | ||
| 46 | + require(["$url"], (package) => { | ||
| 47 | + window.$packageName = package; | ||
| 48 | + const event = new Event("$eventName"); | ||
| 49 | + dispatchEvent(event); | ||
| 50 | + }) | ||
| 51 | + '''; | ||
| 52 | + | ||
| 53 | + html.document.head!.append(script); | ||
| 54 | + | ||
| 55 | + return completer.future; | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +/// Injects JS [libraries] | ||
| 59 | +/// | ||
| 60 | +/// Returns a [Future] that resolves when all of the `script` tags `onLoad` events trigger. | ||
| 61 | +Future<void> injectJSLibraries(List<JsLibrary> libraries) { | ||
| 62 | + final List<Future<void>> loading = []; | ||
| 63 | + | ||
| 64 | + for (final library in libraries) { | ||
| 65 | + final future = loadScript(library); | ||
| 66 | + loading.add(future); | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + return Future.wait(loading); | ||
| 70 | +} |
| @@ -168,10 +168,13 @@ extension JsZXingBrowserMultiFormatReaderExt | @@ -168,10 +168,13 @@ extension JsZXingBrowserMultiFormatReaderExt | ||
| 168 | external MediaStream? stream; | 168 | external MediaStream? stream; |
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | +const zxingJsLibrary = JsLibrary( | ||
| 172 | + contextName: 'ZXing', | ||
| 173 | + url: 'https://unpkg.com/@zxing/library@0.19.1', | ||
| 174 | + usesRequireJs: true, | ||
| 175 | +); | ||
| 176 | + | ||
| 171 | /// Barcode reader that uses zxing-js library. | 177 | /// Barcode reader that uses zxing-js library. |
| 172 | -/// | ||
| 173 | -/// Include zxing-js to your index.html file: | ||
| 174 | -/// <script type="text/javascript" src="https://unpkg.com/@zxing/library@0.19.1"></script> | ||
| 175 | class ZXingBarcodeReader extends WebBarcodeReaderBase | 178 | class ZXingBarcodeReader extends WebBarcodeReaderBase |
| 176 | with InternalStreamCreation, InternalTorchDetection { | 179 | with InternalStreamCreation, InternalTorchDetection { |
| 177 | JsZXingBrowserMultiFormatReader? _reader; | 180 | JsZXingBrowserMultiFormatReader? _reader; |
| @@ -182,6 +185,9 @@ class ZXingBarcodeReader extends WebBarcodeReaderBase | @@ -182,6 +185,9 @@ class ZXingBarcodeReader extends WebBarcodeReaderBase | ||
| 182 | bool get isStarted => localMediaStream != null; | 185 | bool get isStarted => localMediaStream != null; |
| 183 | 186 | ||
| 184 | @override | 187 | @override |
| 188 | + List<JsLibrary> get jsLibraries => [zxingJsLibrary]; | ||
| 189 | + | ||
| 190 | + @override | ||
| 185 | Future<void> start({ | 191 | Future<void> start({ |
| 186 | required CameraFacing cameraFacing, | 192 | required CameraFacing cameraFacing, |
| 187 | List<BarcodeFormat>? formats, | 193 | List<BarcodeFormat>? formats, |
-
Please register or login to post a comment