Fix QR scanner to accept fountain coding for BC-UR codes (#3048)

* fix: use fountain decoder to determine UR scanning progress * fix: use fountain encoder for cupcake * fix build * fix crash * revert encoder changes

Hector Chu committed Mar 13, 2026 at 22:11 UTC 1520ba8e58a53d1966d41cb229b712b5a7660b3d
1 file changed +10 -7
lib/entities/qr_scanner.dart
+10 -7
@@ -7,6 +7,7 @@ import 'package:cw_core/utils/print_verbose.dart';
7 import 'package:fast_scanner/fast_scanner.dart';
8 import 'package:flutter/material.dart';
9 import 'package:flutter/scheduler.dart';
10 +import 'package:ur/ur_decoder.dart';
11
12 var isQrScannerShown = false;
13
@@ -42,6 +43,7 @@ class _BarcodeScannerSimpleState extends State<BarcodeScannerSimple> {
43
44 List<String> urCodes = [];
45 late var ur = URQRToURQRData(urCodes);
46 + final decoder = URDecoder();
47
48 void _handleBarcode(BarcodeCapture barcodes) {
49 try {
@@ -70,11 +72,12 @@ class _BarcodeScannerSimpleState extends State<BarcodeScannerSimple> {
72 if (barcode.rawValue?.trim().isEmpty ?? false == false) continue;
73 if (barcode.rawValue!.startsWith("ur:")) {
74 if (urCodes.contains(barcode.rawValue)) continue;
75 + decoder.receivePart(barcode.rawValue!);
76 setState(() {
77 urCodes.add(barcode.rawValue!);
78 ur = URQRToURQRData(urCodes);
79 });
77 - if (ur.progress == 1) {
80 + if (decoder.estimatedPercentComplete() == 1) {
81 setState(() {
82 popped = true;
83 });
@@ -118,10 +121,10 @@ class _BarcodeScannerSimpleState extends State<BarcodeScannerSimple> {
121 onDetect: _handleBarcode,
122 controller: ctrl,
123 ),
121 - if (ur.inputs.length != 0)
124 + if (decoder.expectedPartCount() != null)
125 Center(
126 child: Text(
124 - "${ur.inputs.length}/${ur.count}",
127 + "${decoder.processedPartsCount()}/${decoder.expectedPartCount()!}",
128 style: Theme.of(context)
129 .textTheme
130 .displayLarge
@@ -136,10 +139,10 @@ class _BarcodeScannerSimpleState extends State<BarcodeScannerSimple> {
139 child: CustomPaint(
140 painter: ProgressPainter(
141 urQrProgress: URQrProgress(
139 - expectedPartCount: ur.count - 1,
140 - processedPartsCount: ur.inputs.length,
141 - receivedPartIndexes: _urParts(),
142 - percentage: ur.progress,
142 + expectedPartCount: decoder.expectedPartCount() ?? 0,
143 + processedPartsCount: decoder.processedPartsCount(),
144 + receivedPartIndexes: decoder.receivedPartIndexes().toList(),
145 + percentage: decoder.estimatedPercentComplete(),
146 ),
147 ),
148 ),