From c4bc3c07ee37aa24c563c7e8fd1d6343b99be796 Mon Sep 17 00:00:00 2001 From: dardan-inecta Date: Tue, 15 Apr 2025 11:14:45 -0400 Subject: [PATCH 01/27] Update build.gradle --- android/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/android/build.gradle b/android/build.gradle index e1173a39..26a0034c 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -31,6 +31,7 @@ android { main.java.srcDirs += 'src/main/kotlin' } defaultConfig { + namespace 'com.example.qrcodescanner' // minSdkVersion is determined by Native View. minSdkVersion 20 targetSdkVersion 33 From af42b6cdfc8db21ee22d608ee7b9fa17015be329 Mon Sep 17 00:00:00 2001 From: dardan-inecta Date: Tue, 15 Apr 2025 11:21:03 -0400 Subject: [PATCH 02/27] Update build.gradle --- android/build.gradle | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 26a0034c..1649317e 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -26,32 +26,27 @@ apply plugin: 'kotlin-android' android { compileSdk 33 + namespace 'net.touchcapture.qr.flutterqr' // ✅ Place it here - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } defaultConfig { - namespace 'com.example.qrcodescanner' - // minSdkVersion is determined by Native View. minSdkVersion 20 targetSdkVersion 33 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" multiDexEnabled true } - kotlinOptions { - jvmTarget = '11' + sourceSets { + main.java.srcDirs += 'src/main/kotlin' } compileOptions { - // Flag to enable support for the new language APIs - coreLibraryDesugaringEnabled true - // Sets Java compatibility to Java 11 sourceCompatibility JavaVersion.VERSION_11 targetCompatibility JavaVersion.VERSION_11 + coreLibraryDesugaringEnabled true } - if (project.android.hasProperty('namespace')) { - namespace 'net.touchcapture.qr.flutterqr' + + kotlinOptions { + jvmTarget = '11' } } @@ -60,5 +55,5 @@ dependencies { implementation('com.journeyapps:zxing-android-embedded:4.3.0') { transitive = false } implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'com.google.zxing:core:3.5.2' - coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3' + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4' // ✅ latest stable } From bb340c8f76fce09e4864f988ea11e76b296b353c Mon Sep 17 00:00:00 2001 From: Sweta0208 Date: Tue, 22 Apr 2025 20:36:39 +0530 Subject: [PATCH 03/27] Fix web issue --- lib/src/web/flutter_qr_web.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/web/flutter_qr_web.dart b/lib/src/web/flutter_qr_web.dart index de368ace..c0bea29a 100644 --- a/lib/src/web/flutter_qr_web.dart +++ b/lib/src/web/flutter_qr_web.dart @@ -80,7 +80,7 @@ class _WebQrViewState extends State { // video = html.VideoElement(); WebQrView.vidDiv.children = [video]; - // ignore: UNDEFINED_PREFIXED_NAME + // ignore: undefined_prefixed_name ui.platformViewRegistry .registerViewFactory(viewID, (int id) => WebQrView.vidDiv); // giving JavaScipt some time to process the DOM changes From f4784d9260fdf0a9e14623761439ef888c4e68e4 Mon Sep 17 00:00:00 2001 From: Sweta0208 Date: Tue, 22 Apr 2025 20:50:25 +0530 Subject: [PATCH 04/27] fixed web issue --- lib/src/web/flutter_qr_web.dart | 48 +++++++++++++-------------------- 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/lib/src/web/flutter_qr_web.dart b/lib/src/web/flutter_qr_web.dart index c0bea29a..fa5cb873 100644 --- a/lib/src/web/flutter_qr_web.dart +++ b/lib/src/web/flutter_qr_web.dart @@ -4,8 +4,9 @@ import 'dart:async'; import 'dart:core'; import 'dart:html' as html; import 'dart:js_util'; -import 'dart:ui' as ui; +// ignore_for_file: avoid_web_libraries_in_flutter +import 'dart:ui' as ui; import 'package:flutter/material.dart'; import '../../qr_code_scanner.dart'; @@ -24,21 +25,16 @@ class WebQrView extends StatefulWidget { final CameraFacing? cameraFacing; const WebQrView( - {Key? key, - required this.onPlatformViewCreated, - this.onPermissionSet, - this.cameraFacing = CameraFacing.front}) + {Key? key, required this.onPlatformViewCreated, this.onPermissionSet, this.cameraFacing = CameraFacing.front}) : super(key: key); @override _WebQrViewState createState() => _WebQrViewState(); - static html.DivElement vidDiv = - html.DivElement(); // need a global for the registerViewFactory + static html.DivElement vidDiv = html.DivElement(); // need a global for the registerViewFactory static Future cameraAvailable() async { - final sources = - await html.window.navigator.mediaDevices!.enumerateDevices(); + final sources = await html.window.navigator.mediaDevices!.enumerateDevices(); // List vidIds = []; var hasCam = false; for (final e in sources) { @@ -66,8 +62,7 @@ class _WebQrViewState extends State { html.VideoElement video = html.VideoElement(); String viewID = 'QRVIEW-' + DateTime.now().millisecondsSinceEpoch.toString(); - final StreamController _scanUpdateController = - StreamController(); + final StreamController _scanUpdateController = StreamController(); late CameraFacing facing; Timer? _frameIntervall; @@ -80,9 +75,11 @@ class _WebQrViewState extends State { // video = html.VideoElement(); WebQrView.vidDiv.children = [video]; - // ignore: undefined_prefixed_name - ui.platformViewRegistry - .registerViewFactory(viewID, (int id) => WebQrView.vidDiv); + // ignore: undefined_prefixed_name + ui.platformViewRegistry.registerViewFactory( + viewID, + (int id) => WebQrView.vidDiv, + ); // giving JavaScipt some time to process the DOM changes Timer(const Duration(milliseconds: 500), () { start(); @@ -92,8 +89,7 @@ class _WebQrViewState extends State { Future start() async { await _makeCall(); _frameIntervall?.cancel(); - _frameIntervall = - Timer.periodic(const Duration(milliseconds: 200), (timer) { + _frameIntervall = Timer.periodic(const Duration(milliseconds: 200), (timer) { _captureFrame2(); }); } @@ -137,8 +133,7 @@ class _WebQrViewState extends State { widget.onPermissionSet?.call(_controller!, true); _localStream = stream; video.srcObject = _localStream; - video.setAttribute('playsinline', - 'true'); // required to tell iOS safari we don't want fullscreen + video.setAttribute('playsinline', 'true'); // required to tell iOS safari we don't want fullscreen await video.play(); } catch (e) { cancel(); @@ -177,16 +172,14 @@ class _WebQrViewState extends State { if (_localStream == null) { return null; } - final canvas = - html.CanvasElement(width: video.videoWidth, height: video.videoHeight); + final canvas = html.CanvasElement(width: video.videoWidth, height: video.videoHeight); final ctx = canvas.context2D; // canvas.width = video.videoWidth; // canvas.height = video.videoHeight; ctx.drawImage(video, 0, 0); final imgData = ctx.getImageData(0, 0, canvas.width!, canvas.height!); - final size = - Size(canvas.width?.toDouble() ?? 0, canvas.height?.toDouble() ?? 0); + final size = Size(canvas.width?.toDouble() ?? 0, canvas.height?.toDouble() ?? 0); if (size != _size) { setState(() { _setCanvasSize(size); @@ -197,8 +190,7 @@ class _WebQrViewState extends State { final code = jsQR(imgData.data, canvas.width, canvas.height); // ignore: unnecessary_null_comparison if (code != null && code.data != null) { - _scanUpdateController - .add(Barcode(code.data, BarcodeFormat.qrcode, code.data.codeUnits)); + _scanUpdateController.add(Barcode(code.data, BarcodeFormat.qrcode, code.data.codeUnits)); } } on NoSuchMethodError { // Do nothing, this exception occurs continously in web release when no @@ -263,9 +255,7 @@ class QRViewControllerWeb implements QRViewController { @override Future flipCamera() async { // TODO: improve error handling - _state.facing = _state.facing == CameraFacing.front - ? CameraFacing.back - : CameraFacing.front; + _state.facing = _state.facing == CameraFacing.front ? CameraFacing.back : CameraFacing.front; await _state.start(); return _state.facing; } @@ -325,9 +315,7 @@ class QRViewControllerWeb implements QRViewController { } } -Widget createWebQrView( - {onPlatformViewCreated, onPermissionSet, CameraFacing? cameraFacing}) => - WebQrView( +Widget createWebQrView({onPlatformViewCreated, onPermissionSet, CameraFacing? cameraFacing}) => WebQrView( onPlatformViewCreated: onPlatformViewCreated, onPermissionSet: onPermissionSet, cameraFacing: cameraFacing, From ba3c4a40f00ae8904e5b221e12b7b41d23082dc1 Mon Sep 17 00:00:00 2001 From: Sweta0208 Date: Wed, 23 Apr 2025 11:40:22 +0530 Subject: [PATCH 05/27] Resolved issue for Dart SDK (3.3+) --- lib/src/web/flutter_qr_web.dart | 6 +++--- lib/src/web/web_view_registry.dart | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 lib/src/web/web_view_registry.dart diff --git a/lib/src/web/flutter_qr_web.dart b/lib/src/web/flutter_qr_web.dart index fa5cb873..6db8a516 100644 --- a/lib/src/web/flutter_qr_web.dart +++ b/lib/src/web/flutter_qr_web.dart @@ -6,7 +6,7 @@ import 'dart:html' as html; import 'dart:js_util'; // ignore_for_file: avoid_web_libraries_in_flutter -import 'dart:ui' as ui; +import 'web_view_registry.dart'; import 'package:flutter/material.dart'; import '../../qr_code_scanner.dart'; @@ -76,7 +76,7 @@ class _WebQrViewState extends State { // video = html.VideoElement(); WebQrView.vidDiv.children = [video]; // ignore: undefined_prefixed_name - ui.platformViewRegistry.registerViewFactory( + platformViewRegistry.registerViewFactory( viewID, (int id) => WebQrView.vidDiv, ); @@ -238,7 +238,7 @@ class _WebQrViewState extends State { ); } - void _setCanvasSize(ui.Size size) { + void _setCanvasSize(Size size) { setState(() { _size = size; }); diff --git a/lib/src/web/web_view_registry.dart b/lib/src/web/web_view_registry.dart new file mode 100644 index 00000000..27106cb9 --- /dev/null +++ b/lib/src/web/web_view_registry.dart @@ -0,0 +1,4 @@ +// ignore: avoid_web_libraries_in_flutter +import 'dart:ui_web' as ui_web; + +final platformViewRegistry = ui_web.platformViewRegistry; \ No newline at end of file From 9e7eec9669023ea9f8d9fb0b700c5a96494d68a1 Mon Sep 17 00:00:00 2001 From: Sweta0208 Date: Wed, 23 Apr 2025 11:46:57 +0530 Subject: [PATCH 06/27] Fix --- lib/src/web/flutter_qr_web.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/src/web/flutter_qr_web.dart b/lib/src/web/flutter_qr_web.dart index 6db8a516..118b1b7f 100644 --- a/lib/src/web/flutter_qr_web.dart +++ b/lib/src/web/flutter_qr_web.dart @@ -80,6 +80,9 @@ class _WebQrViewState extends State { viewID, (int id) => WebQrView.vidDiv, ); + + print('[QR Scanner Web] viewID: $viewID'); + // giving JavaScipt some time to process the DOM changes Timer(const Duration(milliseconds: 500), () { start(); From 88f5f26c5f091fa82b70d410201b562707db5ab9 Mon Sep 17 00:00:00 2001 From: Sweta - Inecta <151121857+swetav1996@users.noreply.github.com> Date: Thu, 9 Oct 2025 16:44:11 +0530 Subject: [PATCH 07/27] Upgrade flutter version --- pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index 72f21cb8..1ed960fd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,8 +5,8 @@ homepage: https://juliuscanute.com repository: https://github.com/juliuscanute/qr_code_scanner environment: - sdk: '>=2.17.0 <3.0.0' - flutter: ">=1.12.0" + sdk: '>=3.4.3 <4.0.0' + flutter: ">=1.17.0" dependencies: js: ^0.6.3 From ca0bbce134e746664adaacd7aa6748947f89728a Mon Sep 17 00:00:00 2001 From: Sweta - Inecta <151121857+swetav1996@users.noreply.github.com> Date: Thu, 9 Oct 2025 16:50:57 +0530 Subject: [PATCH 08/27] Update flutter_qr_web.dart --- lib/src/web/flutter_qr_web.dart | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/src/web/flutter_qr_web.dart b/lib/src/web/flutter_qr_web.dart index 118b1b7f..a380bd6b 100644 --- a/lib/src/web/flutter_qr_web.dart +++ b/lib/src/web/flutter_qr_web.dart @@ -10,6 +10,7 @@ import 'web_view_registry.dart'; import 'package:flutter/material.dart'; import '../../qr_code_scanner.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart' as web_plugins; import 'jsqr.dart'; import 'media.dart'; @@ -76,10 +77,10 @@ class _WebQrViewState extends State { // video = html.VideoElement(); WebQrView.vidDiv.children = [video]; // ignore: undefined_prefixed_name - platformViewRegistry.registerViewFactory( - viewID, - (int id) => WebQrView.vidDiv, - ); + web_plugins.registerViewFactory( + viewID, + (int id) => WebQrView.vidDiv, +); print('[QR Scanner Web] viewID: $viewID'); From 7b2631f0ca6bfb550176386dbbd688cc64c69dc8 Mon Sep 17 00:00:00 2001 From: Sweta - Inecta <151121857+swetav1996@users.noreply.github.com> Date: Thu, 9 Oct 2025 16:54:44 +0530 Subject: [PATCH 09/27] Update flutter_qr_web.dart --- lib/src/web/flutter_qr_web.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/web/flutter_qr_web.dart b/lib/src/web/flutter_qr_web.dart index a380bd6b..f4f20468 100644 --- a/lib/src/web/flutter_qr_web.dart +++ b/lib/src/web/flutter_qr_web.dart @@ -10,7 +10,7 @@ import 'web_view_registry.dart'; import 'package:flutter/material.dart'; import '../../qr_code_scanner.dart'; -import 'package:flutter_web_plugins/flutter_web_plugins.dart' as web_plugins; +import 'dart:ui_web' as ui_web; import 'jsqr.dart'; import 'media.dart'; @@ -77,7 +77,7 @@ class _WebQrViewState extends State { // video = html.VideoElement(); WebQrView.vidDiv.children = [video]; // ignore: undefined_prefixed_name - web_plugins.registerViewFactory( + ui_web.platformViewRegistry.registerViewFactory( viewID, (int id) => WebQrView.vidDiv, ); From 5bd088cc9b25cfa5bb2685382f95ddeb8ed6ff19 Mon Sep 17 00:00:00 2001 From: Sweta - Inecta <151121857+swetav1996@users.noreply.github.com> Date: Thu, 9 Oct 2025 17:01:48 +0530 Subject: [PATCH 10/27] Update flutter_qr_web.dart --- lib/src/web/flutter_qr_web.dart | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/src/web/flutter_qr_web.dart b/lib/src/web/flutter_qr_web.dart index f4f20468..d777b11f 100644 --- a/lib/src/web/flutter_qr_web.dart +++ b/lib/src/web/flutter_qr_web.dart @@ -10,7 +10,8 @@ import 'web_view_registry.dart'; import 'package:flutter/material.dart'; import '../../qr_code_scanner.dart'; -import 'dart:ui_web' as ui_web; +import 'dart:ui' as ui; +import 'package:flutter_web_plugins/flutter_web_plugins.dart' show registerViewFactory; import 'jsqr.dart'; import 'media.dart'; @@ -77,10 +78,7 @@ class _WebQrViewState extends State { // video = html.VideoElement(); WebQrView.vidDiv.children = [video]; // ignore: undefined_prefixed_name - ui_web.platformViewRegistry.registerViewFactory( - viewID, - (int id) => WebQrView.vidDiv, -); + registerViewFactory(viewID, (int id) => WebQrView.vidDiv); print('[QR Scanner Web] viewID: $viewID'); From 73835fe9ed6cf68f8d5a4d9f9d767f038921f270 Mon Sep 17 00:00:00 2001 From: Sweta - Inecta <151121857+swetav1996@users.noreply.github.com> Date: Thu, 9 Oct 2025 17:04:22 +0530 Subject: [PATCH 11/27] Update flutter_qr_web.dart --- lib/src/web/flutter_qr_web.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/src/web/flutter_qr_web.dart b/lib/src/web/flutter_qr_web.dart index d777b11f..1ccd1407 100644 --- a/lib/src/web/flutter_qr_web.dart +++ b/lib/src/web/flutter_qr_web.dart @@ -6,7 +6,6 @@ import 'dart:html' as html; import 'dart:js_util'; // ignore_for_file: avoid_web_libraries_in_flutter -import 'web_view_registry.dart'; import 'package:flutter/material.dart'; import '../../qr_code_scanner.dart'; From 646cb3ba8f60e2f15bb8fd20f76d99ee9ee6a885 Mon Sep 17 00:00:00 2001 From: Sweta - Inecta <151121857+swetav1996@users.noreply.github.com> Date: Thu, 9 Oct 2025 17:11:42 +0530 Subject: [PATCH 12/27] Update flutter_qr_web.dart --- lib/src/web/flutter_qr_web.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/web/flutter_qr_web.dart b/lib/src/web/flutter_qr_web.dart index 1ccd1407..5c51cf29 100644 --- a/lib/src/web/flutter_qr_web.dart +++ b/lib/src/web/flutter_qr_web.dart @@ -10,7 +10,7 @@ import 'package:flutter/material.dart'; import '../../qr_code_scanner.dart'; import 'dart:ui' as ui; -import 'package:flutter_web_plugins/flutter_web_plugins.dart' show registerViewFactory; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; import 'jsqr.dart'; import 'media.dart'; From fa2c89386adc32c5c89050f06069be61ebddc7ef Mon Sep 17 00:00:00 2001 From: Sweta - Inecta <151121857+swetav1996@users.noreply.github.com> Date: Thu, 9 Oct 2025 17:15:57 +0530 Subject: [PATCH 13/27] Update flutter_qr_web.dart --- lib/src/web/flutter_qr_web.dart | 52 ++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/lib/src/web/flutter_qr_web.dart b/lib/src/web/flutter_qr_web.dart index 5c51cf29..91fe183a 100644 --- a/lib/src/web/flutter_qr_web.dart +++ b/lib/src/web/flutter_qr_web.dart @@ -4,13 +4,12 @@ import 'dart:async'; import 'dart:core'; import 'dart:html' as html; import 'dart:js_util'; +import 'dart:ui' as ui; +import 'dart:ui' as ui_web; -// ignore_for_file: avoid_web_libraries_in_flutter import 'package:flutter/material.dart'; import '../../qr_code_scanner.dart'; -import 'dart:ui' as ui; -import 'package:flutter_web_plugins/flutter_web_plugins.dart'; import 'jsqr.dart'; import 'media.dart'; @@ -26,16 +25,21 @@ class WebQrView extends StatefulWidget { final CameraFacing? cameraFacing; const WebQrView( - {Key? key, required this.onPlatformViewCreated, this.onPermissionSet, this.cameraFacing = CameraFacing.front}) + {Key? key, + required this.onPlatformViewCreated, + this.onPermissionSet, + this.cameraFacing = CameraFacing.front}) : super(key: key); @override _WebQrViewState createState() => _WebQrViewState(); - static html.DivElement vidDiv = html.DivElement(); // need a global for the registerViewFactory + static html.DivElement vidDiv = + html.DivElement(); // need a global for the registerViewFactory static Future cameraAvailable() async { - final sources = await html.window.navigator.mediaDevices!.enumerateDevices(); + final sources = + await html.window.navigator.mediaDevices!.enumerateDevices(); // List vidIds = []; var hasCam = false; for (final e in sources) { @@ -63,7 +67,8 @@ class _WebQrViewState extends State { html.VideoElement video = html.VideoElement(); String viewID = 'QRVIEW-' + DateTime.now().millisecondsSinceEpoch.toString(); - final StreamController _scanUpdateController = StreamController(); + final StreamController _scanUpdateController = + StreamController(); late CameraFacing facing; Timer? _frameIntervall; @@ -76,11 +81,9 @@ class _WebQrViewState extends State { // video = html.VideoElement(); WebQrView.vidDiv.children = [video]; - // ignore: undefined_prefixed_name - registerViewFactory(viewID, (int id) => WebQrView.vidDiv); - - print('[QR Scanner Web] viewID: $viewID'); - + // ignore: UNDEFINED_PREFIXED_NAME + ui.platformViewRegistry + .registerViewFactory(viewID, (int id) => WebQrView.vidDiv); // giving JavaScipt some time to process the DOM changes Timer(const Duration(milliseconds: 500), () { start(); @@ -90,7 +93,8 @@ class _WebQrViewState extends State { Future start() async { await _makeCall(); _frameIntervall?.cancel(); - _frameIntervall = Timer.periodic(const Duration(milliseconds: 200), (timer) { + _frameIntervall = + Timer.periodic(const Duration(milliseconds: 200), (timer) { _captureFrame2(); }); } @@ -134,7 +138,8 @@ class _WebQrViewState extends State { widget.onPermissionSet?.call(_controller!, true); _localStream = stream; video.srcObject = _localStream; - video.setAttribute('playsinline', 'true'); // required to tell iOS safari we don't want fullscreen + video.setAttribute('playsinline', + 'true'); // required to tell iOS safari we don't want fullscreen await video.play(); } catch (e) { cancel(); @@ -173,14 +178,16 @@ class _WebQrViewState extends State { if (_localStream == null) { return null; } - final canvas = html.CanvasElement(width: video.videoWidth, height: video.videoHeight); + final canvas = + html.CanvasElement(width: video.videoWidth, height: video.videoHeight); final ctx = canvas.context2D; // canvas.width = video.videoWidth; // canvas.height = video.videoHeight; ctx.drawImage(video, 0, 0); final imgData = ctx.getImageData(0, 0, canvas.width!, canvas.height!); - final size = Size(canvas.width?.toDouble() ?? 0, canvas.height?.toDouble() ?? 0); + final size = + Size(canvas.width?.toDouble() ?? 0, canvas.height?.toDouble() ?? 0); if (size != _size) { setState(() { _setCanvasSize(size); @@ -191,7 +198,8 @@ class _WebQrViewState extends State { final code = jsQR(imgData.data, canvas.width, canvas.height); // ignore: unnecessary_null_comparison if (code != null && code.data != null) { - _scanUpdateController.add(Barcode(code.data, BarcodeFormat.qrcode, code.data.codeUnits)); + _scanUpdateController + .add(Barcode(code.data, BarcodeFormat.qrcode, code.data.codeUnits)); } } on NoSuchMethodError { // Do nothing, this exception occurs continously in web release when no @@ -239,7 +247,7 @@ class _WebQrViewState extends State { ); } - void _setCanvasSize(Size size) { + void _setCanvasSize(ui.Size size) { setState(() { _size = size; }); @@ -256,7 +264,9 @@ class QRViewControllerWeb implements QRViewController { @override Future flipCamera() async { // TODO: improve error handling - _state.facing = _state.facing == CameraFacing.front ? CameraFacing.back : CameraFacing.front; + _state.facing = _state.facing == CameraFacing.front + ? CameraFacing.back + : CameraFacing.front; await _state.start(); return _state.facing; } @@ -316,7 +326,9 @@ class QRViewControllerWeb implements QRViewController { } } -Widget createWebQrView({onPlatformViewCreated, onPermissionSet, CameraFacing? cameraFacing}) => WebQrView( +Widget createWebQrView( + {onPlatformViewCreated, onPermissionSet, CameraFacing? cameraFacing}) => + WebQrView( onPlatformViewCreated: onPlatformViewCreated, onPermissionSet: onPermissionSet, cameraFacing: cameraFacing, From 22d754b81f7593cdd16818964afcfea4fc4ab0cf Mon Sep 17 00:00:00 2001 From: Sweta - Inecta <151121857+swetav1996@users.noreply.github.com> Date: Thu, 9 Oct 2025 17:34:32 +0530 Subject: [PATCH 14/27] Update flutter_qr_web.dart --- lib/src/web/flutter_qr_web.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/src/web/flutter_qr_web.dart b/lib/src/web/flutter_qr_web.dart index 91fe183a..93051121 100644 --- a/lib/src/web/flutter_qr_web.dart +++ b/lib/src/web/flutter_qr_web.dart @@ -5,7 +5,6 @@ import 'dart:core'; import 'dart:html' as html; import 'dart:js_util'; import 'dart:ui' as ui; -import 'dart:ui' as ui_web; import 'package:flutter/material.dart'; @@ -82,8 +81,7 @@ class _WebQrViewState extends State { // video = html.VideoElement(); WebQrView.vidDiv.children = [video]; // ignore: UNDEFINED_PREFIXED_NAME - ui.platformViewRegistry - .registerViewFactory(viewID, (int id) => WebQrView.vidDiv); + registerViewFactory(viewID, (int id) => WebQrView.vidDiv); // giving JavaScipt some time to process the DOM changes Timer(const Duration(milliseconds: 500), () { start(); From 8c93ed72f6839ad58c1f290f30a7c6c1ed4506bf Mon Sep 17 00:00:00 2001 From: Sweta - Inecta <151121857+swetav1996@users.noreply.github.com> Date: Thu, 9 Oct 2025 17:41:51 +0530 Subject: [PATCH 15/27] Update flutter_qr_web.dart --- lib/src/web/flutter_qr_web.dart | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/src/web/flutter_qr_web.dart b/lib/src/web/flutter_qr_web.dart index 93051121..acdc6b1a 100644 --- a/lib/src/web/flutter_qr_web.dart +++ b/lib/src/web/flutter_qr_web.dart @@ -5,6 +5,7 @@ import 'dart:core'; import 'dart:html' as html; import 'dart:js_util'; import 'dart:ui' as ui; +import 'dart:ui_web' as ui_web; // Import the necessary library import 'package:flutter/material.dart'; @@ -81,7 +82,9 @@ class _WebQrViewState extends State { // video = html.VideoElement(); WebQrView.vidDiv.children = [video]; // ignore: UNDEFINED_PREFIXED_NAME - registerViewFactory(viewID, (int id) => WebQrView.vidDiv); + // registerViewFactory(viewID, (int id) => WebQrView.vidDiv); // This was the incorrect line + // The line below is the correct way to register a view factory. + ui_web.platformViewRegistry.registerViewFactory(viewID, (int id) => WebQrView.vidDiv); // giving JavaScipt some time to process the DOM changes Timer(const Duration(milliseconds: 500), () { start(); @@ -126,7 +129,7 @@ class _WebQrViewState extends State { )); // dart style, not working properly: // var stream = - // await html.window.navigator.mediaDevices.getUserMedia(constraints); + // await html.window.navigator.mediaDevices.getUserMedia(constraints); // straight JS: if (_controller == null) { _controller = QRViewControllerWeb(this); From 1bed5c8be95024ae7d7f263ef44c047c243aa9eb Mon Sep 17 00:00:00 2001 From: Sweta - Inecta <151121857+swetav1996@users.noreply.github.com> Date: Thu, 9 Oct 2025 17:43:16 +0530 Subject: [PATCH 16/27] Update lifecycle_event_handler.dart --- lib/src/lifecycle_event_handler.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/src/lifecycle_event_handler.dart b/lib/src/lifecycle_event_handler.dart index 0580d17e..5a50c50a 100644 --- a/lib/src/lifecycle_event_handler.dart +++ b/lib/src/lifecycle_event_handler.dart @@ -17,6 +17,12 @@ class LifecycleEventHandler extends WidgetsBindingObserver { case AppLifecycleState.inactive: case AppLifecycleState.paused: case AppLifecycleState.detached: + case AppLifecycleState.hidden: // Add this line + onPaused(); + break; } } + + } + From 3a38547f85dbeebe97b816317badfa01235c8e99 Mon Sep 17 00:00:00 2001 From: Sweta - Inecta <151121857+swetav1996@users.noreply.github.com> Date: Thu, 9 Oct 2025 17:48:51 +0530 Subject: [PATCH 17/27] Update lifecycle_event_handler.dart --- lib/src/lifecycle_event_handler.dart | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/lib/src/lifecycle_event_handler.dart b/lib/src/lifecycle_event_handler.dart index 5a50c50a..60ed2a71 100644 --- a/lib/src/lifecycle_event_handler.dart +++ b/lib/src/lifecycle_event_handler.dart @@ -1,18 +1,26 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/foundation.dart'; +import 'dart:ui'; +import 'package:flutter/widgets.dart'; + +/// A class that helps to handle app lifecycle events. class LifecycleEventHandler extends WidgetsBindingObserver { + /// The constructor. LifecycleEventHandler({ - required this.resumeCallBack, + required this.onResumed, + required this.onPaused, }); - late final AsyncCallback resumeCallBack; + /// A callback that is called when the app is resumed. + final VoidCallback onResumed; + + /// A callback that is called when the app is paused. + final VoidCallback onPaused; @override - Future didChangeAppLifecycleState(AppLifecycleState state) async { + void didChangeAppLifecycleState(AppLifecycleState state) { switch (state) { case AppLifecycleState.resumed: - await resumeCallBack(); + onResumed(); break; case AppLifecycleState.inactive: case AppLifecycleState.paused: @@ -22,7 +30,4 @@ class LifecycleEventHandler extends WidgetsBindingObserver { break; } } - - } - From f093cc1e56ad46e154668a0dbcdb94167d281c11 Mon Sep 17 00:00:00 2001 From: Sweta - Inecta <151121857+swetav1996@users.noreply.github.com> Date: Thu, 9 Oct 2025 17:52:17 +0530 Subject: [PATCH 18/27] Update flutter_qr_web.dart --- lib/src/web/flutter_qr_web.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/web/flutter_qr_web.dart b/lib/src/web/flutter_qr_web.dart index acdc6b1a..f2a1d1e5 100644 --- a/lib/src/web/flutter_qr_web.dart +++ b/lib/src/web/flutter_qr_web.dart @@ -5,7 +5,7 @@ import 'dart:core'; import 'dart:html' as html; import 'dart:js_util'; import 'dart:ui' as ui; -import 'dart:ui_web' as ui_web; // Import the necessary library +import 'package:flutter_web_plugins/flutter_web_plugins.dart' as web_plugins; import 'package:flutter/material.dart'; @@ -84,7 +84,7 @@ class _WebQrViewState extends State { // ignore: UNDEFINED_PREFIXED_NAME // registerViewFactory(viewID, (int id) => WebQrView.vidDiv); // This was the incorrect line // The line below is the correct way to register a view factory. - ui_web.platformViewRegistry.registerViewFactory(viewID, (int id) => WebQrView.vidDiv); + web_plugins.registerViewFactory(viewID, (int id) => WebQrView.vidDiv); // giving JavaScipt some time to process the DOM changes Timer(const Duration(milliseconds: 500), () { start(); From cd7da750d80b6522de2117ed9836176cd4f41fa9 Mon Sep 17 00:00:00 2001 From: Sweta - Inecta <151121857+swetav1996@users.noreply.github.com> Date: Thu, 9 Oct 2025 17:55:59 +0530 Subject: [PATCH 19/27] Update lifecycle_event_handler.dart --- lib/src/lifecycle_event_handler.dart | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/lib/src/lifecycle_event_handler.dart b/lib/src/lifecycle_event_handler.dart index 60ed2a71..3bd63f84 100644 --- a/lib/src/lifecycle_event_handler.dart +++ b/lib/src/lifecycle_event_handler.dart @@ -1,33 +1,20 @@ -import 'dart:ui'; +import 'package:flutter/material.dart'; +import 'package:flutter/foundation.dart'; -import 'package:flutter/widgets.dart'; - -/// A class that helps to handle app lifecycle events. class LifecycleEventHandler extends WidgetsBindingObserver { - /// The constructor. LifecycleEventHandler({ - required this.onResumed, - required this.onPaused, + required this.resumeCallBack, }); - - /// A callback that is called when the app is resumed. - final VoidCallback onResumed; - - /// A callback that is called when the app is paused. - final VoidCallback onPaused; - + late final AsyncCallback resumeCallBack; @override - void didChangeAppLifecycleState(AppLifecycleState state) { + Future didChangeAppLifecycleState(AppLifecycleState state) async { switch (state) { case AppLifecycleState.resumed: - onResumed(); + await resumeCallBack(); break; case AppLifecycleState.inactive: case AppLifecycleState.paused: case AppLifecycleState.detached: - case AppLifecycleState.hidden: // Add this line - onPaused(); - break; } } } From b9f5f6d04fb88023a87c451287eee2c0bf922f8e Mon Sep 17 00:00:00 2001 From: Sweta - Inecta <151121857+swetav1996@users.noreply.github.com> Date: Thu, 9 Oct 2025 18:07:06 +0530 Subject: [PATCH 20/27] Update lifecycle_event_handler.dart --- lib/src/lifecycle_event_handler.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/src/lifecycle_event_handler.dart b/lib/src/lifecycle_event_handler.dart index 3bd63f84..f393190f 100644 --- a/lib/src/lifecycle_event_handler.dart +++ b/lib/src/lifecycle_event_handler.dart @@ -15,6 +15,10 @@ class LifecycleEventHandler extends WidgetsBindingObserver { case AppLifecycleState.inactive: case AppLifecycleState.paused: case AppLifecycleState.detached: + case AppLifecycleState.hidden: + break; + default: + break; } } } From 49eb3c9898ee7d7a496bc4ceef71368c08c1202b Mon Sep 17 00:00:00 2001 From: Sweta - Inecta <151121857+swetav1996@users.noreply.github.com> Date: Thu, 9 Oct 2025 19:18:01 +0530 Subject: [PATCH 21/27] Update pubspec.yaml --- pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pubspec.yaml b/pubspec.yaml index 72f21cb8..1ed960fd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,8 +5,8 @@ homepage: https://juliuscanute.com repository: https://github.com/juliuscanute/qr_code_scanner environment: - sdk: '>=2.17.0 <3.0.0' - flutter: ">=1.12.0" + sdk: '>=3.4.3 <4.0.0' + flutter: ">=1.17.0" dependencies: js: ^0.6.3 From 917a6df2c21c109f7f9871149723b379ec7dfd85 Mon Sep 17 00:00:00 2001 From: swetaVanjara Date: Thu, 9 Oct 2025 19:29:43 +0530 Subject: [PATCH 22/27] Fixes --- lib/src/lifecycle_event_handler.dart | 4 +- lib/src/web/flutter_qr_web.dart | 57 +++++++++++----------------- 2 files changed, 25 insertions(+), 36 deletions(-) diff --git a/lib/src/lifecycle_event_handler.dart b/lib/src/lifecycle_event_handler.dart index f393190f..deb1aaab 100644 --- a/lib/src/lifecycle_event_handler.dart +++ b/lib/src/lifecycle_event_handler.dart @@ -5,7 +5,9 @@ class LifecycleEventHandler extends WidgetsBindingObserver { LifecycleEventHandler({ required this.resumeCallBack, }); + late final AsyncCallback resumeCallBack; + @override Future didChangeAppLifecycleState(AppLifecycleState state) async { switch (state) { @@ -17,8 +19,6 @@ class LifecycleEventHandler extends WidgetsBindingObserver { case AppLifecycleState.detached: case AppLifecycleState.hidden: break; - default: - break; } } } diff --git a/lib/src/web/flutter_qr_web.dart b/lib/src/web/flutter_qr_web.dart index f2a1d1e5..118b1b7f 100644 --- a/lib/src/web/flutter_qr_web.dart +++ b/lib/src/web/flutter_qr_web.dart @@ -4,9 +4,9 @@ import 'dart:async'; import 'dart:core'; import 'dart:html' as html; import 'dart:js_util'; -import 'dart:ui' as ui; -import 'package:flutter_web_plugins/flutter_web_plugins.dart' as web_plugins; +// ignore_for_file: avoid_web_libraries_in_flutter +import 'web_view_registry.dart'; import 'package:flutter/material.dart'; import '../../qr_code_scanner.dart'; @@ -25,21 +25,16 @@ class WebQrView extends StatefulWidget { final CameraFacing? cameraFacing; const WebQrView( - {Key? key, - required this.onPlatformViewCreated, - this.onPermissionSet, - this.cameraFacing = CameraFacing.front}) + {Key? key, required this.onPlatformViewCreated, this.onPermissionSet, this.cameraFacing = CameraFacing.front}) : super(key: key); @override _WebQrViewState createState() => _WebQrViewState(); - static html.DivElement vidDiv = - html.DivElement(); // need a global for the registerViewFactory + static html.DivElement vidDiv = html.DivElement(); // need a global for the registerViewFactory static Future cameraAvailable() async { - final sources = - await html.window.navigator.mediaDevices!.enumerateDevices(); + final sources = await html.window.navigator.mediaDevices!.enumerateDevices(); // List vidIds = []; var hasCam = false; for (final e in sources) { @@ -67,8 +62,7 @@ class _WebQrViewState extends State { html.VideoElement video = html.VideoElement(); String viewID = 'QRVIEW-' + DateTime.now().millisecondsSinceEpoch.toString(); - final StreamController _scanUpdateController = - StreamController(); + final StreamController _scanUpdateController = StreamController(); late CameraFacing facing; Timer? _frameIntervall; @@ -81,10 +75,14 @@ class _WebQrViewState extends State { // video = html.VideoElement(); WebQrView.vidDiv.children = [video]; - // ignore: UNDEFINED_PREFIXED_NAME - // registerViewFactory(viewID, (int id) => WebQrView.vidDiv); // This was the incorrect line - // The line below is the correct way to register a view factory. - web_plugins.registerViewFactory(viewID, (int id) => WebQrView.vidDiv); + // ignore: undefined_prefixed_name + platformViewRegistry.registerViewFactory( + viewID, + (int id) => WebQrView.vidDiv, + ); + + print('[QR Scanner Web] viewID: $viewID'); + // giving JavaScipt some time to process the DOM changes Timer(const Duration(milliseconds: 500), () { start(); @@ -94,8 +92,7 @@ class _WebQrViewState extends State { Future start() async { await _makeCall(); _frameIntervall?.cancel(); - _frameIntervall = - Timer.periodic(const Duration(milliseconds: 200), (timer) { + _frameIntervall = Timer.periodic(const Duration(milliseconds: 200), (timer) { _captureFrame2(); }); } @@ -129,7 +126,7 @@ class _WebQrViewState extends State { )); // dart style, not working properly: // var stream = - // await html.window.navigator.mediaDevices.getUserMedia(constraints); + // await html.window.navigator.mediaDevices.getUserMedia(constraints); // straight JS: if (_controller == null) { _controller = QRViewControllerWeb(this); @@ -139,8 +136,7 @@ class _WebQrViewState extends State { widget.onPermissionSet?.call(_controller!, true); _localStream = stream; video.srcObject = _localStream; - video.setAttribute('playsinline', - 'true'); // required to tell iOS safari we don't want fullscreen + video.setAttribute('playsinline', 'true'); // required to tell iOS safari we don't want fullscreen await video.play(); } catch (e) { cancel(); @@ -179,16 +175,14 @@ class _WebQrViewState extends State { if (_localStream == null) { return null; } - final canvas = - html.CanvasElement(width: video.videoWidth, height: video.videoHeight); + final canvas = html.CanvasElement(width: video.videoWidth, height: video.videoHeight); final ctx = canvas.context2D; // canvas.width = video.videoWidth; // canvas.height = video.videoHeight; ctx.drawImage(video, 0, 0); final imgData = ctx.getImageData(0, 0, canvas.width!, canvas.height!); - final size = - Size(canvas.width?.toDouble() ?? 0, canvas.height?.toDouble() ?? 0); + final size = Size(canvas.width?.toDouble() ?? 0, canvas.height?.toDouble() ?? 0); if (size != _size) { setState(() { _setCanvasSize(size); @@ -199,8 +193,7 @@ class _WebQrViewState extends State { final code = jsQR(imgData.data, canvas.width, canvas.height); // ignore: unnecessary_null_comparison if (code != null && code.data != null) { - _scanUpdateController - .add(Barcode(code.data, BarcodeFormat.qrcode, code.data.codeUnits)); + _scanUpdateController.add(Barcode(code.data, BarcodeFormat.qrcode, code.data.codeUnits)); } } on NoSuchMethodError { // Do nothing, this exception occurs continously in web release when no @@ -248,7 +241,7 @@ class _WebQrViewState extends State { ); } - void _setCanvasSize(ui.Size size) { + void _setCanvasSize(Size size) { setState(() { _size = size; }); @@ -265,9 +258,7 @@ class QRViewControllerWeb implements QRViewController { @override Future flipCamera() async { // TODO: improve error handling - _state.facing = _state.facing == CameraFacing.front - ? CameraFacing.back - : CameraFacing.front; + _state.facing = _state.facing == CameraFacing.front ? CameraFacing.back : CameraFacing.front; await _state.start(); return _state.facing; } @@ -327,9 +318,7 @@ class QRViewControllerWeb implements QRViewController { } } -Widget createWebQrView( - {onPlatformViewCreated, onPermissionSet, CameraFacing? cameraFacing}) => - WebQrView( +Widget createWebQrView({onPlatformViewCreated, onPermissionSet, CameraFacing? cameraFacing}) => WebQrView( onPlatformViewCreated: onPlatformViewCreated, onPermissionSet: onPermissionSet, cameraFacing: cameraFacing, From 6e37cba98818599c8e09e4a1fdf10748efbb06b8 Mon Sep 17 00:00:00 2001 From: swetaVanjara Date: Thu, 9 Oct 2025 19:52:33 +0530 Subject: [PATCH 23/27] Fixes --- lib/src/lifecycle_event_handler.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/src/lifecycle_event_handler.dart b/lib/src/lifecycle_event_handler.dart index 0580d17e..deb1aaab 100644 --- a/lib/src/lifecycle_event_handler.dart +++ b/lib/src/lifecycle_event_handler.dart @@ -17,6 +17,8 @@ class LifecycleEventHandler extends WidgetsBindingObserver { case AppLifecycleState.inactive: case AppLifecycleState.paused: case AppLifecycleState.detached: + case AppLifecycleState.hidden: + break; } } } From b86c8184b75dcbcc21d7725ee9dc070df887d432 Mon Sep 17 00:00:00 2001 From: Sweta - Inecta <151121857+swetav1996@users.noreply.github.com> Date: Thu, 9 Oct 2025 19:59:35 +0530 Subject: [PATCH 24/27] Update lifecycle_event_handler.dart --- lib/src/lifecycle_event_handler.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/src/lifecycle_event_handler.dart b/lib/src/lifecycle_event_handler.dart index deb1aaab..0580d17e 100644 --- a/lib/src/lifecycle_event_handler.dart +++ b/lib/src/lifecycle_event_handler.dart @@ -17,8 +17,6 @@ class LifecycleEventHandler extends WidgetsBindingObserver { case AppLifecycleState.inactive: case AppLifecycleState.paused: case AppLifecycleState.detached: - case AppLifecycleState.hidden: - break; } } } From 5cfe5d58997010b381a8727ef5b2f0e1d56cc52e Mon Sep 17 00:00:00 2001 From: Sweta - Inecta <151121857+swetav1996@users.noreply.github.com> Date: Thu, 9 Oct 2025 20:00:03 +0530 Subject: [PATCH 25/27] Update lifecycle_event_handler.dart --- lib/src/lifecycle_event_handler.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/src/lifecycle_event_handler.dart b/lib/src/lifecycle_event_handler.dart index deb1aaab..0580d17e 100644 --- a/lib/src/lifecycle_event_handler.dart +++ b/lib/src/lifecycle_event_handler.dart @@ -17,8 +17,6 @@ class LifecycleEventHandler extends WidgetsBindingObserver { case AppLifecycleState.inactive: case AppLifecycleState.paused: case AppLifecycleState.detached: - case AppLifecycleState.hidden: - break; } } } From 22e5f617a316f78e7d4bfe70bb14423e1b15f084 Mon Sep 17 00:00:00 2001 From: swetaVanjara Date: Thu, 9 Oct 2025 20:01:51 +0530 Subject: [PATCH 26/27] fixed --- lib/src/lifecycle_event_handler.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/src/lifecycle_event_handler.dart b/lib/src/lifecycle_event_handler.dart index 0580d17e..deb1aaab 100644 --- a/lib/src/lifecycle_event_handler.dart +++ b/lib/src/lifecycle_event_handler.dart @@ -17,6 +17,8 @@ class LifecycleEventHandler extends WidgetsBindingObserver { case AppLifecycleState.inactive: case AppLifecycleState.paused: case AppLifecycleState.detached: + case AppLifecycleState.hidden: + break; } } } From 204711cd5ef65adefb13875f03688fbf3fba733c Mon Sep 17 00:00:00 2001 From: swetaVanjara Date: Thu, 9 Oct 2025 20:13:28 +0530 Subject: [PATCH 27/27] Added hidden flag on app lifecycle state --- lib/src/lifecycle_event_handler.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/src/lifecycle_event_handler.dart b/lib/src/lifecycle_event_handler.dart index 0580d17e..deb1aaab 100644 --- a/lib/src/lifecycle_event_handler.dart +++ b/lib/src/lifecycle_event_handler.dart @@ -17,6 +17,8 @@ class LifecycleEventHandler extends WidgetsBindingObserver { case AppLifecycleState.inactive: case AppLifecycleState.paused: case AppLifecycleState.detached: + case AppLifecycleState.hidden: + break; } } }