diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 443268c..2722427 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -22,4 +22,4 @@ jobs: - name: Format run: dartfmt -n --set-exit-if-changed . - name: Linter - run: dartanalyzer . --fatal-hints \ No newline at end of file + run: dartanalyzer . --options=analysis_options.yaml --fatal-hints diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..e2dba57 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,106 @@ +include: package:pedantic/analysis_options.1.9.0.yaml +linter: + rules: + - always_put_required_named_parameters_first + - always_require_non_null_named_parameters + - avoid_annotating_with_dynamic + - avoid_bool_literals_in_conditional_expressions + - avoid_catching_errors + - avoid_classes_with_only_static_members + - avoid_empty_else + - avoid_init_to_null + - avoid_null_checks_in_equality_operators + - avoid_print + - avoid_relative_lib_imports + - avoid_return_types_on_setters + - avoid_returning_null + - avoid_returning_null_for_future + - avoid_returning_null_for_void + - avoid_shadowing_type_parameters + - avoid_single_cascade_in_expression_statements + - avoid_types_as_parameter_names + - avoid_types_on_closure_parameters + - avoid_void_async + - await_only_futures + - camel_case_types + - cancel_subscriptions + - cascade_invocations + - close_sinks + - comment_references + - constant_identifier_names + - control_flow_in_finally + - curly_braces_in_flow_control_structures + - directives_ordering + - empty_catches + - empty_constructor_bodies + - empty_statements + - file_names + - hash_and_equals + - implementation_imports + - invariant_booleans + - iterable_contains_unrelated_type + - join_return_with_assignment + - library_names + - library_prefixes + - list_remove_unrelated_type + - no_duplicate_case_values + - non_constant_identifier_names + - null_closures + - only_throw_errors + - overridden_fields + - package_api_docs + - package_names + - package_prefixed_library_names + - prefer_collection_literals + - prefer_conditional_assignment + - prefer_const_declarations + - prefer_contains + - prefer_equal_for_default_values + - prefer_final_fields + - prefer_for_elements_to_map_fromIterable + - prefer_foreach + - prefer_function_declarations_over_variables + - prefer_if_elements_to_conditional_expressions + - prefer_if_null_operators + - prefer_initializing_formals + - prefer_inlined_adds + - prefer_int_literals + - prefer_interpolation_to_compose_strings + - prefer_is_empty + - prefer_is_not_empty + - prefer_iterable_whereType + - prefer_null_aware_operators + - prefer_void_to_null + - provide_deprecation_message + - recursive_getters + - slash_for_doc_comments + - sort_child_properties_last + - sort_constructors_first + - sort_pub_dependencies + - sort_unnamed_constructors_first + - test_types_in_equals + - throw_in_finally + - type_init_formals + - unawaited_futures + - unnecessary_await_in_return + - unnecessary_brace_in_string_interps + - unnecessary_const + - unnecessary_getters_setters + - unnecessary_lambdas + - unnecessary_new + - unnecessary_null_aware_assignments + - unnecessary_null_in_if_null_operators + - unnecessary_overrides + - unnecessary_parenthesis + - unnecessary_statements + - unnecessary_this + - unrelated_type_equality_checks + - unsafe_html + - use_full_hex_values_for_flutter_colors + - use_function_type_syntax_for_parameters + - use_rethrow_when_possible + - use_setters_to_change_properties + - use_string_buffers + - use_to_and_as_if_applicable + - valid_regexps + - void_checks diff --git a/example/lib/main.dart b/example/lib/main.dart index f90cccd..25855f9 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -3,10 +3,10 @@ import 'package:qr_code_scanner/qr_code_scanner.dart'; void main() => runApp(MaterialApp(home: QRViewExample())); -const flash_on = "FLASH ON"; -const flash_off = "FLASH OFF"; -const front_camera = "FRONT CAMERA"; -const back_camera = "BACK CAMERA"; +const flashOn = 'FLASH ON'; +const flashOff = 'FLASH OFF'; +const frontCamera = 'FRONT CAMERA'; +const backCamera = 'BACK CAMERA'; class QRViewExample extends StatefulWidget { const QRViewExample({ @@ -18,9 +18,9 @@ class QRViewExample extends StatefulWidget { } class _QRViewExampleState extends State { - var qrText = ""; - var flashState = flash_on; - var cameraState = front_camera; + var qrText = ''; + var flashState = flashOn; + var cameraState = frontCamera; QRViewController controller; final GlobalKey qrKey = GlobalKey(debugLabel: 'QR'); @@ -30,6 +30,7 @@ class _QRViewExampleState extends State { body: Column( children: [ Expanded( + flex: 4, child: QRView( key: qrKey, onQRViewCreated: _onQRViewCreated, @@ -41,32 +42,32 @@ class _QRViewExampleState extends State { cutOutSize: 300, ), ), - flex: 4, ), Expanded( + flex: 1, child: FittedBox( fit: BoxFit.contain, child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - Text("This is the result of scan: $qrText"), + Text('This is the result of scan: $qrText'), Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( - margin: EdgeInsets.all(8.0), + margin: EdgeInsets.all(8), child: RaisedButton( onPressed: () { if (controller != null) { controller.toggleFlash(); if (_isFlashOn(flashState)) { setState(() { - flashState = flash_off; + flashState = flashOff; }); } else { setState(() { - flashState = flash_on; + flashState = flashOn; }); } } @@ -76,18 +77,18 @@ class _QRViewExampleState extends State { ), ), Container( - margin: EdgeInsets.all(8.0), + margin: EdgeInsets.all(8), child: RaisedButton( onPressed: () { if (controller != null) { controller.flipCamera(); if (_isBackCamera(cameraState)) { setState(() { - cameraState = front_camera; + cameraState = frontCamera; }); } else { setState(() { - cameraState = back_camera; + cameraState = backCamera; }); } } @@ -103,7 +104,7 @@ class _QRViewExampleState extends State { crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( - margin: EdgeInsets.all(8.0), + margin: EdgeInsets.all(8), child: RaisedButton( onPressed: () { controller?.pauseCamera(); @@ -112,7 +113,7 @@ class _QRViewExampleState extends State { ), ), Container( - margin: EdgeInsets.all(8.0), + margin: EdgeInsets.all(8), child: RaisedButton( onPressed: () { controller?.resumeCamera(); @@ -125,19 +126,18 @@ class _QRViewExampleState extends State { ], ), ), - flex: 1, ) ], ), ); } - _isFlashOn(String current) { - return flash_on == current; + bool _isFlashOn(String current) { + return flashOn == current; } - _isBackCamera(String current) { - return back_camera == current; + bool _isBackCamera(String current) { + return backCamera == current; } void _onQRViewCreated(QRViewController controller) { diff --git a/lib/src/qr_code_scanner.dart b/lib/src/qr_code_scanner.dart index 036e27f..fad8126 100644 --- a/lib/src/qr_code_scanner.dart +++ b/lib/src/qr_code_scanner.dart @@ -4,7 +4,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -typedef void QRViewCreatedCallback(QRViewController controller); +typedef QRViewCreatedCallback = void Function(QRViewController); class QRView extends StatefulWidget { const QRView({ @@ -29,13 +29,14 @@ class _QRViewState extends State { return Stack( children: [ _getPlatformQrView(), - widget.overlay != null - ? Container( - decoration: ShapeDecoration( - shape: widget.overlay, - ), - ) - : Container(), + if (widget.overlay != null) + Container( + decoration: ShapeDecoration( + shape: widget.overlay, + ), + ) + else + Container(), ], ); } @@ -94,23 +95,15 @@ class _CreationParams { } class QRViewController { - static const scanMethodCall = "onRecognizeQR"; - - final MethodChannel _channel; - - StreamController _scanUpdateController = StreamController(); - - Stream get scannedDataStream => _scanUpdateController.stream; - QRViewController._(int id, GlobalKey qrKey) : _channel = MethodChannel('net.touchcapture.qr.flutterqr/qrview_$id') { if (defaultTargetPlatform == TargetPlatform.iOS) { final RenderBox renderBox = qrKey.currentContext.findRenderObject(); - _channel.invokeMethod("setDimensions", - {"width": renderBox.size.width, "height": renderBox.size.height}); + _channel.invokeMethod('setDimensions', + {'width': renderBox.size.width, 'height': renderBox.size.height}); } _channel.setMethodCallHandler( - (MethodCall call) async { + (call) async { switch (call.method) { case scanMethodCall: if (call.arguments != null) { @@ -121,20 +114,29 @@ class QRViewController { ); } + static const scanMethodCall = 'onRecognizeQR'; + + final MethodChannel _channel; + + final StreamController _scanUpdateController = + StreamController(); + + Stream get scannedDataStream => _scanUpdateController.stream; + void flipCamera() { - _channel.invokeMethod("flipCamera"); + _channel.invokeMethod('flipCamera'); } void toggleFlash() { - _channel.invokeMethod("toggleFlash"); + _channel.invokeMethod('toggleFlash'); } void pauseCamera() { - _channel.invokeMethod("pauseCamera"); + _channel.invokeMethod('pauseCamera'); } void resumeCamera() { - _channel.invokeMethod("resumeCamera"); + _channel.invokeMethod('resumeCamera'); } void dispose() { diff --git a/lib/src/qr_scanner_overlay_shape.dart b/lib/src/qr_scanner_overlay_shape.dart index 67c8439..886c533 100644 --- a/lib/src/qr_scanner_overlay_shape.dart +++ b/lib/src/qr_scanner_overlay_shape.dart @@ -3,13 +3,6 @@ import 'dart:ui'; import 'package:flutter/material.dart'; class QrScannerOverlayShape extends ShapeBorder { - final Color borderColor; - final double borderWidth; - final Color overlayColor; - final double borderRadius; - final double borderLength; - final double cutOutSize; - QrScannerOverlayShape({ this.borderColor = Colors.red, this.borderWidth = 3.0, @@ -18,15 +11,20 @@ class QrScannerOverlayShape extends ShapeBorder { this.borderLength = 40, this.cutOutSize = 250, }) : assert( - cutOutSize != null - ? cutOutSize != null - ? borderLength <= cutOutSize / 2 + borderWidth * 2 - : true - : true, + cutOutSize != null ?? + cutOutSize != null ?? + borderLength <= cutOutSize / 2 + borderWidth * 2, "Border can't be larger than ${cutOutSize / 2 + borderWidth * 2}"); + final Color borderColor; + final double borderWidth; + final Color overlayColor; + final double borderRadius; + final double borderLength; + final double cutOutSize; + @override - EdgeInsetsGeometry get dimensions => const EdgeInsets.all(10.0); + EdgeInsetsGeometry get dimensions => const EdgeInsets.all(10); @override Path getInnerPath(Rect rect, {TextDirection textDirection}) { @@ -93,12 +91,11 @@ class QrScannerOverlayShape extends ShapeBorder { _cutOutSize - borderOffset * 2, ); - canvas.saveLayer( - rect, - backgroundPaint, - ); - canvas + ..saveLayer( + rect, + backgroundPaint, + ) ..drawRect( rect, backgroundPaint, diff --git a/pubspec.yaml b/pubspec.yaml index e488733..70c2511 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -6,12 +6,15 @@ homepage: https://juliuscanute.com repository: https://github.com/juliuscanute/qr_code_scanner environment: - sdk: ">=2.0.0-dev.68.0 <3.0.0" + sdk: ">=2.3.0 <3.0.0" dependencies: flutter: sdk: flutter +dev_dependencies: + pedantic: ^1.9.0 + flutter: plugin: androidPackage: net.touchcapture.qr.flutterqr