| @@ -22,4 +22,4 @@ jobs: | |||
| - name: Format | |||
| run: dartfmt -n --set-exit-if-changed . | |||
| - name: Linter | |||
| run: dartanalyzer . --fatal-hints | |||
| run: dartanalyzer . --options=analysis_options.yaml --fatal-hints | |||
| @@ -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 | |||
| @@ -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<QRViewExample> { | |||
| 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<QRViewExample> { | |||
| body: Column( | |||
| children: <Widget>[ | |||
| Expanded( | |||
| flex: 4, | |||
| child: QRView( | |||
| key: qrKey, | |||
| onQRViewCreated: _onQRViewCreated, | |||
| @@ -41,32 +42,32 @@ class _QRViewExampleState extends State<QRViewExample> { | |||
| cutOutSize: 300, | |||
| ), | |||
| ), | |||
| flex: 4, | |||
| ), | |||
| Expanded( | |||
| flex: 1, | |||
| child: FittedBox( | |||
| fit: BoxFit.contain, | |||
| child: Column( | |||
| mainAxisAlignment: MainAxisAlignment.spaceEvenly, | |||
| children: <Widget>[ | |||
| Text("This is the result of scan: $qrText"), | |||
| Text('This is the result of scan: $qrText'), | |||
| Row( | |||
| mainAxisAlignment: MainAxisAlignment.center, | |||
| crossAxisAlignment: CrossAxisAlignment.center, | |||
| children: <Widget>[ | |||
| 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<QRViewExample> { | |||
| ), | |||
| ), | |||
| 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<QRViewExample> { | |||
| crossAxisAlignment: CrossAxisAlignment.center, | |||
| children: <Widget>[ | |||
| Container( | |||
| margin: EdgeInsets.all(8.0), | |||
| margin: EdgeInsets.all(8), | |||
| child: RaisedButton( | |||
| onPressed: () { | |||
| controller?.pauseCamera(); | |||
| @@ -112,7 +113,7 @@ class _QRViewExampleState extends State<QRViewExample> { | |||
| ), | |||
| ), | |||
| Container( | |||
| margin: EdgeInsets.all(8.0), | |||
| margin: EdgeInsets.all(8), | |||
| child: RaisedButton( | |||
| onPressed: () { | |||
| controller?.resumeCamera(); | |||
| @@ -125,19 +126,18 @@ class _QRViewExampleState extends State<QRViewExample> { | |||
| ], | |||
| ), | |||
| ), | |||
| 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) { | |||
| @@ -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<QRView> { | |||
| 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<String> _scanUpdateController = StreamController<String>(); | |||
| Stream<String> 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<String> _scanUpdateController = | |||
| StreamController<String>(); | |||
| Stream<String> 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() { | |||
| @@ -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, | |||
| @@ -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 | |||