From 985b25e339e81b8121db891864a572582c00f708 Mon Sep 17 00:00:00 2001
From: Navaron Bracke <brackenavaron@gmail.com>
Date: Wed, 6 Mar 2024 13:17:13 +0100
Subject: [PATCH] port scan window update fix to the new beta release

---
 CHANGELOG.md                |  5 +++
 lib/src/mobile_scanner.dart | 64 +++++++++++++++++++++++++++++++++----
 2 files changed, 62 insertions(+), 7 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 27562c9fb..9cc503244 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## NEXT
+
+Bugs fixed:
+* Fixed an issue where the scan window was not updated when its size was changed. (thanks @navaronbracke !)
+
 ## 5.0.0-beta.1
 
 **BREAKING CHANGES:**
diff --git a/lib/src/mobile_scanner.dart b/lib/src/mobile_scanner.dart
index c3d59d498..286e207e6 100644
--- a/lib/src/mobile_scanner.dart
+++ b/lib/src/mobile_scanner.dart
@@ -24,6 +24,7 @@ class MobileScanner extends StatefulWidget {
     this.overlayBuilder,
     this.placeholderBuilder,
     this.scanWindow,
+    this.scanWindowUpdateThreshold = 0.0,
     super.key,
   });
 
@@ -94,6 +95,19 @@ class MobileScanner extends StatefulWidget {
   /// ```
   final Rect? scanWindow;
 
+  /// The threshold for updates to the [scanWindow].
+  ///
+  /// If the [scanWindow] would be updated,
+  /// due to new layout constraints for the scanner,
+  /// and the width or height of the new scan window have not changed by this threshold,
+  /// then the scan window is not updated.
+  ///
+  /// It is recommended to set this threshold
+  /// if scan window updates cause performance issues.
+  ///
+  /// Defaults to no threshold for scan window updates.
+  final double scanWindowUpdateThreshold;
+
   @override
   State<MobileScanner> createState() => _MobileScannerState();
 }
@@ -109,13 +123,49 @@ class _MobileScannerState extends State<MobileScanner> {
     MobileScannerState scannerState,
     BoxConstraints constraints,
   ) {
-    if (widget.scanWindow != null && scanWindow == null) {
-      scanWindow = calculateScanWindowRelativeToTextureInPercentage(
-        widget.fit,
-        widget.scanWindow!,
-        textureSize: scannerState.size,
-        widgetSize: constraints.biggest,
-      );
+    if (widget.scanWindow == null) {
+      return;
+    }
+
+    final Rect newScanWindow = calculateScanWindowRelativeToTextureInPercentage(
+      widget.fit,
+      widget.scanWindow!,
+      textureSize: scannerState.size,
+      widgetSize: constraints.biggest,
+    );
+
+    // The scan window was never set before.
+    // Set the initial scan window.
+    if (scanWindow == null) {
+      scanWindow = newScanWindow;
+
+      unawaited(widget.controller.updateScanWindow(scanWindow));
+
+      return;
+    }
+
+    // The scan window did not not change.
+    // The left, right, top and bottom are the same.
+    if (scanWindow == newScanWindow) {
+      return;
+    }
+
+    // The update threshold is not set, allow updating the scan window.
+    if (widget.scanWindowUpdateThreshold == 0.0) {
+      scanWindow = newScanWindow;
+
+      unawaited(widget.controller.updateScanWindow(scanWindow));
+
+      return;
+    }
+
+    final double dx = (newScanWindow.width - scanWindow!.width).abs();
+    final double dy = (newScanWindow.height - scanWindow!.height).abs();
+
+    // The new scan window has changed enough, allow updating the scan window.
+    if (dx >= widget.scanWindowUpdateThreshold ||
+        dy >= widget.scanWindowUpdateThreshold) {
+      scanWindow = newScanWindow;
 
       unawaited(widget.controller.updateScanWindow(scanWindow));
     }