diff --git a/lib/processors/scheme_processors/navigation_scheme_processors/home_widget_navigate_processor.dart b/lib/processors/scheme_processors/navigation_scheme_processors/home_widget_navigate_processor.dart index d26a4da46..2d71409db 100644 --- a/lib/processors/scheme_processors/navigation_scheme_processors/home_widget_navigate_processor.dart +++ b/lib/processors/scheme_processors/navigation_scheme_processors/home_widget_navigate_processor.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_launcher_icons/custom_exceptions.dart'; import '../../../utils/home_widget_utils.dart'; import '../../../utils/logger.dart'; @@ -19,8 +18,11 @@ class HomeWidgetNavigateProcessor implements NavigationSchemeProcessor { @override Future processUri(Uri uri, {BuildContext? context, bool fromInit = false}) async { if (context == null) { - Logger.error('HomeWidgetNavigateProcessor: Cannot Navigate without context', - error: const InvalidConfigException('context is null'), stackTrace: StackTrace.current); + Logger.error( + 'HomeWidgetNavigateProcessor: Cannot Navigate without context', + error: Exception('context is null'), + stackTrace: StackTrace.current, + ); return; } Logger.warning('HomeWidgetNavigateProcessor: Processing uri: $uri'); diff --git a/lib/utils/image_converter.dart b/lib/utils/image_converter.dart new file mode 100644 index 000000000..3ddb1f2ec --- /dev/null +++ b/lib/utils/image_converter.dart @@ -0,0 +1,133 @@ +import 'dart:io'; +import 'dart:typed_data'; +import 'dart:ui'; +import 'package:camera/camera.dart'; +import 'package:image/image.dart' as imglib; + +class ImageConverter { + final imglib.Image image; + final Size size; + + ImageConverter({ + required this.image, + }) : size = Size(image.width.toDouble(), image.height.toDouble()); + + factory ImageConverter.fromCameraImage(CameraImage image, int rotation, {bool isFrontCamera = false}) { + if (image.format.group != ImageFormatGroup.yuv420 || image.planes.length != 3) { + throw ArgumentError('Only support YUV_420 format'); + } + return ImageConverter._rotatedCameraImage(image, rotation: rotation, mirror: isFrontCamera); + } + + factory ImageConverter._rotatedCameraImage(CameraImage image, {required int rotation, required bool mirror}) { + rotation = 360 - rotation; // if the rotation is 90, we need to rotate by 270 to get the correct rotation + const alpha = 0xFF; + final height = image.height; + final width = image.width; + final yPlane = image.planes[0]; + final uPlane = image.planes[1]; + final vPlane = image.planes[2]; + final int outputWidth = rotation == 90 || rotation == 270 ? height : width; + final int outputHeight = rotation == 90 || rotation == 270 ? width : height; + final int uvRowStride = uPlane.bytesPerRow; + final int uvPixelStride = uPlane.bytesPerPixel!; + Function(int x, int y) getNewX; + Function(int x, int y) getNewY; + + switch (rotation) { + case 90: + if (mirror) { + // rotate by 90 and flip horizontally + getNewX = (x, y) => height - y - 1; + getNewY = (x, y) => width - x - 1; + } else { + getNewX = (x, y) => y; + getNewY = (x, y) => width - x - 1; + } + break; + case 180: + if (mirror) { + // rotate by 180 and flip horizontally + getNewX = (x, y) => x; + getNewY = (x, y) => height - y - 1; + } else { + getNewX = (x, y) => width - x - 1; + getNewY = (x, y) => height - y - 1; + } + break; + case 270: + if (mirror) { + // rotate by 270 and flip horizontally + getNewX = (x, y) => y; + getNewY = (x, y) => outputHeight - x; + } else { + getNewX = (x, y) => height - y - 1; + getNewY = (x, y) => x; + } + break; + + default: + if (mirror) { + // flip horizontally + getNewX = (x, y) => x; + getNewY = (x, y) => height - y - 1; + } else { + getNewX = (x, y) => x; + getNewY = (x, y) => y; + } + break; + } + + try { + // imgLib -> Image package from https://pub.dartlang.org/packages/image + var img = imglib.Image(width: outputWidth, height: outputHeight); // Create Image buffer + + // Fill image buffer with plane[0] from YUV420_888 + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + final int uvIndex = uvPixelStride * (x / 2).floor() + uvRowStride * (y / 2).floor(); + final int index = (y * width + x); + + final yp = yPlane.bytes[index]; + final up = uPlane.bytes[uvIndex]; + final vp = vPlane.bytes[uvIndex]; + // Calculate pixel color + + final int r = (yp + vp * 1436 / 1024 - 179).round().clamp(0, 255); + final int g = (yp - up * 46549 / 131072 + 44 - vp * 93604 / 131072 + 91).round().clamp(0, 255); + final int b = (yp + up * 1814 / 1024 - 227).round().clamp(0, 255); + // color: 0x FF FF FF FF + // A B G R + final newX = getNewX(x, y); + final newY = getNewY(x, y); + + if ((img.isBoundsSafe(newX, newY))) { + img.setPixelRgba(newX, newY, r, g, b, alpha); + } + } + } + return ImageConverter(image: img); + } catch (e) { + print(">>>>>>>>>>>> ERROR:" + e.toString()); + throw e; + } + } + + factory ImageConverter.fromFile(String path) { + final img = imglib.decodeImage(File(path).readAsBytesSync())!; + return ImageConverter(image: img); + } + + factory ImageConverter.fromBytes(Uint8List bytes) { + final img = imglib.decodeImage(bytes)!; + return ImageConverter(image: img); + } + + Uint8List toBytes() { + return Uint8List.fromList(imglib.encodePng(image)); + } + + imglib.Image toImage() { + return image; + } +} diff --git a/lib/views/qr_scanner_view/qr_scanner_view.dart b/lib/views/qr_scanner_view/qr_scanner_view.dart index 7cce572c6..950235a02 100644 --- a/lib/views/qr_scanner_view/qr_scanner_view.dart +++ b/lib/views/qr_scanner_view/qr_scanner_view.dart @@ -37,56 +37,56 @@ class QRScannerView extends StatelessView { @override Widget build(BuildContext context) { - return Scaffold( - resizeToAvoidBottomInset: false, - backgroundColor: Colors.black, - appBar: AppBar( - backgroundColor: Colors.black, - leading: IconButton( - icon: const Icon( - Icons.arrow_back, - color: Colors.white, - size: 32, - ), - onPressed: () { - Navigator.pop(context, null); - }), - ), - extendBodyBehindAppBar: true, - body: FutureBuilder( - future: Permission.camera.request(), - builder: (context, isGranted) { - if (isGranted.connectionState != ConnectionState.done) return const SizedBox(); - if (isGranted.data == PermissionStatus.permanentlyDenied) { - return DefaultDialog( - title: Text(AppLocalizations.of(context)!.grantCameraPermissionDialogTitle), - content: Text(AppLocalizations.of(context)!.grantCameraPermissionDialogPermanentlyDenied), - ); - } - if (isGranted.data != PermissionStatus.granted) { - return DefaultDialog( - title: Text(AppLocalizations.of(context)!.grantCameraPermissionDialogTitle), - content: Text(AppLocalizations.of(context)!.grantCameraPermissionDialogContent), - actions: [ - DefaultDialogButton( - child: Text(AppLocalizations.of(context)!.grantCameraPermissionDialogButton), - onPressed: () { - //Trigger the permission to request it - Permission.camera.request(); - }, + return FutureBuilder( + future: Permission.camera.request(), + builder: (context, isGranted) { + if (isGranted.connectionState != ConnectionState.done) return const SizedBox(); + if (isGranted.data == PermissionStatus.permanentlyDenied) { + return DefaultDialog( + title: Text(AppLocalizations.of(context)!.grantCameraPermissionDialogTitle), + content: Text(AppLocalizations.of(context)!.grantCameraPermissionDialogPermanentlyDenied), + ); + } + if (isGranted.data != PermissionStatus.granted) { + return DefaultDialog( + title: Text(AppLocalizations.of(context)!.grantCameraPermissionDialogTitle), + content: Text(AppLocalizations.of(context)!.grantCameraPermissionDialogContent), + actions: [ + DefaultDialogButton( + child: Text(AppLocalizations.of(context)!.grantCameraPermissionDialogButton), + onPressed: () { + //Trigger the permission to request it + Permission.camera.request(); + }, + ), + DefaultDialogButton( + child: Text(AppLocalizations.of(context)!.cancel), + onPressed: () { + Navigator.pop(context, null); + }, + ), + ], + ); + } + return SafeArea( + child: Stack( + children: [ + const QRScannerWidget(), + Scaffold( + resizeToAvoidBottomInset: false, + backgroundColor: Colors.transparent, + appBar: AppBar( + backgroundColor: Colors.transparent, + foregroundColor: Colors.white, + elevation: 0, ), - DefaultDialogButton( - child: Text(AppLocalizations.of(context)!.cancel), - onPressed: () { - Navigator.pop(context, null); - }, - ), - ], - ); - } - return const QRScannerWidget(); - }, - ), + extendBodyBehindAppBar: true, + body: const SizedBox(), + ), + ], + ), + ); + }, ); } } diff --git a/lib/views/qr_scanner_view/qr_scanner_view_widgets/qr_code_scanner_overlay.dart b/lib/views/qr_scanner_view/qr_scanner_view_widgets/qr_code_scanner_overlay.dart index 0ec2b5220..cb8c20b8c 100644 --- a/lib/views/qr_scanner_view/qr_scanner_view_widgets/qr_code_scanner_overlay.dart +++ b/lib/views/qr_scanner_view/qr_scanner_view_widgets/qr_code_scanner_overlay.dart @@ -17,46 +17,37 @@ class ScannerOverlayShape extends ShapeBorder { EdgeInsetsGeometry get dimensions => const EdgeInsets.all(10.0); @override - Path getInnerPath(Rect rect, {TextDirection? textDirection}) { - return Path() - ..fillType = PathFillType.evenOdd - ..addPath(getOuterPath(rect), Offset.zero); - } + Path getInnerPath(Rect rect, {TextDirection? textDirection}) => Path() + ..fillType = PathFillType.evenOdd + ..addPath(getOuterPath(rect), Offset.zero); @override - Path getOuterPath(Rect rect, {TextDirection? textDirection}) { - { - Path getLeftTopPath(Rect rect) { - return Path() - ..moveTo(rect.left, rect.bottom) - ..lineTo(rect.left, rect.top) - ..lineTo(rect.right, rect.top); - } - - return getLeftTopPath(rect) - ..lineTo( - rect.right, - rect.bottom, - ) - ..lineTo( - rect.left, - rect.bottom, - ) - ..lineTo( - rect.left, - rect.top, - ); - } - } + Path getOuterPath(Rect rect, {TextDirection? textDirection}) => Path() + ..moveTo(rect.left, rect.bottom) + ..lineTo(rect.left, rect.top) + ..lineTo(rect.right, rect.top) + ..lineTo(rect.right, rect.bottom) + ..lineTo(rect.left, rect.bottom); @override void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) { const lineSize = 30; + final isPortrait = rect.height > rect.width; + final width = rect.width; - final borderWidthSize = width * 10 / 100; + final double borderWidthSize; final height = rect.height; - final borderHeightSize = height - (width - borderWidthSize); + final double borderHeightSize; + + if (isPortrait) { + borderWidthSize = width * 10 / 100; + borderHeightSize = height - (width - borderWidthSize); + } else { + borderHeightSize = height * 10 / 100; + borderWidthSize = width - (height - borderHeightSize); + } + final borderSize = Size(borderWidthSize / 2, borderHeightSize / 2); var paint = Paint() diff --git a/lib/views/qr_scanner_view/qr_scanner_view_widgets/qr_scanner_widget.dart b/lib/views/qr_scanner_view/qr_scanner_view_widgets/qr_scanner_widget.dart index 3dabf889c..d94b1fadd 100644 --- a/lib/views/qr_scanner_view/qr_scanner_view_widgets/qr_scanner_widget.dart +++ b/lib/views/qr_scanner_view/qr_scanner_view_widgets/qr_scanner_widget.dart @@ -1,11 +1,31 @@ +import 'dart:async'; +import 'dart:isolate'; import 'package:flutter/material.dart'; -import 'package:mobile_scanner/mobile_scanner.dart'; +import 'package:camera/camera.dart'; +import 'package:image/image.dart'; +import 'package:privacyidea_authenticator/utils/logger.dart'; +import 'package:zxing2/qrcode.dart'; -import '../../../utils/logger.dart'; +import '../../../utils/image_converter.dart'; import 'qr_code_scanner_overlay.dart'; +/// Args: [SendPort] sendPort, [BinaryBitmap] bitmap +/// Returns: [Result] result or [null] if no QR code was found or [Exception] if an error occurred +void _isolatedDecodeQRCode(List args) { + final SendPort sendPort = args[0] as SendPort; + final BinaryBitmap bitmap = args[1] as BinaryBitmap; + try { + final result = QRCodeReader().decode(bitmap); + sendPort.send(result); + } on NotFoundException catch (_) { + sendPort.send(null); + } catch (e, s) { + Logger.warning('Error decoding QR Code', error: e, stackTrace: s, name: 'QRScannerWidget#_isolatedDecodeQRCode'); + sendPort.send(e); + } +} + class QRScannerWidget extends StatefulWidget { - // final _key = GlobalKey(); const QRScannerWidget({super.key}); @override @@ -13,26 +33,90 @@ class QRScannerWidget extends StatefulWidget { } class _QRScannerWidgetState extends State { - bool alreadyDetected = false; + late Future _controller; + bool _alreadyDetected = false; + Timer? _scanTimer; + + @override + void initState() { + super.initState(); + _controller = _initCamera(); + } + + @override + void dispose() { + _controller.then((controller) => controller.dispose()); + super.dispose(); + } + + Future _initCamera() async { + final cameras = await availableCameras(); + final backCamera = cameras.firstWhere((camera) => camera.lensDirection == CameraLensDirection.back); + final controller = CameraController(backCamera, ResolutionPreset.low, enableAudio: false); + await controller.initialize(); + controller.startImageStream((image) => _scanQrCode(image)); + return controller; + } + + void _scanQrCode(CameraImage cameraImage) async { + if (_alreadyDetected || _scanTimer?.isActive == true) return; + _scanTimer = Timer(const Duration(seconds: 1), () {}); + // currentlyScanning = true; + final image = ImageConverter.fromCameraImage(cameraImage, 0).toImage(); + + LuminanceSource source = RGBLuminanceSource( + image.width, + image.height, + image.convert(numChannels: 4).getBytes(order: ChannelOrder.abgr).buffer.asInt32List(), + ); + var bitmap = BinaryBitmap(GlobalHistogramBinarizer(source)); + Result result; + try { + final decodeResult = await _decodeQRCode(bitmap); + if (decodeResult == null) return; + result = decodeResult; + } on ChecksumException catch (e, s) { + Logger.warning('Error decoding QR Code', error: e, stackTrace: s, name: 'QRScannerWidget#_scanQrCode'); + return; + } catch (e, s) { + Logger.error('Error decoding QR Code', error: e, stackTrace: s, name: 'QRScannerWidget#_scanQrCode'); + return; + } + _alreadyDetected = true; + return _navigatorReturn(result.text); + } + + Future _decodeQRCode(BinaryBitmap bitmap) async { + final receivePort = ReceivePort(); + try { + Isolate.spawn(_isolatedDecodeQRCode, [receivePort.sendPort, bitmap]); + } catch (e) { + receivePort.close(); + } + final result = await receivePort.first; + if (result is Exception) { + throw result; + } + return result as Result?; + } + + void _navigatorReturn(String qrCode) { + Navigator.of(context).pop(qrCode); + } + @override Widget build(BuildContext context) => SizedBox.expand( child: Stack( alignment: Alignment.center, children: [ - MobileScanner( - fit: BoxFit.contain, - controller: MobileScannerController( - // facing: CameraFacing.back, - // torchEnabled: false, - returnImage: false, - ), - onDetect: (capture) { - if (alreadyDetected) return; - alreadyDetected = true; - final List barcodes = capture.barcodes; - Logger.info('Found ${barcodes.length} barcode(s).', name: 'QRScannerWidget#onDetect'); - - Navigator.pop(context, barcodes.first.rawValue); + FutureBuilder( + future: _controller, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + final controller = snapshot.data as CameraController; + return CameraPreview(controller); + } + return const Center(child: CircularProgressIndicator()); }, ), Container( diff --git a/pubspec.lock b/pubspec.lock index 3dab58d5d..35c9cc0b9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,26 +5,26 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051 + sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7" url: "https://pub.dev" source: hosted - version: "64.0.0" + version: "67.0.0" _flutterfire_internals: dependency: transitive description: name: _flutterfire_internals - sha256: "1a52f1afae8ab7ac4741425114713bdbba802f1ce1e0648e167ffcc6e05e96cf" + sha256: "4eec93681221723a686ad580c2e7d960e1017cf1a4e0a263c2573c2c6b0bf5cd" url: "https://pub.dev" source: hosted - version: "1.3.21" + version: "1.3.25" analyzer: dependency: transitive description: name: analyzer - sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893" + sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d" url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "6.4.1" app_minimizer: dependency: "direct main" description: @@ -49,14 +49,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.2" - arrow_path: - dependency: "direct main" - description: - name: arrow_path - sha256: "794651f27eca2e9b4749d307b1e7fb8254fb8343124cc24ee6497f3ceff94651" - url: "https://pub.dev" - source: hosted - version: "3.1.0" asn1lib: dependency: "direct main" description: @@ -149,10 +141,50 @@ packages: dependency: transitive description: name: built_value - sha256: a3ec2e0f967bc47f69f95009bb93db936288d61d5343b9436e378b28a2f830c6 + sha256: fedde275e0a6b798c3296963c5cd224e3e1b55d0e478d5b7e65e6b540f363a0e + url: "https://pub.dev" + source: hosted + version: "8.9.1" + camera: + dependency: "direct main" + description: + name: camera + sha256: "9499cbc2e51d8eb0beadc158b288380037618ce4e30c9acbc4fae1ac3ecb5797" + url: "https://pub.dev" + source: hosted + version: "0.10.5+9" + camera_android: + dependency: transitive + description: + name: camera_android + sha256: "351429510121d179b9aac5a2e8cb525c3cd6c39f4d709c5f72dfb21726e52371" + url: "https://pub.dev" + source: hosted + version: "0.10.8+16" + camera_avfoundation: + dependency: transitive + description: + name: camera_avfoundation + sha256: "8b113e43ee4434c9244c03c905432a0d5956cedaded3cd7381abaab89ce50297" + url: "https://pub.dev" + source: hosted + version: "0.9.14+1" + camera_platform_interface: + dependency: transitive + description: + name: camera_platform_interface + sha256: a250314a48ea337b35909a4c9d5416a208d736dcb01d0b02c6af122be66660b0 + url: "https://pub.dev" + source: hosted + version: "2.7.4" + camera_web: + dependency: transitive + description: + name: camera_web + sha256: f18ccfb33b2a7c49a52ad5aa3f07330b7422faaecbdfd9b9fe8e51182f6ad67d url: "https://pub.dev" source: hosted - version: "8.9.0" + version: "0.3.2+4" characters: dependency: transitive description: @@ -177,14 +209,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.3" - cli_util: - dependency: transitive - description: - name: cli_util - sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19 - url: "https://pub.dev" - source: hosted - version: "0.4.1" clock: dependency: transitive description: @@ -202,7 +226,7 @@ packages: source: hosted version: "4.10.0" collection: - dependency: "direct main" + dependency: transitive description: name: collection sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a @@ -277,10 +301,10 @@ packages: dependency: transitive description: name: dart_style - sha256: "40ae61a5d43feea6d24bd22c0537a6629db858963b99b4bc1c3db80676f32368" + sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" url: "https://pub.dev" source: hosted - version: "2.3.4" + version: "2.3.6" dbus: dependency: transitive description: @@ -321,14 +345,6 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.3" - equatable: - dependency: "direct main" - description: - name: equatable - sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 - url: "https://pub.dev" - source: hosted - version: "2.0.5" expandable: dependency: "direct main" description: @@ -337,14 +353,6 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.1" - extended_nested_scroll_view: - dependency: "direct main" - description: - name: extended_nested_scroll_view - sha256: "835580d40c2c62b448bd14adecd316acba469ba61f1510ef559d17668a85e777" - url: "https://pub.dev" - source: hosted - version: "6.2.1" fake_async: dependency: transitive description: @@ -357,10 +365,10 @@ packages: dependency: transitive description: name: ffi - sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.2" file: dependency: transitive description: @@ -434,13 +442,13 @@ packages: source: hosted version: "0.9.3+1" firebase_core: - dependency: "direct main" + dependency: transitive description: name: firebase_core - sha256: "7e049e32a9d347616edb39542cf92cd53fdb4a99fb6af0a0bff327c14cd76445" + sha256: "53316975310c8af75a96e365f9fccb67d1c544ef0acdbf0d88bbe30eedd1c4f9" url: "https://pub.dev" source: hosted - version: "2.25.4" + version: "2.27.0" firebase_core_platform_interface: dependency: transitive description: @@ -453,34 +461,34 @@ packages: dependency: transitive description: name: firebase_core_web - sha256: "57e61d6010e253b36d38191cefd6199d7849152cdcd234b61ca290cdb278a0ba" + sha256: c8e1d59385eee98de63c92f961d2a7062c5d9a65e7f45bdc7f1b0b205aab2492 url: "https://pub.dev" source: hosted - version: "2.11.4" + version: "2.11.5" firebase_messaging: dependency: "direct main" description: name: firebase_messaging - sha256: "9c97b20c012542252a8853f11334efd833ddae83551fe37d27f87d885c655038" + sha256: e41586e0fd04fe9a40424f8b0053d0832e6d04f49e020cdaf9919209a28497e9 url: "https://pub.dev" source: hosted - version: "14.7.15" + version: "14.7.19" firebase_messaging_platform_interface: dependency: transitive description: name: firebase_messaging_platform_interface - sha256: d464b255e922c7915dc4b0ebc305ebad4e1f130519bee3d6e568ef2ea1613a4b + sha256: f7a9d74ff7fc588a924f6b2eaeaa148b0db521b13a9db55f6ad45864fa98c06e url: "https://pub.dev" source: hosted - version: "4.5.23" + version: "4.5.27" firebase_messaging_web: dependency: transitive description: name: firebase_messaging_web - sha256: f3f71aeec719ec1fe2c99f75cd74d00d33f1c240cf1e402cc9d43883e84f935a + sha256: fc21e771166860c55b103701c5ac7cdb2eec28897b97c42e6e5703cbedf9e02e url: "https://pub.dev" source: hosted - version: "3.6.4" + version: "3.6.8" fixnum: dependency: transitive description: @@ -489,22 +497,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" - flare_flutter: - dependency: "direct main" - description: - name: flare_flutter - sha256: "99d63c60f00fac81249ce6410ee015d7b125c63d8278a30da81edf3317a1f6a0" - url: "https://pub.dev" - source: hosted - version: "3.0.2" fluentui_system_icons: dependency: "direct main" description: name: fluentui_system_icons - sha256: abe7c343e2151e0ad6544653e0b6601686b993bc436ccde72b88cea677db0c0a + sha256: "14c52f5e66620e12803cf7e1514d695474282f0821c9fbae60e6721036dbe1a7" url: "https://pub.dev" source: hosted - version: "1.1.226" + version: "1.1.231" flutter: dependency: "direct main" description: flutter @@ -515,16 +515,8 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_launcher_icons: - dependency: "direct main" - description: - name: flutter_launcher_icons - sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" - url: "https://pub.dev" - source: hosted - version: "0.13.1" flutter_lints: - dependency: "direct main" + dependency: "direct dev" description: name: flutter_lints sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7 @@ -535,10 +527,10 @@ packages: dependency: "direct main" description: name: flutter_local_notifications - sha256: c18f1de98fe0bb9dd5ba91e1330d4febc8b6a7de6aae3ffe475ef423723e72f3 + sha256: f9a05409385b77b06c18f200a41c7c2711ebf7415669350bb0f8474c07bd40d1 url: "https://pub.dev" source: hosted - version: "16.3.2" + version: "17.0.0" flutter_local_notifications_linux: dependency: transitive description: @@ -568,14 +560,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" - flutter_markdown: - dependency: "direct main" - description: - name: flutter_markdown - sha256: "21b085a1c185e46701373866144ced56cfb7a0c33f63c916bb8fe2d0c1491278" - url: "https://pub.dev" - source: hosted - version: "0.6.19" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -588,10 +572,10 @@ packages: dependency: "direct main" description: name: flutter_riverpod - sha256: "4bce556b7ecbfea26109638d5237684538d4abc509d253e6c5c4c5733b360098" + sha256: "0f1974eff5bbe774bf1d870e406fc6f29e3d6f1c46bd9c58e7172ff68a785d7d" url: "https://pub.dev" source: hosted - version: "2.4.10" + version: "2.5.1" flutter_secure_storage: dependency: "direct main" description: @@ -658,6 +642,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_zxing: + dependency: "direct main" + description: + name: flutter_zxing + sha256: ed8da1a0e4650c7645e94b5ab92f855a6b628385d815641761ccbdcaee131683 + url: "https://pub.dev" + source: hosted + version: "1.5.2" flutterlifecyclehooks: dependency: "direct main" description: @@ -743,13 +735,77 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.7" + image_picker: + dependency: transitive + description: + name: image_picker + sha256: "26222b01a0c9a2c8fe02fc90b8208bd3325da5ed1f4a2acabf75939031ac0bdd" + url: "https://pub.dev" + source: hosted + version: "1.0.7" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: "39f2bfe497e495450c81abcd44b62f56c2a36a37a175da7d137b4454977b51b1" + url: "https://pub.dev" + source: hosted + version: "0.8.9+3" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: e2423c53a68b579a7c37a1eda967b8ae536c3d98518e5db95ca1fe5719a730a3 + url: "https://pub.dev" + source: hosted + version: "3.0.2" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: fadafce49e8569257a0cad56d24438a6fa1f0cbd7ee0af9b631f7492818a4ca3 + url: "https://pub.dev" + source: hosted + version: "0.8.9+1" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: "3d2c323daea9d60608f1caf30be32a938916f4975434b8352e6f73dae496da38" + url: "https://pub.dev" + source: hosted + version: "2.9.4" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" integration_test: dependency: "direct dev" description: flutter source: sdk version: "0.0.0" intl: - dependency: "direct main" + dependency: transitive description: name: intl sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" @@ -824,10 +880,10 @@ packages: dependency: "direct main" description: name: local_auth - sha256: "27679ed8e0d7daab2357db6bb7076359e083a56b295c0c59723845301da6aed9" + sha256: "280421b416b32de31405b0a25c3bd42dfcef2538dfbb20c03019e02a5ed55ed0" url: "https://pub.dev" source: hosted - version: "2.1.8" + version: "2.2.0" local_auth_android: dependency: "direct main" description: @@ -836,6 +892,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.37" + local_auth_darwin: + dependency: transitive + description: + name: local_auth_darwin + sha256: "33381a15b0de2279523eca694089393bb146baebdce72a404555d03174ebc1e9" + url: "https://pub.dev" + source: hosted + version: "1.2.2" local_auth_ios: dependency: "direct main" description: @@ -864,10 +928,10 @@ packages: dependency: "direct main" description: name: logger - sha256: "6bbb9d6f7056729537a4309bda2e74e18e5d9f14302489cc1e93f33b3fe32cac" + sha256: b3ff55aeb08d9d8901b767650285872cb1bb8f508373b3e348d60268b0c7f770 url: "https://pub.dev" source: hosted - version: "2.0.2+1" + version: "2.1.0" logging: dependency: transitive description: @@ -880,18 +944,10 @@ packages: dependency: "direct main" description: name: lottie - sha256: "1f0ce68112072d66ea271a9841994fa8d16442e23d8cf8996c9fa74174e58b4e" - url: "https://pub.dev" - source: hosted - version: "3.0.0" - markdown: - dependency: transitive - description: - name: markdown - sha256: "1b134d9f8ff2da15cb298efe6cd8b7d2a78958c1b00384ebcbdf13fe340a6c90" + sha256: ce2bb2605753915080e4ee47f036a64228c88dc7f56f7bc1dbe912d75b55b1e2 url: "https://pub.dev" source: hosted - version: "7.2.1" + version: "3.1.0" matcher: dependency: transitive description: @@ -932,14 +988,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.5" - mobile_scanner: - dependency: "direct main" - description: - name: mobile_scanner - sha256: "619ed5fd43ca9007a151f00c3dc43feedeaf235fe5647735d0237c38849d49dc" - url: "https://pub.dev" - source: hosted - version: "4.0.0" mockito: dependency: "direct dev" description: @@ -1013,7 +1061,7 @@ packages: source: hosted version: "1.9.0" path_provider: - dependency: "direct main" + dependency: transitive description: name: path_provider sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b @@ -1164,7 +1212,7 @@ packages: source: hosted version: "5.0.2" protobuf: - dependency: "direct main" + dependency: "direct dev" description: name: protobuf sha256: "68645b24e0716782e58948f8467fd42a880f255096a821f9e7d0ec625b00c84d" @@ -1191,10 +1239,10 @@ packages: dependency: transitive description: name: riverpod - sha256: "548e2192eb7aeb826eb89387f814edb76594f3363e2c0bb99dd733d795ba3589" + sha256: f21b32ffd26a36555e501b04f4a5dca43ed59e16343f1a30c13632b2351dfa4d url: "https://pub.dev" source: hosted - version: "2.5.0" + version: "2.5.1" shared_preferences: dependency: "direct main" description: @@ -1468,10 +1516,10 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: c512655380d241a337521703af62d2c122bf7b77a46ff7dd750092aa9433499c + sha256: "0ecc004c62fd3ed36a2ffcbe0dd9700aee63bd7532d0b642a488b1ec310f492e" url: "https://pub.dev" source: hosted - version: "6.2.4" + version: "6.2.5" url_launcher_android: dependency: transitive description: @@ -1484,10 +1532,10 @@ packages: dependency: transitive description: name: url_launcher_ios - sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" + sha256: "9149d493b075ed740901f3ee844a38a00b33116c7c5c10d7fb27df8987fb51d5" url: "https://pub.dev" source: hosted - version: "6.2.4" + version: "6.2.5" url_launcher_linux: dependency: transitive description: @@ -1544,14 +1592,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" - visibility_detector: - dependency: transitive - description: - name: visibility_detector - sha256: dd5cc11e13494f432d15939c3aa8ae76844c42b723398643ce9addb88a5ed420 - url: "https://pub.dev" - source: hosted - version: "0.4.0+2" vm_service: dependency: transitive description: @@ -1572,18 +1612,18 @@ packages: dependency: transitive description: name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + sha256: "4188706108906f002b3a293509234588823c8c979dc83304e229ff400c996b05" url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "0.4.2" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + sha256: "939ab60734a4f8fa95feacb55804fa278de28bdeef38e616dc08e44a84adea23" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.3" webdriver: dependency: transitive description: @@ -1604,10 +1644,10 @@ packages: dependency: transitive description: name: win32 - sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8" + sha256: "8cb58b45c47dcb42ab3651533626161d6b67a2921917d8d429791f76972b3480" url: "https://pub.dev" source: hosted - version: "5.2.0" + version: "5.3.0" win32_registry: dependency: transitive description: @@ -1644,10 +1684,10 @@ packages: dependency: "direct main" description: name: zxing2 - sha256: a042961441bd400f59595f9125ef5fca4c888daf0ea59c17f41e0e151f8a12b5 + sha256: "6cf995abd3c86f01ba882968dedffa7bc130185e382f2300239d2e857fc7912c" url: "https://pub.dev" source: hosted - version: "0.2.1" + version: "0.2.3" sdks: - dart: ">=3.2.3 <4.0.0" - flutter: ">=3.16.6" + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.19.0" diff --git a/pubspec.yaml b/pubspec.yaml index 98b1dc8e4..e9215b4db 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -14,7 +14,7 @@ publish_to: none # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 4.3.0+403008 # TODO Set the right version number +version: 4.3.0+403009 # TODO Set the right version number # version: major.minor.build + 2x major|2x minor|3x build # version: version number + build number (optional) # android: build-name + versionCode @@ -28,62 +28,57 @@ dependencies: sdk: flutter flutter_localizations: sdk: flutter - cupertino_icons: ^1.0.4 - - intl: ^0.18.0 + app_minimizer: ^1.0.0+2 + flutter_local_notifications: ^17.0.0 + home_widget: ^0.4.1 + image: ^4.1.6 + json_annotation: ^4.8.1 + local_auth: ^2.1.6 + local_auth_ios: ^1.1.3 + local_auth_android: ^1.0.32 + logger: ^2.0.0 + permission_handler: ^11.0.0 + pi_authenticator_legacy: + path: local_plugins/pi-authenticator-legacy + uuid: ^4.0.0 + zxing2: ^0.2.1 + # Crypto + mutex: ^3.0.0 hex: ^0.2.0 base32: ^2.1.1 + pointycastle: ^3.7.3 + asn1lib: ^1.5.0 + encrypt: ^5.0.3 + cryptography: ^2.7.0 otp: ^3.0.1 + # Storage + file_selector: ^1.0.2 + shared_preferences: ^2.2.0 flutter_secure_storage: ^9.0.0 - flutter_slidable: ^3.0.0 + # Info package_info_plus: ^5.0.1 - asn1lib: ^1.5.0 - flutter_markdown: ^0.6.8 - url_launcher: ^6.0.12 - uuid: ^4.0.0 - http: ^1.1.0 - pointycastle: ^3.7.3 - mutex: ^3.0.0 - flutter_lints: ^3.0.0 - expandable: ^5.0.1 - flutterlifecyclehooks: ^4.0.0 - easy_dynamic_theme: ^2.2.0 - firebase_messaging: ^14.6.4 - firebase_core: ^2.14.0 - pi_authenticator_legacy: - path: local_plugins/pi-authenticator-legacy - collection: ^1.17.2 + device_info_plus: ^9.0.3 + # URI uni_links: ^0.5.1 - local_auth: ^2.1.6 - lottie: ^3.0.0 - flare_flutter: ^3.0.2 + url_launcher: ^6.0.12 + http: ^1.2.0 + connectivity_plus: ^5.0.1 flutter_mailer: ^2.1.1 - permission_handler: ^11.0.0 - path_provider: ^2.0.15 - logger: ^2.0.0 + # Riverpod flutter_riverpod: ^2.3.6 - shared_preferences: ^2.2.0 - flutter_launcher_icons: ^0.13.1 - flutter_local_notifications: ^16.1.0 - extended_nested_scroll_view: ^6.1.2 - local_auth_ios: ^1.1.3 - local_auth_android: ^1.0.32 - connectivity_plus: ^5.0.1 - device_info_plus: ^9.0.3 - json_annotation: ^4.8.1 - equatable: ^2.0.5 - mobile_scanner: ^4.0.0 - arrow_path: ^3.1.0 - protobuf: ^3.1.0 - home_widget: ^0.4.1 - app_minimizer: ^1.0.0+2 - encrypt: ^5.0.3 - cryptography: ^2.7.0 + flutterlifecyclehooks: ^4.0.0 + # Icons + lottie: ^3.0.0 + cupertino_icons: ^1.0.4 fluentui_system_icons: ^1.1.223 - file_selector: ^1.0.2 - zxing2: ^0.2.1 - image: ^4.1.6 material_design_icons_flutter: ^7.0.7296 + # UI + easy_dynamic_theme: ^2.2.0 + flutter_slidable: ^3.0.0 + expandable: ^5.0.1 + camera: ^0.10.5+9 + flutter_zxing: ^1.5.2 + firebase_messaging: ^14.7.19 dev_dependencies: flutter_driver: @@ -92,8 +87,10 @@ dev_dependencies: sdk: flutter integration_test: sdk: flutter + flutter_lints: ^3.0.0 mockito: ^5.4.2 test: ^1.24.1 + protobuf: ^3.1.0 # dependencies to serialize objects to json @@ -125,39 +122,3 @@ flutter: - res/gif/ - res/lottie/ - res/rive/ - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware. - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/assets-and-images/#from-packages - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/custom-fonts/#from-packages - -flutter_launcher_icons: - android: true - image_path: "customization/temp/app_icon.png" - min_sdk_android: 21 # android min sdk min:16, default 21 - adaptive_icon_background: "#FFFFFF" - adaptive_icon_foreground: "customization/temp/app_icon_adaptive.png" - ios: true - image_path_ios: "customization/temp/app_icon_ios.png" - remove_alpha_ios: false # default false \ No newline at end of file