Navaron Bracke

implement the start method

@@ -6,11 +6,13 @@ import 'package:mobile_scanner/src/enums/barcode_format.dart'; @@ -6,11 +6,13 @@ import 'package:mobile_scanner/src/enums/barcode_format.dart';
6 import 'package:mobile_scanner/src/enums/camera_facing.dart'; 6 import 'package:mobile_scanner/src/enums/camera_facing.dart';
7 import 'package:mobile_scanner/src/enums/detection_speed.dart'; 7 import 'package:mobile_scanner/src/enums/detection_speed.dart';
8 import 'package:mobile_scanner/src/enums/mobile_scanner_error_code.dart'; 8 import 'package:mobile_scanner/src/enums/mobile_scanner_error_code.dart';
9 -import 'package:mobile_scanner/src/enums/mobile_scanner_state.dart';  
10 import 'package:mobile_scanner/src/enums/torch_state.dart'; 9 import 'package:mobile_scanner/src/enums/torch_state.dart';
11 import 'package:mobile_scanner/src/mobile_scanner_exception.dart'; 10 import 'package:mobile_scanner/src/mobile_scanner_exception.dart';
12 import 'package:mobile_scanner/src/mobile_scanner_platform_interface.dart'; 11 import 'package:mobile_scanner/src/mobile_scanner_platform_interface.dart';
  12 +import 'package:mobile_scanner/src/mobile_scanner_view_attributes.dart';
13 import 'package:mobile_scanner/src/objects/barcode_capture.dart'; 13 import 'package:mobile_scanner/src/objects/barcode_capture.dart';
  14 +import 'package:mobile_scanner/src/objects/mobile_scanner_state.dart';
  15 +import 'package:mobile_scanner/src/objects/start_options.dart';
14 16
15 /// The controller for the [MobileScanner] widget. 17 /// The controller for the [MobileScanner] widget.
16 class MobileScannerController extends ValueNotifier<MobileScannerState> { 18 class MobileScannerController extends ValueNotifier<MobileScannerState> {
@@ -94,8 +96,38 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> { @@ -94,8 +96,38 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> {
94 /// Get the stream of scanned barcodes. 96 /// Get the stream of scanned barcodes.
95 Stream<BarcodeCapture> get barcodes => _barcodesController.stream; 97 Stream<BarcodeCapture> get barcodes => _barcodesController.stream;
96 98
  99 + StreamSubscription<BarcodeCapture?>? _barcodesSubscription;
  100 + StreamSubscription<TorchState>? _torchStateSubscription;
  101 + StreamSubscription<double>? _zoomScaleSubscription;
  102 +
97 bool _isDisposed = false; 103 bool _isDisposed = false;
98 104
  105 + void _disposeListeners() {
  106 + _barcodesSubscription?.cancel();
  107 + _torchStateSubscription?.cancel();
  108 + _zoomScaleSubscription?.cancel();
  109 +
  110 + _barcodesSubscription = null;
  111 + _torchStateSubscription = null;
  112 + _zoomScaleSubscription = null;
  113 + }
  114 +
  115 + void _setupListeners() {
  116 + _barcodesSubscription = MobileScannerPlatform.instance.barcodesStream.listen((BarcodeCapture? barcode) {
  117 + if (barcode != null) {
  118 + _barcodesController.add(barcode);
  119 + }
  120 + });
  121 +
  122 + _torchStateSubscription = MobileScannerPlatform.instance.torchStateStream.listen((TorchState torchState) {
  123 + value = value.copyWith(torchState: torchState);
  124 + });
  125 +
  126 + _zoomScaleSubscription = MobileScannerPlatform.instance.zoomScaleStateStream.listen((double zoomScale) {
  127 + value = value.copyWith(zoomScale: zoomScale);
  128 + });
  129 + }
  130 +
99 void _throwIfNotInitialized() { 131 void _throwIfNotInitialized() {
100 if (!value.isInitialized) { 132 if (!value.isInitialized) {
101 throw const MobileScannerException( 133 throw const MobileScannerException(
@@ -144,6 +176,55 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> { @@ -144,6 +176,55 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> {
144 await MobileScannerPlatform.instance.setZoomScale(clampedZoomScale); 176 await MobileScannerPlatform.instance.setZoomScale(clampedZoomScale);
145 } 177 }
146 178
  179 + /// Start scanning for barcodes.
  180 + /// Upon calling this method, the necessary camera permission will be requested.
  181 + ///
  182 + /// Throws a [MobileScannerException] if starting the scanner failed.
  183 + Future<void> start({CameraFacing? cameraDirection}) async {
  184 + if (_isDisposed) {
  185 + throw const MobileScannerException(
  186 + errorCode: MobileScannerErrorCode.controllerDisposed,
  187 + errorDetails: MobileScannerErrorDetails(
  188 + message: 'The MobileScannerController was used after it has been disposed.',
  189 + ),
  190 + );
  191 + }
  192 +
  193 + final CameraFacing effectiveDirection = cameraDirection ?? facing;
  194 +
  195 + final StartOptions options = StartOptions(
  196 + cameraDirection: effectiveDirection,
  197 + cameraResolution: cameraResolution,
  198 + detectionSpeed: detectionSpeed,
  199 + detectionTimeoutMs: detectionTimeoutMs,
  200 + formats: formats,
  201 + returnImage: returnImage,
  202 + torchEnabled: torchEnabled,
  203 + );
  204 +
  205 + try {
  206 + _setupListeners();
  207 +
  208 + final MobileScannerViewAttributes viewAttributes = await MobileScannerPlatform.instance.start(
  209 + options,
  210 + );
  211 +
  212 + value = value.copyWith(
  213 + cameraDirection: effectiveDirection,
  214 + isInitialized: true,
  215 + size: viewAttributes.size,
  216 + );
  217 + } on MobileScannerException catch (error) {
  218 + if (!_isDisposed) {
  219 + value = value.copyWith(
  220 + cameraDirection: facing,
  221 + isInitialized: true,
  222 + error: error,
  223 + );
  224 + }
  225 + }
  226 + }
  227 +
147 /// Stop the camera. 228 /// Stop the camera.
148 /// 229 ///
149 /// After calling this method, the camera can be restarted using [start]. 230 /// After calling this method, the camera can be restarted using [start].