Browse Source

allow to change multi scan mode,

allow to change camera
pull/82/head
Khoren Markosyan 2 years ago
parent
commit
3ef3e587c9
  1. 23
      example/lib/main.dart
  2. 31
      example/lib/widgets/debug_info_widget.dart
  3. 43
      example/lib/widgets/scan_from_gallery_widget.dart
  4. 46
      example/pubspec.lock
  5. 3
      example/pubspec.yaml
  6. 6
      lib/flutter_zxing.dart
  7. 10
      lib/src/logic/barcode_reader.dart
  8. 6
      lib/src/logic/barcodes_reader.dart
  9. 20
      lib/src/models/code.dart
  10. 157
      lib/src/ui/reader_widget.dart
  11. 32
      lib/src/ui/scan_mode_dropdown.dart
  12. 18
      lib/src/utils/extentions.dart
  13. 6
      lib/zxing_mobile.dart
  14. 6
      lib/zxing_web.dart
  15. 1
      pubspec.yaml
  16. 4
      src/native_zxing.cpp
  17. 2
      src/zxing
  18. 408
      zxscanner/pubspec.lock

23
example/lib/main.dart

@ -3,8 +3,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_zxing/flutter_zxing.dart';
import 'widgets/debug_info_widget.dart';
import 'widgets/scan_from_gallery_widget.dart';
import 'widgets/scan_mode_dropdown.dart';
import 'widgets/scan_result_widget.dart';
import 'widgets/unsupported_platform_widget.dart';
@ -86,24 +84,13 @@ class _DemoPageState extends State<DemoPage> {
onScanFailure: _onScanFailure,
onMultiScan: _onMultiScanSuccess,
onMultiScanFailure: _onMultiScanFailure,
onMultiScanModeChanged: _onMultiScanModeChanged,
isMultiScan: isMultiScan,
scanDelay: isMultiScan
? Duration.zero
: const Duration(milliseconds: 500),
tryInverted: true,
),
ScanFromGalleryWidget(
onScan: _onScanSuccess,
onScanFailure: _onScanFailure,
),
// Change single/multi scan mode dropdown button
ScanModeDropdown(
isMultiScan: isMultiScan,
onChanged: (value) {
setState(() {
isMultiScan = value;
});
},
actionButtonsAlignment: Alignment.bottomLeft,
),
if (showDebugInfo)
DebugInfoWidget(
@ -192,4 +179,10 @@ class _DemoPageState extends State<DemoPage> {
failedScans = 0;
});
}
_onMultiScanModeChanged(bool isMultiScan) {
setState(() {
this.isMultiScan = isMultiScan;
});
}
}

31
example/lib/widgets/debug_info_widget.dart

