From 45b2c47726b2155bc238cf110061ccff4e4d83d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Garc=C3=ADa=20=C3=81lvarez?= Date: Tue, 17 Mar 2020 17:44:59 +0100 Subject: [PATCH] Web support --- .../lib/barcode_web.dart | 235 ++++++++++++++++++ flutter_barcode_reader_web/pubspec.yaml | 22 ++ pubspec.yaml | 4 +- 3 files changed, 259 insertions(+), 2 deletions(-) create mode 100644 flutter_barcode_reader_web/lib/barcode_web.dart create mode 100644 flutter_barcode_reader_web/pubspec.yaml diff --git a/flutter_barcode_reader_web/lib/barcode_web.dart b/flutter_barcode_reader_web/lib/barcode_web.dart new file mode 100644 index 00000000..c528df40 --- /dev/null +++ b/flutter_barcode_reader_web/lib/barcode_web.dart @@ -0,0 +1,235 @@ +@JS() +library jsqrscanner; + +import 'dart:async'; +import 'dart:html'; + +import 'package:flutter/services.dart'; +import 'package:js/js.dart'; +import 'package:js/js_util.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; + +class BarcodeScanPlugin { + Completer _completer; + + static void registerWith(Registrar registrar) { + final MethodChannel channel = MethodChannel( + 'de.mintware.barcode_scan', + const StandardMethodCodec(), + registrar.messenger + ); + final BarcodeScanPlugin instance = new BarcodeScanPlugin(); + channel.setMethodCallHandler(instance.handleMethodCall); + } + + Future handleMethodCall(MethodCall call) async { + _createCSS(); + var script = document.createElement('script'); + script.setAttribute('type', 'text/javascript'); + document.querySelector('head').append(script); + script.setAttribute('src', 'https://cdn.jsdelivr.net/gh/jbialobr/JsQRScanner@master/war/js/jsqrscanner.nocache.js'); + _createHTML(); + document.querySelector('#toolbar p').addEventListener('click', (event) => _close()); + setProperty(window, 'JsQRScannerReady', allowInterop(this.scannerReady)); + _completer = new Completer(); + return _completer.future; + } + + void _createCSS() { + var style = document.createElement('style'); + style.appendText(''' + * { + margin: 0; + padding: 0; + } + + body { + overflow: hidden; + } + + #container { + position: fixed; + width: 100%; + height: 100%; + background-color: #2F2F2F; + } + + video { + position: relative; + top: 0; + left: 0; + height: 100vh; + width: 100vw; + object-fit: cover; + } + + #cover { + position: absolute; + top: 50%; + left: 50%; + width: 70vmin; + height: 70vmin; + transform: translateX(-50%) translateY(-50%); + text-align: center; + } + + #cover:after { + content:''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + box-shadow: 0 0 0 999px rgba(0, 0, 0, 0.4); + } + + #cover img { + width: 100%; + height: 100%; + } + + #cover > div { + background-color: #BFE47B; + } + + #topleft, #lefttop { + position: absolute; + top: 0; + left: 0; + } + + #topleft { + width: 8vmin; + height: 2vmin; + } + + #lefttop { + width: 2vmin; + height: 8vmin; + } + + #topright, #righttop { + position: absolute; + top: 0; + right: 0; + } + + #topright { + width: 8vmin; + height: 2vmin; + } + + #righttop { + width: 2vmin; + height: 8vmin; + } + + #bottomleft, #leftbottom { + position: absolute; + bottom: 0; + left: 0; + } + + #bottomleft { + width: 8vmin; + height: 2vmin; + } + + #leftbottom { + width: 2vmin; + height: 8vmin; + } + + #bottomright, #rightbottom { + position: absolute; + bottom: 0; + right: 0; + } + + #bottomright { + width: 8vmin; + height: 2vmin; + } + + #rightbottom { + width: 2vmin; + height: 8vmin; + } + + #toolbar { + background-color: #2F2F2F; + } + + #toolbar p { + float: left; + font-size: 24px; + color: white; + margin-left: 16px; + padding: 16px; + } + + #clear { + clear: both; + } + '''); + document.querySelector('head').append(style); + } + + void _createHTML() { + var containerDiv = document.createElement('div'); + containerDiv.id = 'container'; + containerDiv.innerHtml = ''' +
+

X

+
+
+
+
+
+
+
+
+
+
+
+
+
+ '''; + document.body.append(containerDiv); + } + + void onQRCodeScanned(String scannedText) { + _completer.complete(scannedText); + _close(); + } + + void _close() { + document.getElementById('container').remove(); + } + + void scannerReady() { + var scanner = JsQRScanner(onQRCodeScanned, provideVideo); + scanner.setSnapImageMaxSize(300); + var scannerParentElement = document.getElementById('scanner'); + scanner.appendTo(scannerParentElement); + } + + Promise provideVideo() { + return new Promise(allowInterop((resolve, reject) { + window.navigator.getUserMedia(video: true).then(resolve, onError: reject); + })); + } +} + +@JS() +class JsQRScanner { + external factory JsQRScanner(Function onQRCodeScanned, Function provideVideo); + external setSnapImageMaxSize(int maxSize); + external appendTo(Element element); +} + +@JS() +class Promise { + external Promise(void executor(void resolve(T result), Function reject)); + external Promise then(void onFulfilled(T result), [Function onRejected]); +} \ No newline at end of file diff --git a/flutter_barcode_reader_web/pubspec.yaml b/flutter_barcode_reader_web/pubspec.yaml new file mode 100644 index 00000000..1feb93cc --- /dev/null +++ b/flutter_barcode_reader_web/pubspec.yaml @@ -0,0 +1,22 @@ +name: barcode_scan_web +description: A flutter plugin for scanning 2D barcodes and QRCodes via camera. +version: 2.0.1 +homepage: https://github.com/mintware-de/flutter_barcode_reader + +dependencies: + flutter: + sdk: flutter + flutter_web_plugins: + sdk: flutter + js: ^0.6.0 + +environment: + sdk: ">=2.0.0-dev.58.0 <3.0.0" + flutter: ^1.10.0 + +flutter: + plugin: + platforms: + web: + pluginClass: BarcodeScanPlugin + fileName: barcode_web.dart \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index a897da35..1fb90086 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,8 +7,8 @@ dependencies: flutter: sdk: flutter -environment: - sdk: ">=2.0.0-dev.58.0 <3.0.0" +environment: + sdk: ">=2.0.0-dev.58.0 <3.0.0" flutter: plugin: