Ver código fonte

Add support for null-safety (#278)

flutter-beta
Julian Steenbakker 5 anos atrás
pai
commit
f60e7affae
Nenhuma chave conhecida encontrada para esta assinatura no banco de dados ID da chave GPG: 16E437C7A3D94250
9 arquivos alterados com 65 adições e 66 exclusões
  1. +6
    -10
      example/lib/main.dart
  2. +1
    -1
      example/pubspec.yaml
  3. +4
    -4
      lib/src/lifecycle_event_handler.dart
  4. +45
    -42
      lib/src/qr_code_scanner.dart
  5. +3
    -3
      lib/src/qr_scanner_overlay_shape.dart
  6. +2
    -2
      lib/src/types/barcode.dart
  7. +1
    -1
      lib/src/types/barcode_format.dart
  8. +1
    -1
      lib/src/types/camera_exception.dart
  9. +2
    -2
      pubspec.yaml

+ 6
- 10
example/lib/main.dart Ver arquivo

@@ -7,17 +7,13 @@ import 'package:qr_code_scanner/qr_code_scanner.dart';
void main() => runApp(MaterialApp(home: QRViewExample()));

class QRViewExample extends StatefulWidget {
const QRViewExample({
Key key,
}) : super(key: key);

@override
State<StatefulWidget> createState() => _QRViewExampleState();
}

class _QRViewExampleState extends State<QRViewExample> {
Barcode result;
QRViewController controller;
Barcode? result;
QRViewController? controller;
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');

// In order to get hot reload to work we need to pause the camera if the platform
@@ -26,9 +22,9 @@ class _QRViewExampleState extends State<QRViewExample> {
void reassemble() {
super.reassemble();
if (Platform.isAndroid) {
controller.pauseCamera();
controller!.pauseCamera();
}
controller.resumeCamera();
controller!.resumeCamera();
}

@override
@@ -46,7 +42,7 @@ class _QRViewExampleState extends State<QRViewExample> {
children: <Widget>[
if (result != null)
Text(
'Barcode Type: ${describeEnum(result.format)} Data: ${result.code}')
'Barcode Type: ${describeEnum(result!.format)} Data: ${result!.code}')
else
Text('Scan a code'),
Row(
@@ -79,7 +75,7 @@ class _QRViewExampleState extends State<QRViewExample> {
builder: (context, snapshot) {
if (snapshot.data != null) {
return Text(
'Camera facing ${describeEnum(snapshot.data)}');
'Camera facing ${describeEnum(snapshot.data!)}');
} else {
return Text('loading');
}


+ 1
- 1
example/pubspec.yaml Ver arquivo

@@ -3,7 +3,7 @@ description: Demonstrates how to use the flutter_qr plugin.
publish_to: 'none'

environment:
sdk: ">=2.6.0 <3.0.0"
sdk: '>=2.12.0 <3.0.0'

dependencies:
flutter:


+ 4
- 4
lib/src/lifecycle_event_handler.dart Ver arquivo

@@ -7,22 +7,22 @@ class LifecycleEventHandler extends WidgetsBindingObserver {
this.suspendingCallBack,
});

final AsyncCallback resumeCallBack;
final AsyncCallback suspendingCallBack;
final AsyncCallback? resumeCallBack;
final AsyncCallback? suspendingCallBack;

@override
Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
switch (state) {
case AppLifecycleState.resumed:
if (resumeCallBack != null) {
await resumeCallBack();
await resumeCallBack!();
}
break;
case AppLifecycleState.inactive:
case AppLifecycleState.paused:
case AppLifecycleState.detached:
if (suspendingCallBack != null) {
await suspendingCallBack();
await suspendingCallBack!();
}
break;
}


+ 45
- 42
lib/src/qr_code_scanner.dart Ver arquivo

@@ -14,29 +14,27 @@ import 'types/camera_exception.dart';
import 'types/features.dart';

typedef QRViewCreatedCallback = void Function(QRViewController);
typedef PermissionSetCallback = void Function(QRViewController, bool);
typedef PermissionSetCallback = void Function(QRViewController, bool?);

/// The [QRView] is the view where the camera
/// and the barcode scanner gets displayed.
class QRView extends StatefulWidget {
const QRView({
@required Key key,
@required this.onQRViewCreated,
required Key key,
required this.onQRViewCreated,
this.overlay,
this.overlayMargin = EdgeInsets.zero,
this.cameraFacing = CameraFacing.back,
this.onPermissionSet,
this.formatsAllowed,
}) : assert(key != null),
assert(onQRViewCreated != null),
super(key: key);
}) : super(key: key);

/// [onQRViewCreated] gets called when the view is created
final QRViewCreatedCallback onQRViewCreated;

/// Use [overlay] to provide an overlay for the view.
/// This can be used to create a certain scan area.
final QrScannerOverlayShape overlay;
final QrScannerOverlayShape? overlay;

/// Use [overlayMargin] to provide a margin to [overlay]
final EdgeInsetsGeometry overlayMargin;
@@ -48,10 +46,10 @@ class QRView extends StatefulWidget {
final CameraFacing cameraFacing;

/// Calls the provided [onPermissionSet] callback when the permission is set.
final PermissionSetCallback onPermissionSet;
final PermissionSetCallback? onPermissionSet;

/// Use [formatsAllowed] to specify which formats needs to be scanned.
final List<BarcodeFormat> formatsAllowed;
final List<BarcodeFormat>? formatsAllowed;

@override
State<StatefulWidget> createState() => _QRViewState();
@@ -59,7 +57,7 @@ class QRView extends StatefulWidget {

class _QRViewState extends State<QRView> {
var _channel;
var _observer;
late var _observer;

@override
void initState() {
@@ -68,11 +66,12 @@ class _QRViewState extends State<QRView> {
resumeCallBack: () async => {
if (_channel != null)
{
QRViewController.updateDimensions(widget.key, _channel,
QRViewController.updateDimensions(
widget.key as GlobalKey<State<StatefulWidget>>, _channel,
overlay: widget.overlay)
}
});
WidgetsBinding.instance.addObserver(_observer);
WidgetsBinding.instance!.addObserver(_observer);
}

@override
@@ -90,12 +89,13 @@ class _QRViewState extends State<QRView> {
@override
void dispose() {
super.dispose();
WidgetsBinding.instance.removeObserver(_observer);
WidgetsBinding.instance!.removeObserver(_observer);
}

bool onNotification(notification) {
Future.microtask(() => {
QRViewController.updateDimensions(widget.key, _channel,
QRViewController.updateDimensions(
widget.key as GlobalKey<State<StatefulWidget>>, _channel,
overlay: widget.overlay)
});

@@ -109,7 +109,7 @@ class _QRViewState extends State<QRView> {
Container(
padding: widget.overlayMargin,
decoration: ShapeDecoration(
shape: widget.overlay,
shape: widget.overlay!,
),
)
],
@@ -149,13 +149,15 @@ class _QRViewState extends State<QRView> {

// Start scan after creation of the view
final controller = QRViewController._(
_channel, widget.key, widget.onPermissionSet, widget.cameraFacing)
.._startScan(widget.key, widget.overlay, widget.formatsAllowed);
_channel,
widget.key as GlobalKey<State<StatefulWidget>>?,
widget.onPermissionSet,
widget.cameraFacing)
.._startScan(widget.key as GlobalKey<State<StatefulWidget>>,
widget.overlay, widget.formatsAllowed);

// Initialize the controller for controlling the QRView
if (widget.onQRViewCreated != null) {
widget.onQRViewCreated(controller);
}
widget.onQRViewCreated(controller);
}
}

@@ -164,18 +166,18 @@ class _QrCameraSettings {
this.cameraFacing,
});

final CameraFacing cameraFacing;
final CameraFacing? cameraFacing;

Map<String, dynamic> toMap() {
return <String, dynamic>{
'cameraFacing': cameraFacing.index,
'cameraFacing': cameraFacing!.index,
};
}
}

class QRViewController {
QRViewController._(MethodChannel channel, GlobalKey qrKey,
PermissionSetCallback onPermissionSet, CameraFacing cameraFacing)
QRViewController._(MethodChannel channel, GlobalKey? qrKey,
PermissionSetCallback? onPermissionSet, CameraFacing cameraFacing)
: _channel = channel,
_cameraFacing = cameraFacing {
_channel.setMethodCallHandler((call) async {
@@ -183,10 +185,10 @@ class QRViewController {
case 'onRecognizeQR':
if (call.arguments != null) {
final args = call.arguments as Map;
final code = args['code'] as String;
final rawType = args['type'] as String;
final code = args['code'] as String?;
final rawType = args['type'] as String?;
// Raw bytes are only supported by Android.
final rawBytes = args['rawBytes'] as List<int>;
final rawBytes = args['rawBytes'] as List<int>?;
final format = BarcodeTypesExtension.fromString(rawType);
if (format != null) {
final barcode = Barcode(code, format, rawBytes);
@@ -205,7 +207,7 @@ class QRViewController {
_hasPermissions = false;
}
if (onPermissionSet != null) {
onPermissionSet(this, call.arguments as bool);
onPermissionSet(this, call.arguments as bool?);
}
}
break;
@@ -213,27 +215,27 @@ class QRViewController {
});
}

final MethodChannel _channel;
late final MethodChannel _channel;
final CameraFacing _cameraFacing;
final StreamController<Barcode> _scanUpdateController =
StreamController<Barcode>();

Stream<Barcode> get scannedDataStream => _scanUpdateController.stream;

SystemFeatures _features;
bool _hasPermissions;
SystemFeatures? _features;
bool? _hasPermissions;

SystemFeatures get systemFeatures => _features;
bool get hasPermissions => _hasPermissions;
SystemFeatures? get systemFeatures => _features;
bool? get hasPermissions => _hasPermissions;

/// Starts the barcode scanner
Future<void> _startScan(GlobalKey key, QrScannerOverlayShape overlay,
List<BarcodeFormat> barcodeFormats) async {
Future<void> _startScan(GlobalKey key, QrScannerOverlayShape? overlay,
List<BarcodeFormat>? barcodeFormats) async {
// We need to update the dimension before the scan is started.
try {
await QRViewController.updateDimensions(key, _channel, overlay: overlay);
return await _channel.invokeMethod(
'startScan', barcodeFormats?.map((e) => e.asInt())?.toList() ?? []);
'startScan', barcodeFormats?.map((e) => e.asInt()).toList() ?? []);
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
@@ -242,7 +244,7 @@ class QRViewController {
/// Gets information about which camera is active.
Future<CameraFacing> getCameraInfo() async {
try {
var cameraFacing = await _channel.invokeMethod('getCameraInfo') as int;
var cameraFacing = await _channel.invokeMethod('getCameraInfo') as int?;
if (cameraFacing == -1) return _cameraFacing;
return CameraFacing
.values[await _channel.invokeMethod('getCameraInfo') as int];
@@ -262,7 +264,7 @@ class QRViewController {
}

/// Get flashlight status
Future<bool> getFlashStatus() async {
Future<bool?> getFlashStatus() async {
try {
return await _channel.invokeMethod('getFlashInfo');
} on PlatformException catch (e) {
@@ -273,7 +275,7 @@ class QRViewController {
/// Toggles the flashlight between available modes
Future<void> toggleFlash() async {
try {
await _channel.invokeMethod('toggleFlash') as bool;
await _channel.invokeMethod('toggleFlash') as bool?;
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
@@ -310,7 +312,8 @@ class QRViewController {
Future<SystemFeatures> getSystemFeatures() async {
try {
var features =
await _channel.invokeMapMethod<String, dynamic>('getSystemFeatures');
await (_channel.invokeMapMethod<String, dynamic>('getSystemFeatures')
as FutureOr<Map<String, dynamic>>);
return SystemFeatures.fromJson(features);
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
@@ -325,11 +328,11 @@ class QRViewController {

/// Updates the view dimensions for iOS.
static Future<void> updateDimensions(GlobalKey key, MethodChannel channel,
{QrScannerOverlayShape overlay}) async {
{QrScannerOverlayShape? overlay}) async {
if (defaultTargetPlatform == TargetPlatform.iOS) {
// Add small delay to ensure the renderbox is loaded
await Future.delayed(Duration(milliseconds: 100));
final RenderBox renderBox = key.currentContext.findRenderObject();
final renderBox = key.currentContext!.findRenderObject() as RenderBox;
try {
await channel.invokeMethod('setDimensions', {
'width': renderBox.size.width,


+ 3
- 3
lib/src/qr_scanner_overlay_shape.dart Ver arquivo

@@ -29,14 +29,14 @@ class QrScannerOverlayShape extends ShapeBorder {
EdgeInsetsGeometry get dimensions => const EdgeInsets.all(10);

@override
Path getInnerPath(Rect rect, {TextDirection textDirection}) {
Path getInnerPath(Rect rect, {TextDirection? textDirection}) {
return Path()
..fillType = PathFillType.evenOdd
..addPath(getOuterPath(rect), Offset.zero);
}

@override
Path getOuterPath(Rect rect, {TextDirection textDirection}) {
Path getOuterPath(Rect rect, {TextDirection? textDirection}) {
Path _getLeftTopPath(Rect rect) {
return Path()
..moveTo(rect.left, rect.bottom)
@@ -60,7 +60,7 @@ class QrScannerOverlayShape extends ShapeBorder {
}

@override
void paint(Canvas canvas, Rect rect, {TextDirection textDirection}) {
void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {
final width = rect.width;
final borderWidthSize = width / 2;
final height = rect.height;


+ 2
- 2
lib/src/types/barcode.dart Ver arquivo

@@ -8,9 +8,9 @@ import 'barcode_format.dart';
class Barcode {
Barcode(this.code, this.format, this.rawBytes);

final String code;
final String? code;
final BarcodeFormat format;

/// Raw bytes are only supported by Android.
final List<int> rawBytes;
final List<int>? rawBytes;
}

+ 1
- 1
lib/src/types/barcode_format.dart Ver arquivo

@@ -61,7 +61,7 @@ extension BarcodeTypesExtension on BarcodeFormat {
return index;
}

static BarcodeFormat fromString(String format) {
static BarcodeFormat? fromString(String? format) {
switch (format) {
case 'AZTEC':
return BarcodeFormat.aztec;


+ 1
- 1
lib/src/types/camera_exception.dart Ver arquivo

@@ -7,7 +7,7 @@ class CameraException implements Exception {
String code;

/// Textual description of the error.
String description;
String? description;

@override
String toString() => 'CameraException($code, $description)';


+ 2
- 2
pubspec.yaml Ver arquivo

@@ -5,7 +5,7 @@ homepage: https://juliuscanute.com
repository: https://github.com/juliuscanute/qr_code_scanner

environment:
sdk: ">=2.6.0 <3.0.0"
sdk: '>=2.12.0 <3.0.0'
flutter: ">=1.10.0"

dependencies:
@@ -13,7 +13,7 @@ dependencies:
sdk: flutter

dev_dependencies:
pedantic: ^1.9.2
pedantic: ^1.11.0

flutter:
plugin:


Carregando…
Cancelar
Salvar