@ -19,22 +19,37 @@ class DebugInfoWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
TextStyle? style =
Theme.of(context).textTheme.bodySmall?.copyWith(color: Colors.white);
return Align(
alignment: Alignment.topLeft,
alignment: Alignment.topCenter,
child: Padding(
padding: const EdgeInsets.all(8.0),
padding: const EdgeInsets.all(10.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Container(
color: Colors.white.withOpacity(0.7),
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
child: Column(
color: Colors.black54,
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'Success: $successScans\nFailed: $failedScans\nDuration: $duration ms',
style: Theme.of(context).textTheme.bodySmall,
Flexible(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Success: $successScans', style: style),
const SizedBox(width: 10),
Text('Failed: $failedScans', style: style),
const SizedBox(width: 10),
Text('Duration: $duration ms', style: style),
],
),
),
),
const SizedBox(width: 10),
TextButton(
onPressed: onReset,
child: const Text('Reset'),

43
example/lib/widgets/scan_from_gallery_widget.dart

@ -1,43 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_zxing/flutter_zxing.dart';
import 'package:image_picker/image_picker.dart';
class ScanFromGalleryWidget extends StatelessWidget {
const ScanFromGalleryWidget({
Key? key,
this.onScan,
this.onScanFailure,
}) : super(key: key);
final Function(Code)? onScan;
final Function(Code?)? onScanFailure;
@override
Widget build(BuildContext context) {
return Positioned(
bottom: 20,
right: 20,
child: FloatingActionButton(
onPressed: _onFromGalleryButtonTapped,
child: const Icon(Icons.image),
),
);
}
void _onFromGalleryButtonTapped() async {
final XFile? file =
await ImagePicker().pickImage(source: ImageSource.gallery);
if (file != null) {
final Code? result = await zx.readBarcodeImagePath(
file,
params: DecodeParams(tryInverted: true),
);
if (result != null && result.isValid) {
onScan?.call(result);
} else {
result?.error = 'No barcode found';
onScanFailure?.call(result);
}
}
}
}

46
example/pubspec.lock

@ -5,10 +5,10 @@ packages:
dependency: transitive
description:
name: archive
sha256: ed7cc591a948744994714375caf9a2ce89e1d82e8243997c8a2994d57181c212
sha256: d6347d54a2d8028e0437e3c099f66fdb8ae02c4720c1e7534c9f24c10351f85d
url: "https://pub.dev"
source: hosted
version: "3.3.5"
version: "3.3.6"
async:
dependency: transitive
description:
@ -29,34 +29,34 @@ packages:
dependency: transitive
description:
name: camera
sha256: "045e7739f9362f3c01d5c7187ac7e2ba9e2bc9f2ae6470ecdcc5e34d060ed81c"
sha256: e7ac55af24a890d20276821eb3c95857074d03b7de6f9892b99a205ee30bd179
url: "https://pub.dev"
source: hosted
version: "0.10.2+1"
version: "0.10.3"
camera_android:
dependency: transitive
description:
name: camera_android
sha256: "417e9eddda8025d7342f82ee53b214f149793e95c8490c3440a46144409f7966"
sha256: e491c836147f60dd8a54cf3895fd2960e13b21b78a9d15b563a1b6c70894f142
url: "https://pub.dev"
source: hosted
version: "0.10.2+3"
version: "0.10.4"
camera_avfoundation:
dependency: transitive
description:
name: camera_avfoundation
sha256: eeda6a7947b1f7c47395c4459342d1e6866014186449e141a251f0549aba0c8b
sha256: "6a68c20593d4cd58974d555f74a48b244f9db28cc9156de57781122d11b8754b"
url: "https://pub.dev"
source: hosted
version: "0.9.10+2"
version: "0.9.11"
camera_platform_interface:
dependency: transitive
description:
name: camera_platform_interface
sha256: "0eedd642d905ca24f1c483fe9ea0d0e7287b86a402845c28d24df28cc7b0ee6e"
sha256: b632be28e61d00a233f67d98ea90fd7041956f27a1c65500188ee459be60e15f
url: "https://pub.dev"
source: hosted
version: "2.3.4"
version: "2.4.0"
camera_web:
dependency: transitive
description:
@ -101,10 +101,10 @@ packages:
dependency: transitive
description:
name: cross_file
sha256: f71079978789bc2fe78d79227f1f8cfe195b31bbd8db2399b0d15a4b96fb843b
sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9"
url: "https://pub.dev"
source: hosted
version: "0.3.3+2"
version: "0.3.3+4"
crypto:
dependency: transitive
description:
@ -167,14 +167,6 @@ packages:
relative: true
source: path
version: "1.0.0"
font_awesome_flutter:
dependency: "direct main"
description:
name: font_awesome_flutter
sha256: "875dbb9ec1ad30d68102019ceb682760d06c72747c1c5b7885781b95f88569cc"
url: "https://pub.dev"
source: hosted
version: "10.3.0"
http:
dependency: transitive
description:
@ -192,7 +184,7 @@ packages:
source: hosted
version: "4.0.2"
image:
dependency: "direct main"
dependency: transitive
description:
name: image
sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6"
@ -200,7 +192,7 @@ packages:
source: hosted
version: "3.3.0"
image_picker:
dependency: "direct main"
dependency: transitive
description:
name: image_picker
sha256: f98d76672d309c8b7030c323b3394669e122d52b307d2bbd8d06bd70f5b2aabe
@ -211,10 +203,10 @@ packages:
dependency: transitive
description:
name: image_picker_android
sha256: b1cbfec0f5aef427a18eb573f5445af8c9c568626bf3388553e40c263d3f7368
sha256: "385f12ee9c7288575572c7873a332016ec45ebd092e1c2f6bd421b4a9ad21f1d"
url: "https://pub.dev"
source: hosted
version: "0.8.5+5"
version: "0.8.5+6"
image_picker_for_web:
dependency: transitive
description:
@ -227,10 +219,10 @@ packages:
dependency: transitive
description:
name: image_picker_ios
sha256: "39c013200046d14c58b71dc4fa3d00e425fc9c699d589136cd3ca018727c0493"
sha256: "8ffb14b43713d7c43fb21299cc18181cc5b39bd3ea1cc427a085c6400fe5aa52"
url: "https://pub.dev"
source: hosted
version: "0.8.6+6"
version: "0.8.6+7"
image_picker_platform_interface:
dependency: transitive
description:
@ -405,5 +397,5 @@ packages:
source: hosted
version: "6.2.2"
sdks:
dart: ">=2.18.0 <4.0.0"
dart: ">=2.18.0 <3.0.0"
flutter: ">=3.3.0"

3
example/pubspec.yaml

@ -11,9 +11,6 @@ dependencies:
sdk: flutter
flutter_zxing:
path: ../
font_awesome_flutter: ^10.3.0
image: ^3.3.0
image_picker: ^0.8.6
dev_dependencies:
flutter_lints: ^2.0.1

6
lib/flutter_zxing.dart

@ -45,19 +45,19 @@ abstract class Zxing {
});
/// Reads barcode from String image path
Future<Code?> readBarcodeImagePathString(
Future<Code> readBarcodeImagePathString(
String path, {
DecodeParams? params,
});
/// Reads barcode from XFile image path
Future<Code?> readBarcodeImagePath(
Future<Code> readBarcodeImagePath(
XFile path, {
DecodeParams? params,
});
/// Reads barcode from image url
Future<Code?> readBarcodeImageUrl(
Future<Code> readBarcodeImageUrl(
String url, {
DecodeParams? params,
});

10
lib/src/logic/barcode_reader.dart

@ -1,7 +1,7 @@
part of 'zxing.dart';
/// Reads barcode from String image path
Future<Code?> zxingReadBarcodeImagePathString(
Future<Code> zxingReadBarcodeImagePathString(
String path, {
DecodeParams? params,
}) =>
@ -11,14 +11,14 @@ Future<Code?> zxingReadBarcodeImagePathString(
);
/// Reads barcode from XFile image path
Future<Code?> zxingReadBarcodeImagePath(
Future<Code> zxingReadBarcodeImagePath(
XFile path, {
DecodeParams? params,
}) async {
final Uint8List imageBytes = await path.readAsBytes();
imglib.Image? image = imglib.decodeImage(imageBytes);
if (image == null) {
return null;
return Code();
}
image = resizeToMaxSize(image, params?.maxSize);
return zxingReadBarcode(
@ -30,7 +30,7 @@ Future<Code?> zxingReadBarcodeImagePath(
}
/// Reads barcode from image url
Future<Code?> zxingReadBarcodeImageUrl(
Future<Code> zxingReadBarcodeImageUrl(
String url, {
DecodeParams? params,
}) async {
@ -38,7 +38,7 @@ Future<Code?> zxingReadBarcodeImageUrl(
(await NetworkAssetBundle(Uri.parse(url)).load(url)).buffer.asUint8List();
imglib.Image? image = imglib.decodeImage(imageBytes);
if (image == null) {
return null;
return Code(error: 'Failed to decode image');
}
image = resizeToMaxSize(image, params?.maxSize);
return zxingReadBarcode(

6
lib/src/logic/barcodes_reader.dart

@ -18,7 +18,7 @@ Future<Codes> zxingReadBarcodesImagePath(
final Uint8List imageBytes = await path.readAsBytes();
imglib.Image? image = imglib.decodeImage(imageBytes);
if (image == null) {
return Codes(<Code>[], 0);
return Codes();
}
image = resizeToMaxSize(image, params?.maxSize);
return zxingReadBarcodes(
@ -38,7 +38,7 @@ Future<Codes> zxingReadBarcodesImageUrl(
(await NetworkAssetBundle(Uri.parse(url)).load(url)).buffer.asUint8List();
imglib.Image? image = imglib.decodeImage(imageBytes);
if (image == null) {
return Codes(<Code>[], 0);
return Codes();
}
image = resizeToMaxSize(image, params?.maxSize);
return zxingReadBarcodes(
@ -80,5 +80,5 @@ Codes _readBarcodes(
for (int i = 0; i < result.count; i++) {
results.add(result.results.elementAt(i).ref.toCode());
}
return Codes(results, result.duration);
return Codes(codes: results, duration: result.duration);
}

20
lib/src/models/code.dart

@ -4,17 +4,17 @@ import 'position.dart';
// Represents a barcode code
class Code {
Code(
Code({
this.text,
this.isValid,
this.isValid = false,
this.error,
this.rawBytes,
this.format,
this.position,
this.isInverted,
this.isMirrored,
this.duration,
);
this.isInverted = false,
this.isMirrored = false,
this.duration = 0,
});
String? text; // The text of the code
bool isValid; // Whether the code is valid
@ -29,10 +29,10 @@ class Code {
// Represents a list of barcode codes
class Codes {
Codes(
this.codes,
this.duration,
);
Codes({
this.codes = const <Code>[],
this.duration = 0,
});
List<Code> codes; // The list of codes
int duration; // The duration of the decoding in milliseconds

157
lib/src/ui/reader_widget.dart

@ -4,8 +4,10 @@ import 'dart:math';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import '../../flutter_zxing.dart';
import 'scan_mode_dropdown.dart';
/// Widget to scan a code from the camera stream
class ReaderWidget extends StatefulWidget {
@ -16,13 +18,18 @@ class ReaderWidget extends StatefulWidget {
this.onMultiScan,
this.onMultiScanFailure,
this.onControllerCreated,
this.onMultiScanModeChanged,
this.isMultiScan = false,
this.codeFormat = Format.any,
this.tryHarder = false,
this.tryInverted = false,
this.showScannerOverlay = true,
this.scannerOverlay,
this.actionButtonsAlignment = Alignment.topCenter,
this.actionButtonsPadding = const EdgeInsets.all(10),
this.showFlashlight = true,
this.showToggleCamera = true,
this.showGallery = true,
this.allowPinchZoom = true,
this.scanDelay = const Duration(milliseconds: 1000),
this.scanDelaySuccess = const Duration(milliseconds: 1000),
@ -47,6 +54,9 @@ class ReaderWidget extends StatefulWidget {
/// Called when the camera controller is created
final Function(CameraController?)? onControllerCreated;
/// Called when the multi scan mode is changed
final Function(bool)? onMultiScanModeChanged;
/// Allow multiple scans
final bool isMultiScan;
@ -65,9 +75,21 @@ class ReaderWidget extends StatefulWidget {
/// Custom scanner overlay
final ScannerOverlay? scannerOverlay;
/// Align for action buttons
final AlignmentGeometry actionButtonsAlignment;
/// Padding for action buttons
final EdgeInsetsGeometry actionButtonsPadding;
/// Show flashlight button
final bool showFlashlight;
/// Show toggle camera
final bool showGallery;
/// Show toggle camera
final bool showToggleCamera;
/// Allow pinch zoom
final bool allowPinchZoom;
@ -93,6 +115,7 @@ class ReaderWidget extends StatefulWidget {
class _ReaderWidgetState extends State<ReaderWidget>
with TickerProviderStateMixin, WidgetsBindingObserver {
List<CameraDescription> cameras = <CameraDescription>[];
CameraDescription? selectedCamera;
CameraController? controller;
bool _cameraOn = false;
@ -106,12 +129,15 @@ class _ReaderWidgetState extends State<ReaderWidget>
// true when code detecting is ongoing
bool _isProcessing = false;
Codes results = Codes(<Code>[], 0);
bool isMultiScan = false;
Codes results = Codes();
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
isMultiScan = widget.isMultiScan;
initStateAsync();
}
@ -123,7 +149,8 @@ class _ReaderWidgetState extends State<ReaderWidget>
setState(() {
this.cameras = cameras;
if (cameras.isNotEmpty) {
onNewCameraSelected(cameras.first);
selectedCamera = cameras.first;
onNewCameraSelected(selectedCamera);
}
});
});
@ -171,7 +198,10 @@ class _ReaderWidgetState extends State<ReaderWidget>
}
}
Future<void> onNewCameraSelected(CameraDescription cameraDescription) async {
Future<void> onNewCameraSelected(CameraDescription? cameraDescription) async {
if (cameraDescription == null) {
return;
}
final CameraController? oldController = controller;
if (oldController != null) {
// controller?.removeListener(rebuildOnMount);
@ -235,7 +265,7 @@ class _ReaderWidgetState extends State<ReaderWidget>
await Future<void>.delayed(widget.scanDelaySuccess);
}
} else {
results = Codes(<Code>[], 0);
results = Codes();
widget.onMultiScanFailure?.call(result);
}
} else {
@ -327,45 +357,106 @@ class _ReaderWidgetState extends State<ReaderWidget>
controller?.setZoomLevel(_scaleFactor);
},
),
if (widget.showFlashlight && isCameraReady)
Positioned(
bottom: 20,
left: 20,
child: FloatingActionButton(
onPressed: () {
FlashMode mode = controller!.value.flashMode;
if (mode == FlashMode.torch) {
mode = FlashMode.off;
} else {
mode = FlashMode.torch;
}
controller?.setFlashMode(mode);
setState(() {});
},
backgroundColor: Colors.black26,
child: _FlashIcon(
flashMode: controller?.value.flashMode ?? FlashMode.off)),
Align(
alignment: widget.actionButtonsAlignment,
child: Padding(
padding: widget.actionButtonsPadding,
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Container(
color: Colors.black.withOpacity(0.5),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
if (widget.showFlashlight && isCameraReady)
IconButton(
onPressed: _onFlashButtonTapped,
color: Colors.white,
icon: Icon(
_flashIcon(
controller?.value.flashMode ?? FlashMode.off),
),
),
if (widget.showGallery && isCameraReady)
IconButton(
onPressed: _onGalleryButtonTapped,
color: Colors.white,
icon: const Icon(Icons.photo_library),
),
if (widget.showToggleCamera && isCameraReady)
IconButton(
onPressed: _onCameraButtonTapped,
color: Colors.white,
icon: const Icon(Icons.switch_camera),
),
],
),
),
),
),
),
ScanModeDropdown(
isMultiScan: isMultiScan,
onChanged: (bool value) {
setState(() {
isMultiScan = value;
});
widget.onMultiScanModeChanged?.call(value);
},
),
],
);
}
}
class _FlashIcon extends StatelessWidget {
const _FlashIcon({required this.flashMode});
final FlashMode flashMode;
void _onFlashButtonTapped() {
FlashMode mode = controller!.value.flashMode;
if (mode == FlashMode.torch) {
mode = FlashMode.off;
} else {
mode = FlashMode.torch;
}
controller?.setFlashMode(mode);
setState(() {});
}
@override
Widget build(BuildContext context) {
switch (flashMode) {
Future<void> _onGalleryButtonTapped() async {
final XFile? file =
await ImagePicker().pickImage(source: ImageSource.gallery);
if (file != null) {
final Code result = await zx.readBarcodeImagePath(
file,
params: DecodeParams(
format: widget.codeFormat,
tryHarder: widget.tryHarder,
tryInverted: widget.tryInverted,
isMultiScan: widget.isMultiScan,
),
);
if (result.isValid) {
widget.onScan?.call(result);
} else {
widget.onScanFailure?.call(result);
}
}
}
void _onCameraButtonTapped() {
final int cameraIndex = cameras.indexOf(controller!.description);
final int nextCameraIndex = (cameraIndex + 1) % cameras.length;
selectedCamera = cameras[nextCameraIndex];
onNewCameraSelected(selectedCamera);
}
IconData _flashIcon(FlashMode mode) {
switch (mode) {
case FlashMode.torch:
return const Icon(Icons.flash_on);
return Icons.flash_on;
case FlashMode.off:
return const Icon(Icons.flash_off);
return Icons.flash_off;
case FlashMode.always:
return const Icon(Icons.flash_on);
return Icons.flash_on;
case FlashMode.auto:
return const Icon(Icons.flash_auto);
return Icons.flash_auto;
}
}
}

32
example/lib/widgets/scan_mode_dropdown.dart → lib/src/ui/scan_mode_dropdown.dart

@ -2,10 +2,10 @@ import 'package:flutter/material.dart';
class ScanModeDropdown extends StatelessWidget {
const ScanModeDropdown({
Key? key,
super.key,
this.isMultiScan = false,
this.onChanged,
}) : super(key: key);
});
final bool isMultiScan;
final Function(bool value)? onChanged;
@ -13,30 +13,36 @@ class ScanModeDropdown extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Align(
alignment: Alignment.bottomCenter,
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.only(bottom: 20),
padding: const EdgeInsets.all(10),
child: Container(
height: 56,
padding: const EdgeInsets.symmetric(horizontal: 16),
padding: const EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
color: Colors.white,
color: Colors.black54,
borderRadius: BorderRadius.circular(10),
),
child: DropdownButtonHideUnderline(
child: DropdownButton<bool>(
value: isMultiScan,
items: const [
DropdownMenuItem(
dropdownColor: Colors.black87,
items: const <DropdownMenuItem<bool>>[
DropdownMenuItem<bool>(
value: false,
child: Text('Single Scan'),
child: Text(
'Single Code',
style: TextStyle(color: Colors.white),
),
),
DropdownMenuItem(
DropdownMenuItem<bool>(
value: true,
child: Text('Multi Scan'),
child: Text(
'Multi Code',
style: TextStyle(color: Colors.white),
),
),
],
onChanged: (value) => onChanged?.call(value ?? false),
onChanged: (bool? value) => onChanged?.call(value ?? false),
),
),
),

18
lib/src/utils/extentions.dart

@ -8,17 +8,17 @@ import '../../zxing_mobile.dart';
extension CodeExt on CodeResult {
Code toCode() {
return Code(
text == nullptr ? null : text.cast<Utf8>().toDartString(),
isValid == 1,
error == nullptr ? null : error.cast<Utf8>().toDartString(),
bytes == nullptr
text: text == nullptr ? null : text.cast<Utf8>().toDartString(),
isValid: isValid == 1,
error: error == nullptr ? null : error.cast<Utf8>().toDartString(),
rawBytes: bytes == nullptr
? null
: Uint8List.fromList(bytes.cast<Int8>().asTypedList(length)),
format,
pos == nullptr ? null : pos.ref.toPosition(),
isInverted == 1,
isMirrored == 1,
duration,
format: format,
position: pos == nullptr ? null : pos.ref.toPosition(),
isInverted: isInverted == 1,
isMirrored: isMirrored == 1,
duration: duration,
);
}
}

6
lib/zxing_mobile.dart

@ -53,21 +53,21 @@ class ZxingMobile implements Zxing {
await zxingProcessCameraImage(image, params: params) as Codes;
@override
Future<Code?> readBarcodeImagePathString(
Future<Code> readBarcodeImagePathString(
String path, {
DecodeParams? params,
}) =>
zxingReadBarcodeImagePathString(path, params: params);
@override
Future<Code?> readBarcodeImagePath(
Future<Code> readBarcodeImagePath(
XFile path, {
DecodeParams? params,
}) =>
zxingReadBarcodeImagePath(path, params: params);
@override
Future<Code?> readBarcodeImageUrl(
Future<Code> readBarcodeImageUrl(
String url, {
DecodeParams? params,
}) =>

6
lib/zxing_web.dart

@ -46,21 +46,21 @@ class ZxingWeb implements Zxing {
throw UnimplementedError();
@override
Future<Code?> readBarcodeImagePathString(
Future<Code> readBarcodeImagePathString(
String path, {
DecodeParams? params,
}) =>
throw UnimplementedError();
@override
Future<Code?> readBarcodeImagePath(
Future<Code> readBarcodeImagePath(
XFile path, {
DecodeParams? params,
}) =>
throw UnimplementedError();
@override
Future<Code?> readBarcodeImageUrl(
Future<Code> readBarcodeImageUrl(
String url, {
DecodeParams? params,
}) =>

1
pubspec.yaml

@ -13,6 +13,7 @@ dependencies:
flutter:
sdk: flutter
image: ^3.0.0
image_picker: ^0.8.0
dev_dependencies:
ffigen: ^7.0.0 # dart run ffigen

4
src/native_zxing.cpp

@ -3,6 +3,7 @@
#include "MultiFormatWriter.h"
#include "BitMatrix.h"
#include "native_zxing.h"
#include "ZXVersion.h"
#include <locale>
#include <codecvt>
@ -22,8 +23,7 @@ extern "C"
FUNCTION_ATTRIBUTE
char const *version()
{
// TODO: use ZXING_VERSION_STR after zxing-cpp 2.1 is released
return "2.0.0";
return ZXING_VERSION_STR;
}
FUNCTION_ATTRIBUTE

2
src/zxing

@ -1 +1 @@
Subproject commit 86b253d699b13b1da8fca0c5e4fbd62691582d5a
Subproject commit 72023ad3dded9f3f94b5d85bc10385e0cf76620a

408
zxscanner/pubspec.lock

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save