From 325477dab71201da9f437d66d00063a310b77eb1 Mon Sep 17 00:00:00 2001 From: Maxime BEASSE Date: Mon, 5 Feb 2024 00:17:45 +0100 Subject: [PATCH] v1.1.0: Android 34, minor UI improvements and null-safety migration --- .gitattributes | 6 - .gitignore | 7 +- .vscode/settings.json | 12 + .vscode/tasks.json | 2 +- README.md | 12 +- android/app/build.gradle | 17 +- android/app/src/main/AndroidManifest.xml | 10 + .../main/jniLibs/arm64-v8a/libopencv_java4.so | 3 - .../jniLibs/armeabi-v7a/libopencv_java4.so | 3 - .../src/main/jniLibs/x86/libopencv_java4.so | 3 - .../main/jniLibs/x86_64/libopencv_java4.so | 3 - android/build.gradle | 8 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- lib/CropPage.dart | 122 +-- lib/EditorBase.dart | 161 ++-- lib/MeasurePage.dart | 155 ++-- lib/MenuPage.dart | 91 +- lib/ProjectPage.dart | 230 ++--- lib/disclamer_dialog.dart | 10 +- lib/main.dart | 13 +- lib/native_cv/native_cv.dart | 150 ++-- lib/projects/model/projects.dart | 20 +- lib/projects/model/projects.g.dart | 674 ++++++-------- lib/projects/pictures/picture.dart | 4 +- lib/projects/pictures/shapes.dart | 36 +- lib/projects/projectview.dart | 10 +- lib/tutorial_dialog.dart | 19 +- lib/utils/gesture_x_detector.dart | 83 +- lib/utils/utils.dart | 28 +- native_cv/CMakeLists.txt | 17 +- native_cv/core_cv.cpp | 51 +- pubspec.lock | 831 +++++++++++------- pubspec.yaml | 90 +- 33 files changed, 1559 insertions(+), 1324 deletions(-) delete mode 100644 .gitattributes create mode 100644 .vscode/settings.json delete mode 100644 android/app/src/main/jniLibs/arm64-v8a/libopencv_java4.so delete mode 100644 android/app/src/main/jniLibs/armeabi-v7a/libopencv_java4.so delete mode 100644 android/app/src/main/jniLibs/x86/libopencv_java4.so delete mode 100644 android/app/src/main/jniLibs/x86_64/libopencv_java4.so diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index b2541cf..0000000 --- a/.gitattributes +++ /dev/null @@ -1,6 +0,0 @@ -*.so filter=lfs diff=lfs merge=lfs -text -*.jar filter=lfs diff=lfs merge=lfs -text -*.a filter=lfs diff=lfs merge=lfs -text -*.aar filter=lfs diff=lfs merge=lfs -text -*.mp4 filter=lfs diff=lfs merge=lfs -text -opencv2 filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore index 14fbb29..8f89a7a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ .buildlog/ .history .svn/ +.fvm/ # IntelliJ related *.iml @@ -43,4 +44,8 @@ app.*.map.json !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages android/key.properties -*.keystore \ No newline at end of file +*.keystore + +*.bat +*.old +*.so \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9c51797 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,12 @@ +{ + "dart.flutterSdkPath": ".fvm/flutter_sdk", + "dart.flutterSdkPaths": ["E:/SDK/fvm/versions"], + "search.exclude": { + "**/.fvm": true + }, + // Remove from file watching + "files.watcherExclude": { + "**/.fvm": true + }, + "dart.sdkPath": ".fvm/flutter_sdk", +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 01ce798..50eaef5 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -6,7 +6,7 @@ { "label": "Generate Moor Database schema", "type": "shell", - "command": "flutter packages pub run build_runner build" + "command": "fvm flutter packages pub run build_runner build" }, ] diff --git a/README.md b/README.md index 96f4990..917840a 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Developped by [*Maxime BEASSE*](https://twitter.com/maxime_beasse) and [*Quentin In partnership with [FrenchKey](https://intrusion.eu/en/home/) and [CNS](https://www.esiea.fr/expertise-confiance-numerique-securite/) from [ESIEA](https://www.esiea.fr/). -Powered by [Flutter](https://flutter.dev) and [OpenCV (4.3.0)](https://opencv.org/) +Powered by [Flutter (3.13.6)](https://flutter.dev) and [OpenCV (4.3.0)](https://opencv.org/)

@@ -21,7 +21,7 @@ Powered by [Flutter](https://flutter.dev) and [OpenCV (4.3.0)](https://opencv.or # Summary - + * [KeyDecoder](#keydecoder) * [Summary](#summary) * [Disclamer](#disclamer) @@ -71,11 +71,12 @@ If you want to protect yourself from having your keys duplicated without your co ## Build -* Download [Flutter SDK](https://flutter.dev/docs/get-started/install) +* To install Flutter, it is recommended to use [fvm](https://fvm.app/), a Flutter Version Management tool. But you can also use the official [Flutter installation guide](https://flutter.dev/docs/get-started/install). + * The project is built using Flutter `v3.13.6` ### Android -* Download [OpenCV v4.3.0](https://sourceforge.net/projects/opencvlibrary/) +* Download [OpenCV-Android-SDK v4.3.0](https://sourceforge.net/projects/opencvlibrary/files/4.3.0/opencv-4.3.0-android-sdk.zip) and extract it to a directory of your choice. (eg. `C:\SDK\OpenCV-android-sdk`) * Create the `local.properties` file under `android/`, providing the following settings : ```sdk.dir= flutter.sdk= @@ -84,7 +85,8 @@ flutter.versionName=1.0.0 flutter.versionCode=1 opencv.sdk= ``` -* Build the project using `flutter build apk` +* Copy the subdirectories in `C:\...\OpenCV-android-sdk\sdk\native\libs` to the directory `C:\...\keydecoder\android\app\src\main\jniLibs` +* Build the project using `fvm flutter build apk` ### IOS diff --git a/android/app/build.gradle b/android/app/build.gradle index 03c96a2..32e24e0 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -34,7 +34,9 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 29 + namespace "com.keydecoder" + compileSdkVersion 34 + ndkVersion flutter.ndkVersion sourceSets { main.java.srcDirs += 'src/main/kotlin' @@ -45,10 +47,9 @@ android { } defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.keydecoder" - minSdkVersion 21 - targetSdkVersion 29 + minSdkVersion flutter.minSdkVersion + targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName @@ -69,7 +70,7 @@ android { storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null storePassword keystoreProperties['storePassword'] } - } + } buildTypes { release { @@ -84,6 +85,10 @@ android { path file('../../native_cv/CMakeLists.txt') } } + + packagingOptions { + pickFirst '**/libopencv_java4.so' + } } flutter { @@ -91,6 +96,4 @@ flutter { } dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index fd494e6..ff60c41 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@ + + + + + + + + + diff --git a/android/app/src/main/jniLibs/arm64-v8a/libopencv_java4.so b/android/app/src/main/jniLibs/arm64-v8a/libopencv_java4.so deleted file mode 100644 index 10b861a..0000000 --- a/android/app/src/main/jniLibs/arm64-v8a/libopencv_java4.so +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cf364c2214582af130f071d6ef8fd911c12a6ffb7d7505db15be6df2b474fb13 -size 18770760 diff --git a/android/app/src/main/jniLibs/armeabi-v7a/libopencv_java4.so b/android/app/src/main/jniLibs/armeabi-v7a/libopencv_java4.so deleted file mode 100644 index 2be1d31..0000000 --- a/android/app/src/main/jniLibs/armeabi-v7a/libopencv_java4.so +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d2f3927d0c5bad49a7bb531b8a1fef460917a153adb2d521e6f7dfccd9a5b856 -size 10076740 diff --git a/android/app/src/main/jniLibs/x86/libopencv_java4.so b/android/app/src/main/jniLibs/x86/libopencv_java4.so deleted file mode 100644 index ef2d894..0000000 --- a/android/app/src/main/jniLibs/x86/libopencv_java4.so +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b79dd36f3d1c4f885d9ec6e5ae20f235bb44e1c6c15ee0212dda38cb86b5b29f -size 38612828 diff --git a/android/app/src/main/jniLibs/x86_64/libopencv_java4.so b/android/app/src/main/jniLibs/x86_64/libopencv_java4.so deleted file mode 100644 index f308b1d..0000000 --- a/android/app/src/main/jniLibs/x86_64/libopencv_java4.so +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a84cc05b4da3e7c71b8eb255f39910c88670f39ed56d84d792328c0824a68dbb -size 53690632 diff --git a/android/build.gradle b/android/build.gradle index 3100ad2..58001d1 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,12 +1,12 @@ buildscript { - ext.kotlin_version = '1.3.50' + ext.kotlin_version = '1.8.10' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.0' + classpath 'com.android.tools.build:gradle:7.1.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } @@ -21,11 +21,9 @@ allprojects { rootProject.buildDir = '../build' subprojects { project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 01a286e..388b1cb 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip \ No newline at end of file diff --git a/lib/CropPage.dart b/lib/CropPage.dart index 8c750f6..fae5778 100644 --- a/lib/CropPage.dart +++ b/lib/CropPage.dart @@ -22,7 +22,7 @@ class CropPage extends StatefulWidget { final Uint8List imageData; static const routeName = '/crop'; - static Route route(Object args) { + static Route route(Object? args) { return MaterialPageRoute( builder: (BuildContext context) { if (args is File) @@ -40,7 +40,7 @@ class CropPageState extends State { GlobalKey editorKey = GlobalKey(); - ShapeNotifier shapeNotifier; + late ShapeNotifier shapeNotifier; bool _canAdd = true; bool _canRemove = false; @@ -49,6 +49,8 @@ class CropPageState extends State { bool _portrait = false; Size imageSize = Size.zero; + + bool _loadingCrop = false; EditorBaseState get _editorBaseState => (editorKey.currentState as EditorBaseState); @@ -66,11 +68,11 @@ class CropPageState extends State { shapeNotifier.lineShapes.last.b = shapeNotifier.draggableShapes[1].center; }); - img.Image image = img.decodeImage(widget.imageData); + img.Image? image = img.decodeImage(widget.imageData); - imageSize = Size(image.width.toDouble(), image.height.toDouble()); + imageSize = Size(image!.width.toDouble(), image.height.toDouble()); - final orientation = (image.exif.hasOrientation) ? image.exif.orientation : 1; + final orientation = (image.exif.imageIfd.hasOrientation) ? image.exif.imageIfd.Orientation : 1; switch (orientation) { case 1: @@ -102,7 +104,7 @@ class CropPageState extends State { void addLine() { - if (shapeNotifier?.lineShapes?.length == 4) { + if (shapeNotifier.lineShapes.length == 4) { if(!_canAccept || _canAdd) { setState(() { _canAccept = true; @@ -117,7 +119,7 @@ class CropPageState extends State { double longestSide = mediaSize.longestSide; double shortestSide = mediaSize.shortestSide; - double scaleFactor = _editorBaseState.scaleFactor; + double scaleFactor = _editorBaseState.scaleFactor!; final Paint _cropPaint = Paint() ..color = Colors.green @@ -183,7 +185,7 @@ class CropPageState extends State { shapeNotifier.draggableShapes[1].center = lastLine.b; } else { - double scaleFactor = _editorBaseState.scaleFactor; + double scaleFactor = _editorBaseState.scaleFactor!; final Paint _cropPaint = Paint() ..color = Colors.green @@ -239,7 +241,7 @@ class CropPageState extends State { title: Text('Wrong number of corners'), content: Text('Please fix your crop to have 4 corners within the image bounds'), actions: [ - FlatButton( + TextButton( child: Text('Ok'), onPressed: Navigator.of(context)?.pop, ) @@ -248,6 +250,10 @@ class CropPageState extends State { barrierDismissible: true, ); } + + setState(() { + _loadingCrop = true; + }); // Sort points and return DartIntersection DartIntersection dinter = _computeClosedPath(intersections); @@ -270,6 +276,8 @@ class CropPageState extends State { int res = await HomographyWarp.homographyWarp(dinter, widget.imageFile.path, resultPath); + _loadingCrop = false; + if (res < 0) throw Exception('homographyWarp failed'); @@ -339,7 +347,7 @@ class CropPageState extends State { @override void dispose() { - shapeNotifier?.dispose(); + shapeNotifier.dispose(); super.dispose(); } @@ -347,46 +355,60 @@ class CropPageState extends State { Widget build(BuildContext context) { return Center( child: Stack( - fit: StackFit.expand, - children: [ - EditorBase( - key: editorKey, - imageData: widget.imageData, - shapes: shapeNotifier, - portrait: _portrait, - onInitialization: addLine - ), - Align( - alignment: Alignment.bottomRight, - child: Column( - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisAlignment: MainAxisAlignment.end, - mainAxisSize: MainAxisSize.max, - children: [ - VisibleButton( - child: Icon(Icons.undo, size: 56.0, color: Colors.red[600],), - onTap: removeLine, - visible: _canRemove, - ), - VisibleButton( - child: Icon(Icons.add, size: 56.0, color: Colors.white70,), - onTap: addLine, - visible: _canAdd, - keepSpace: true - ), - ], - ) - ), - Align( - alignment: Alignment.topLeft, - child: VisibleButton( - child: Icon(Icons.check, size: 56.0, color: Colors.green,), - onTap: cropImage, - visible: _canAccept, - ), - ) - ], - ), + fit: StackFit.expand, + children: [ + EditorBase( + key: editorKey, + imageData: widget.imageData, + shapes: shapeNotifier, + portrait: _portrait, + onInitialization: addLine + ), + Align( + alignment: Alignment.bottomRight, + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: MainAxisSize.max, + children: [ + VisibleButton( + child: Icon(Icons.undo, size: 56.0, color: Colors.red[600],), + onTap: removeLine, + visible: _canRemove, + ), + VisibleButton( + child: Icon(Icons.add, size: 56.0, color: Colors.white70,), + onTap: addLine, + visible: _canAdd, + keepSpace: true + ), + ], + ) + ), + Align( + alignment: Alignment.topRight, + child: _loadingCrop ? const CircularProgressIndicator() : VisibleButton( + child: Icon(Icons.check, size: 56.0, color: Colors.green,), + onTap: cropImage, + visible: _canAccept, + ), + ), + Align( + alignment: Alignment.topLeft, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + "Crop the card", + style: TextStyle( + color: Colors.white, + decoration: TextDecoration.none, + fontSize: 16.0 + ) + ), + ), + ), + ], + ), ); } } \ No newline at end of file diff --git a/lib/EditorBase.dart b/lib/EditorBase.dart index d117d16..3cda1ba 100644 --- a/lib/EditorBase.dart +++ b/lib/EditorBase.dart @@ -1,10 +1,7 @@ import 'dart:io'; -import 'dart:ui'; -import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:moor_flutter/moor_flutter.dart'; import 'package:provider/provider.dart'; import 'projects/pictures/shapes.dart'; import 'utils/gesture_x_detector.dart'; @@ -27,15 +24,12 @@ class ShapeNotifier extends ChangeNotifier { List get all => miscellaneous + lineShapes + draggableShapes + markers; void rescaleDelta(double scaleDelta) { - all?.forEach((element) { - if (element == null) - return; - + all.forEach((element) { if (element is Circle) element.radius = element.radius / scaleDelta; if (element is Crosshair) { - if (element.textStyle?.fontSize != null) + if (element.textStyle.fontSize != null) element.textPainter.textScaleFactor /= scaleDelta; } @@ -43,16 +37,14 @@ class ShapeNotifier extends ChangeNotifier { } void rescale(double scale) { - all?.forEach((element) { - if (element == null) - return; + all.forEach((element) { if (element is Crosshair) { element.paint.strokeWidth = Crosshair.strokeWidth / scale; element.size = element.baseSize / scale; } else - element.paint?.strokeWidth = Shape.strokeWidth / scale; + element.paint.strokeWidth = Shape.strokeWidth / scale; }); } @@ -68,7 +60,7 @@ class EditorPainter extends CustomPainter { EditorPainter(this.context, {this.shapes}); final BuildContext context; - final List shapes; + final List? shapes; @override void paint(Canvas canvas, Size size) { @@ -76,7 +68,7 @@ class EditorPainter extends CustomPainter { if (shapes == null) return; - for (var shape in shapes) { + for (var shape in shapes!) { if (shape == null || shape.hidden) continue; shape.draw(canvas, context); @@ -88,10 +80,10 @@ class EditorPainter extends CustomPainter { } class _ValueUpdater { - final T Function(T oldValue, T newValue) onUpdate; - T value; + final T Function(T? oldValue, T? newValue) onUpdate; + T? value; - _ValueUpdater({this.onUpdate}); + _ValueUpdater({required this.onUpdate}); T update(T newValue) { T updated = onUpdate(value, newValue); @@ -103,9 +95,9 @@ class _ValueUpdater { class EditorBase extends StatefulWidget { EditorBase({ - Key key, - this.imageData, - this.shapes, + Key? key, + required this.imageData, + required this.shapes, this.portrait = false, this.onInitialization, this.onRotation, @@ -113,8 +105,8 @@ class EditorBase extends StatefulWidget { }) : super(key: key); EditorBase.fromFile({ - Key key, - File imageFile, + Key? key, + required File imageFile, this.shapes, this.portrait = false, this.onInitialization, @@ -122,20 +114,17 @@ class EditorBase extends StatefulWidget { this.onTap }) : imageData = imageFile.readAsBytesSync(), super(key: key); - @required final Uint8List imageData; - @required - final ShapeNotifier shapes; + final ShapeNotifier? shapes; - @required final bool portrait; - final void Function() onInitialization; + final void Function()? onInitialization; - final void Function(double) onRotation; + final void Function(double)? onRotation; - final void Function(Offset) onTap; + final void Function(Offset)? onTap; /// touch radius in centimeter static const double touchDiameterCm = 0.60; @@ -149,12 +138,12 @@ class EditorBase extends StatefulWidget { static const double strokeWidth = Shape.strokeWidth; static Future initEditorBase() async { - await SystemChrome.setEnabledSystemUIOverlays([]); + await SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: [SystemUiOverlay.bottom]); return landscapeModeOnly(); } static Future disposeEditorBase() async { - await SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values); + await SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: SystemUiOverlay.values); return enableRotation(); } @@ -166,54 +155,58 @@ class EditorBaseState extends State { GlobalKey painterKey = GlobalKey(); - void Function() onInitialization; + void Function()? onInitialization; - Circle _drag; + Circle? _drag; Matrix4 translationDeltaMatrix = Matrix4.identity(); Matrix4 scaleDeltaMatrix = Matrix4.identity(); Matrix4 rotationDeltaMatrix = Matrix4.identity(); Matrix4 matrix = Matrix4.identity(); - MediaQueryData _mediaQuery; - Size _mediaQuerySize; + MediaQueryData? _mediaQuery; + Size? _mediaQuerySize; double _initScale = 1.0; - bool _fromPortrait; + bool? _fromPortrait; - Size _imageSize; + Size? _imageSize; GlobalKey _imageKey = GlobalKey(debugLabel: 'image global key'); GlobalKey _baseKey = GlobalKey(debugLabel: 'base global key'); - RenderBox get imageRenderBox => _imageKey?.currentContext?.findRenderObject(); + RenderBox? get imageRenderBox => _imageKey.currentContext?.findRenderObject() as RenderBox?; - RenderObject get ancestor => _baseKey?.currentContext?.findRenderObject(); + RenderObject? get ancestor => _baseKey.currentContext?.findRenderObject(); - double get scaleFactor => imageRenderBox.getTransformTo(ancestor).getColumn(0).length; + double? get scaleFactor => imageRenderBox?.getTransformTo(ancestor).getColumn(0).length; - double get isoRatio => (ISOheight / _imageSize.height); + double get isoRatio => _imageSize != null ? (ISOheight / _imageSize!.height) : 0; double px2mm(double dist) { return dist * isoRatio; } double get angle { - Matrix4 m = imageRenderBox.getTransformTo(null); - Matrix3 m3 = m.getRotation().scaled(1/scaleFactor); + Matrix4 m = imageRenderBox!.getTransformTo(null); + Matrix3 m3 = m.getRotation().scaled(1/scaleFactor!); double res = acos((m3.trace()-1)/2); return res.isNaN ? pi : res; } + bool _editorLoaded = false; + @override void initState() { - img.Image image = img.decodeImage(widget.imageData); - _imageSize = Size(image.width.toDouble(), image.height.toDouble()); + EditorBase.initEditorBase().then((value) => setState(() => _editorLoaded = true)); - if(widget.portrait && _imageSize.width > _imageSize.height) - _imageSize = _imageSize.flipped; + img.Image? image = img.decodeImage(widget.imageData); + _imageSize = Size(image!.width.toDouble(), image.height.toDouble()); + + if(widget.portrait && _imageSize!.width > _imageSize!.height) + _imageSize = _imageSize!.flipped; onInitialization = widget.onInitialization; @@ -227,33 +220,33 @@ class EditorBaseState extends State { Offset globalToLocal(Offset o) { - if (imageRenderBox == null) + if (imageRenderBox == null || _fromPortrait == null) return Offset.zero; Offset out = (widget.portrait) ? Offset(o.dy, o.dx) : Offset(o.dx, o.dy); - Offset globalZero = imageRenderBox.localToGlobal(Offset.zero, ancestor: ancestor); - Offset localZero = imageRenderBox.globalToLocal(Offset.zero, ancestor: ancestor); + Offset globalZero = imageRenderBox!.localToGlobal(Offset.zero, ancestor: ancestor); + Offset localZero = imageRenderBox!.globalToLocal(Offset.zero, ancestor: ancestor); - if (_fromPortrait) { + if (_fromPortrait!) { if (widget.portrait) { - out = out.scale(-1, 1).translate(_mediaQuerySize.shortestSide, 0); - out = imageRenderBox.globalToLocal(out, ancestor: ancestor); + out = out.scale(-1, 1).translate(_mediaQuerySize!.shortestSide, 0); + out = imageRenderBox!.globalToLocal(out, ancestor: ancestor); } else { - localZero = invertOffset(imageRenderBox.globalToLocal(globalZero, ancestor: ancestor)); + localZero = invertOffset(imageRenderBox!.globalToLocal(globalZero, ancestor: ancestor)); if (matrix.isIdentity()) out += globalZero; - out = imageRenderBox.globalToLocal(out, ancestor: ancestor); + out = imageRenderBox!.globalToLocal(out, ancestor: ancestor); } } else { if (widget.portrait) { localZero = Offset.zero; - out = out.scale(-1, 1).translate(_mediaQuerySize.shortestSide, 0); + out = out.scale(-1, 1).translate(_mediaQuerySize!.shortestSide, 0); } else { - localZero = imageRenderBox.globalToLocal(globalZero, ancestor: ancestor); + localZero = imageRenderBox!.globalToLocal(globalZero, ancestor: ancestor); } - out = imageRenderBox.globalToLocal(out, ancestor: ancestor) - localZero; + out = imageRenderBox!.globalToLocal(out, ancestor: ancestor) - localZero; } return out; @@ -261,7 +254,7 @@ class EditorBaseState extends State { void _onMoveStart(int pointer, Offset localPos, Offset position) { - if (localPos == null || imageRenderBox == null) + if (imageRenderBox == null) return; int closest = -1; @@ -269,7 +262,7 @@ class EditorBaseState extends State { Offset transformed = globalToLocal(localPos); - final _draggable = widget.shapes.draggableShapes; + final _draggable = widget.shapes!.draggableShapes; for (int i = 0; i < _draggable.length; i++) { Circle elt = _draggable[i]; @@ -286,7 +279,7 @@ class EditorBaseState extends State { if (closest < 0) { if (widget.onTap != null) - widget.onTap(transformed); + widget.onTap!(transformed); return; } @@ -307,12 +300,12 @@ class EditorBaseState extends State { matrix = translationDeltaMatrix * matrix; }); - widget.shapes.changed(); + widget.shapes!.changed(); } else { setState(() { - _drag.center = globalToLocal(position); - widget.shapes.changed(); + _drag!.center = globalToLocal(position); + widget.shapes!.changed(); }); } } @@ -326,17 +319,23 @@ class EditorBaseState extends State { @override Widget build(BuildContext context) { + if (!_editorLoaded) { + return Center( + child: CircularProgressIndicator(), + ); + } + if (_mediaQuery == null) { _mediaQuery = MediaQuery.of(context); - _mediaQuerySize = _mediaQuery.size; + _mediaQuerySize = _mediaQuery!.size; - if ((_mediaQuerySize.width > _mediaQuerySize.height && _imageSize.width > _imageSize.height) - || (_mediaQuerySize.width < _mediaQuerySize.height && _imageSize.width < _imageSize.height)) { + if ((_mediaQuerySize!.width > _mediaQuerySize!.height && _imageSize!.width > _imageSize!.height) + || (_mediaQuerySize!.width < _mediaQuerySize!.height && _imageSize!.width < _imageSize!.height)) { // When launching portrait in portrait mode // or launching landscape in landscape mode _fromPortrait = widget.portrait; - _mediaQuerySize = _mediaQuerySize.flipped; + _mediaQuerySize = _mediaQuerySize!.flipped; } else { // When launching portrait in landscape mode @@ -344,15 +343,15 @@ class EditorBaseState extends State { _fromPortrait = !widget.portrait; } - _initScale = _mediaQuerySize.shortestSide / _imageSize.shortestSide; + _initScale = _mediaQuerySize!.shortestSide / _imageSize!.shortestSide; } - Size imageSize = _imageSize; + Size imageSize = _imageSize!; return WillPopScope( onWillPop: _onWillPop, child: ChangeNotifierProvider.value( - value: widget.shapes, + value: widget.shapes!, child: XGestureDetector( onScaleStart: onScaleStart, onScaleUpdate: onScaleUpdate, @@ -394,7 +393,7 @@ class EditorBaseState extends State { else { if (onInitialization != null) { WidgetsBinding.instance.addPostFrameCallback((timeStamp) { - onInitialization(); + onInitialization!(); onInitialization = null; }); } @@ -410,7 +409,7 @@ class EditorBaseState extends State { builder: (painterContext, value, child) { return CustomPaint( key: painterKey, - size: _imageSize, + size: _imageSize!, painter: EditorPainter(painterContext, shapes: value.all), ); }, @@ -434,13 +433,13 @@ class EditorBaseState extends State { } _ValueUpdater translationUpdater = _ValueUpdater( - onUpdate: (oldVal, newVal) => newVal - oldVal, + onUpdate: (oldVal, newVal) => newVal! - oldVal!, ); _ValueUpdater rotationUpdater = _ValueUpdater( - onUpdate: (oldVal, newVal) => newVal - oldVal, + onUpdate: (oldVal, newVal) => newVal! - oldVal!, ); _ValueUpdater scaleUpdater = _ValueUpdater( - onUpdate: (oldVal, newVal) => newVal / oldVal, + onUpdate: (oldVal, newVal) => newVal! / oldVal!, ); void onScaleStart(Offset focalPoint) { @@ -472,13 +471,13 @@ class EditorBaseState extends State { scaleDeltaMatrix = _scale(scaleDelta, focalPoint); matrix = scaleDeltaMatrix * matrix; - widget.shapes.rescaleDelta(scaleDelta); - widget.shapes.rescale(scaleFactor); + widget.shapes!.rescaleDelta(scaleDelta); + widget.shapes!.rescale(scaleFactor!); } // handle matrix rotating if (rotation != 0.0) { - if (rotationUpdater.value.isNaN) { + if (rotationUpdater.value!.isNaN) { rotationUpdater.value = rotation; } else { double rotationDelta = rotationUpdater.update(rotation); @@ -486,11 +485,11 @@ class EditorBaseState extends State { matrix = rotationDeltaMatrix * matrix; if(widget.onRotation != null) - widget.onRotation(rotationDelta); + widget.onRotation!(rotationDelta); } } - widget.shapes.changed(); + widget.shapes!.changed(); setState(() {}); } diff --git a/lib/MeasurePage.dart b/lib/MeasurePage.dart index cee2777..624aa9c 100644 --- a/lib/MeasurePage.dart +++ b/lib/MeasurePage.dart @@ -7,6 +7,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:fluttericon/entypo_icons.dart'; import 'package:keydecoder/projects/model/projects.dart'; +import 'package:drift/drift.dart' as drift; import 'EditorBase.dart'; import 'package:image/image.dart' as img; import 'projects/pictures/shapes.dart' hide Rect; @@ -21,7 +22,7 @@ class MeasurePage extends StatefulWidget { final Project project; static const routeName = '/measure'; - static Route route(Object args) { + static Route route(Object? args) { return MaterialPageRoute( builder: (BuildContext context) { if (args is Project) @@ -39,37 +40,39 @@ class MeasurePageState extends State { GlobalKey editorKey = GlobalKey(); - ShapeNotifier shapeNotifier; + ShapeNotifier shapeNotifier = ShapeNotifier(); bool _canAdd = true; bool _canRemove = false; bool _canAccept = false; - Size imageSize; + late Size imageSize; - Uint8List _imageData; + late Uint8List _imageData; final ValueNotifier _currentStep = ValueNotifier(0); int _curStep = 0; - Matrix4 _subMatrix; + late Matrix4 _subMatrix; double _baseAngle = 0.0; - double _mAngle; + double? _mAngle; List _markers = List.empty(growable: true); final Color _colorDisable = Color(0xFFe0f2f1); - final Color _colorActive = Colors.lightBlue[400]; - final Color _colorDone = Colors.lightGreen[400]; + final Color _colorActive = Colors.lightBlue.shade400; + final Color _colorDone = Colors.lightGreen.shade400; + + late Project curProject; - EditorBaseState get _editorBaseState => (editorKey.currentState as EditorBaseState); + EditorBaseState? get _editorBaseState => (editorKey.currentState as EditorBaseState?); String _coordinates = ''; @override void initState() { - shapeNotifier = ShapeNotifier(); + curProject = widget.project; // Snaps daggrable circles to current line shapeNotifier.addListener(() { @@ -84,10 +87,10 @@ class MeasurePageState extends State { shapeNotifier.lineShapes.last.b = shapeNotifier.draggableShapes[1].center; }); - _imageData = File(widget.project.pathCroppedPic).readAsBytesSync(); + _imageData = File(curProject.pathCroppedPic).readAsBytesSync(); - img.Image image = img.decodeImage(_imageData); - imageSize = Size(image.width.toDouble(), image.height.toDouble()); + img.Image? image = img.decodeImage(_imageData); + imageSize = Size(image!.width.toDouble(), image.height.toDouble()); super.initState(); @@ -115,13 +118,13 @@ class MeasurePageState extends State { void initStep() { - if (widget.project.markers == null) + if (curProject.markers == null) return; - _mAngle = _baseAngle + widget.project.angle; - Offset origin = Offset(widget.project.originX, widget.project.originY); + _mAngle = _baseAngle + curProject.angle!; + Offset origin = Offset(curProject.originX!, curProject.originY!); - double angle = _mAngle - _baseAngle; + double angle = _mAngle! - _baseAngle; angle = (angle < -pi) ? angle + 2*pi: angle; angle = (angle > pi) ? angle - 2*pi: angle; @@ -131,19 +134,19 @@ class MeasurePageState extends State { shapeNotifier.draggableShapes.clear(); final Paint _mainAxisPaint = Paint() - ..color = Colors.red[600] - ..strokeWidth = EditorBase.strokeWidth / _editorBaseState.scaleFactor + ..color = Colors.red.shade600 + ..strokeWidth = EditorBase.strokeWidth / _editorBaseState!.scaleFactor! ..style = PaintingStyle.stroke; Line mainAxis = Line.fromAngle( origin, - _mAngle, + _mAngle!, _mainAxisPaint ); final Paint _crossAxisPaint = Paint() - ..color = Colors.blue[600] - ..strokeWidth = EditorBase.strokeWidth / _editorBaseState.scaleFactor + ..color = Colors.blue.shade600 + ..strokeWidth = EditorBase.strokeWidth / _editorBaseState!.scaleFactor! ..style = PaintingStyle.stroke; Line crossAxis = Line.perpendicular( @@ -157,15 +160,15 @@ class MeasurePageState extends State { shapeNotifier.markers.clear(); - _markers = fromBlob(widget.project.markers); + _markers = fromBlob(curProject.markers!); _markers.forEach((center) { addMarker(center); }); shapeNotifier.addListener(() { - Offset coords = _editorBaseState.globalToLocal(MediaQuery.of(context).size.center(Offset.zero)); + Offset coords = _editorBaseState!.globalToLocal(MediaQuery.of(context).size.center(Offset.zero)); coords = transformOffset(Matrix4.inverted(_subMatrix), coords); - coords = Offset(_editorBaseState.px2mm(coords.dx), _editorBaseState.px2mm(coords.dy)); + coords = Offset(_editorBaseState!.px2mm(coords.dx), _editorBaseState!.px2mm(coords.dy)); setState(() { _coordinates = "${coords.dx.toStringAsFixed(3)}, ${coords.dy.toStringAsFixed(3)}"; }); @@ -185,14 +188,16 @@ class MeasurePageState extends State { void nextStep() { switch (_curStep) { - case 3: - Navigator.of(context).pop(); + case 3: + updateDB().then((_) { + Navigator.of(context).pop(); + }); break; case 2: shapeNotifier.draggableShapes.clear(); - shapeNotifier.lineShapes[1].b = shapeNotifier.lineShapes[0].xtersect(shapeNotifier.lineShapes[1]); + shapeNotifier.lineShapes[1].b = shapeNotifier.lineShapes[0].xtersect(shapeNotifier.lineShapes[1])!; Offset origin = shapeNotifier.lineShapes[1].b; setState(() { @@ -202,23 +207,25 @@ class MeasurePageState extends State { _canAccept = true; }); - widget.project.originX = origin.dx; - widget.project.originY = origin.dy; - widget.project.angle = shapeNotifier.lineShapes[0].mAngle; - widget.project.isoRatio = _editorBaseState.isoRatio; + curProject = curProject.copyWith( + originX: drift.Value(origin.dx), + originY: drift.Value(origin.dy), + angle: drift.Value(shapeNotifier.lineShapes[0].mAngle), + isoRatio: drift.Value(_editorBaseState!.isoRatio) + ); - ProjectsDatabase.dao.updateProject(widget.project); + ProjectsDatabase.dao.updateProject(curProject); - double angle = _mAngle - _baseAngle; + double angle = _mAngle! - _baseAngle; angle = (angle < -pi) ? angle + 2*pi: angle; angle = (angle > pi) ? angle - 2*pi: angle; _subMatrix = Matrix4.translationValues(origin.dx, origin.dy, 0.0)..rotateZ(angle); shapeNotifier.addListener(() { - Offset coords = _editorBaseState.globalToLocal(MediaQuery.of(context).size.center(Offset.zero)); + Offset coords = _editorBaseState!.globalToLocal(MediaQuery.of(context).size.center(Offset.zero)); coords = transformOffset(Matrix4.inverted(_subMatrix), coords); - coords = Offset(_editorBaseState.px2mm(coords.dx), _editorBaseState.px2mm(coords.dy)); + coords = Offset(_editorBaseState!.px2mm(coords.dx), _editorBaseState!.px2mm(coords.dy)); setState(() { _coordinates = "${coords.dx.toStringAsFixed(3)}, ${coords.dy.toStringAsFixed(3)}"; }); @@ -232,19 +239,19 @@ class MeasurePageState extends State { } final Paint _crossAxisPaint = Paint() - ..color = Colors.blue[600] - ..strokeWidth = EditorBase.strokeWidth / _editorBaseState.scaleFactor + ..color = Colors.blue.shade600 + ..strokeWidth = EditorBase.strokeWidth / _editorBaseState!.scaleFactor! ..style = PaintingStyle.stroke; Line crossAxis = Line.perpendicular(shapeNotifier.lineShapes.first, - _editorBaseState.globalToLocal(MediaQuery.of(context).size.center(Offset.zero)), + _editorBaseState!.globalToLocal(MediaQuery.of(context).size.center(Offset.zero)), _crossAxisPaint ); shapeNotifier.lineShapes.add(crossAxis); shapeNotifier.draggableShapes.clear(); - shapeNotifier.draggableShapes.add(Circle(crossAxis.a, EditorBase.touchRadius / _editorBaseState.scaleFactor, _crossAxisPaint)); + shapeNotifier.draggableShapes.add(Circle(crossAxis.a, EditorBase.touchRadius / _editorBaseState!.scaleFactor!, _crossAxisPaint)); setState(() { _canAdd = true; @@ -260,18 +267,18 @@ class MeasurePageState extends State { double longestSide = mediaSize.longestSide; double shortestSide = mediaSize.shortestSide; - double scaleFactor = _editorBaseState.scaleFactor; + double scaleFactor = _editorBaseState!.scaleFactor!; final Paint _mainAxisPaint = Paint() - ..color = Colors.red[600] - ..strokeWidth = EditorBase.strokeWidth / _editorBaseState.scaleFactor + ..color = Colors.red.shade600 + ..strokeWidth = EditorBase.strokeWidth / _editorBaseState!.scaleFactor! ..style = PaintingStyle.stroke; if (shapeNotifier.lineShapes.isEmpty) { Line mainAxis = Line( - _editorBaseState.globalToLocal(Offset(longestSide * 1/4, shortestSide * 1/2)), - _editorBaseState.globalToLocal(Offset(longestSide * 3/4, shortestSide * 1/2)), + _editorBaseState!.globalToLocal(Offset(longestSide * 1/4, shortestSide * 1/2)), + _editorBaseState!.globalToLocal(Offset(longestSide * 3/4, shortestSide * 1/2)), _mainAxisPaint ); @@ -305,11 +312,13 @@ class MeasurePageState extends State { switch (_curStep) { case 1: - widget.project.originX = null; - widget.project.originX = null; - widget.project.angle = null; - widget.project.markers = null; - ProjectsDatabase.dao.updateProject(widget.project); + curProject = curProject.copyWith( + originX: drift.Value(null), + originY: drift.Value(null), + angle: drift.Value(null), + markers: drift.Value(null), + ); + ProjectsDatabase.dao.updateProject(curProject); shapeNotifier.markers.clear(); _markers.clear(); @@ -317,8 +326,8 @@ class MeasurePageState extends State { _mAngle = null; final Paint _crossAxisPaint = Paint() - ..color = Colors.blue[600] - ..strokeWidth = EditorBase.strokeWidth / _editorBaseState.scaleFactor + ..color = Colors.blue.shade600 + ..strokeWidth = EditorBase.strokeWidth / _editorBaseState!.scaleFactor! ..style = PaintingStyle.stroke; Line crossAxis = shapeNotifier.lineShapes[1]; @@ -326,7 +335,7 @@ class MeasurePageState extends State { shapeNotifier.lineShapes.add(crossAxis); shapeNotifier.draggableShapes.clear(); - shapeNotifier.draggableShapes.add(Circle(crossAxis.a, EditorBase.touchRadius / _editorBaseState.scaleFactor, _crossAxisPaint)); + shapeNotifier.draggableShapes.add(Circle(crossAxis.a, EditorBase.touchRadius / _editorBaseState!.scaleFactor!, _crossAxisPaint)); setState(() { _canAdd = true; @@ -342,18 +351,18 @@ class MeasurePageState extends State { double longestSide = mediaSize.longestSide; double shortestSide = mediaSize.shortestSide; - double scaleFactor = _editorBaseState.scaleFactor; + double scaleFactor = _editorBaseState!.scaleFactor!; final Paint _mainAxisPaint = Paint() - ..color = Colors.red[600] + ..color = Colors.red.shade600 ..strokeWidth = EditorBase.strokeWidth / scaleFactor ..style = PaintingStyle.stroke; if (shapeNotifier.lineShapes.isEmpty) { Line mainAxis = Line( - _editorBaseState.globalToLocal(Offset(longestSide * 1/4, shortestSide * 1/2)), - _editorBaseState.globalToLocal(Offset(longestSide * 3/4, shortestSide * 1/2)), + _editorBaseState!.globalToLocal(Offset(longestSide * 1/4, shortestSide * 1/2)), + _editorBaseState!.globalToLocal(Offset(longestSide * 3/4, shortestSide * 1/2)), _mainAxisPaint ); @@ -383,21 +392,21 @@ class MeasurePageState extends State { } } - void addMarker([Offset center]) { + void addMarker([Offset? center]) { - double angle = _mAngle - _baseAngle; + double angle = _mAngle! - _baseAngle; angle = (angle < -pi) ? angle + 2*pi: angle; angle = (angle > pi) ? angle - 2*pi: angle; - Offset _offset = center ?? _editorBaseState.globalToLocal(MediaQuery.of(context).size.center(Offset.zero)); + Offset _offset = center ?? _editorBaseState!.globalToLocal(MediaQuery.of(context).size.center(Offset.zero)); Matrix4 m = Matrix4.inverted(_subMatrix); Offset transformedCenter = transformOffset(m, _offset); - Crosshair ch = Crosshair(_offset, angle, transformedCenter * _editorBaseState.isoRatio, Crosshair.markerPaint, _editorBaseState.scaleFactor); + Crosshair ch = Crosshair(_offset, angle, transformedCenter * _editorBaseState!.isoRatio, Crosshair.markerPaint, _editorBaseState!.scaleFactor!); - ch.size = ch.baseSize / _editorBaseState.scaleFactor; - ch.paint.strokeWidth = Crosshair.strokeWidth / _editorBaseState.scaleFactor; + ch.size = ch.baseSize / _editorBaseState!.scaleFactor!; + ch.paint.strokeWidth = Crosshair.strokeWidth / _editorBaseState!.scaleFactor!; if (center != null) { shapeNotifier.markers.add(ch); @@ -427,10 +436,10 @@ class MeasurePageState extends State { void removeMarker(Offset position) { - Crosshair ch; + Crosshair? ch; - ch = shapeNotifier.markers.firstWhere( - (element) => (element.center - position).distance < (element.size), + ch = shapeNotifier.markers.cast().firstWhere( + (element) => (element!.center - position).distance < (element.size), orElse: () => null ); @@ -449,14 +458,14 @@ class MeasurePageState extends State { updateDB(); } - void updateDB() { - widget.project.markers = toBlob(_markers); - ProjectsDatabase.dao.updateProject(widget.project); + Future updateDB() { + curProject = curProject.copyWith(markers: drift.Value(toBlob(_markers))); + return ProjectsDatabase.dao.updateProject(curProject); } @override void dispose() { - shapeNotifier?.dispose(); + shapeNotifier.dispose(); super.dispose(); } @@ -620,8 +629,6 @@ class MeasurePageState extends State { shapes: shapeNotifier, onInitialization: nextStep, onRotation: (delta) { - if (_baseAngle == null) - return; setState(() { _baseAngle += delta; _baseAngle = _baseAngle > pi ? _baseAngle - 2*pi : _baseAngle; @@ -643,7 +650,7 @@ class MeasurePageState extends State { class MarkerUiPainter extends CustomPainter { - double angle; + double? angle; double length = 20.0; @@ -657,7 +664,7 @@ class MarkerUiPainter extends CustomPainter { Offset center = size.center(Offset.zero); - double mAngle = angle; + double mAngle = angle!; Offset a = center.translate(length * cos(mAngle), length * sin(mAngle)); Offset b = center.translate(-length * cos(mAngle), -length * sin(mAngle)); diff --git a/lib/MenuPage.dart b/lib/MenuPage.dart index de4c223..769d138 100644 --- a/lib/MenuPage.dart +++ b/lib/MenuPage.dart @@ -4,9 +4,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:keydecoder/disclamer_dialog.dart'; import 'package:keydecoder/utils/utils.dart'; -import 'package:moor_flutter/moor_flutter.dart' as moor; +import 'package:drift/drift.dart' as drift; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:url_launcher/url_launcher.dart'; +import 'package:url_launcher/url_launcher_string.dart'; import 'ProjectPage.dart'; import 'projects/model/projects.dart'; import 'package:provider/provider.dart'; @@ -20,7 +20,7 @@ class MenuPage extends StatefulWidget { final String title = 'Projects'; static const routeName = '/menu'; - static Route route(Object args) { + static Route route(Object? args) { return MaterialPageRoute( builder: (BuildContext context) => MenuPage(), ); @@ -61,9 +61,9 @@ class MenuPageState extends State { final dao = ProjectsDatabase.dao; final nb = (await dao.allProjects).length + 1; - final newProject = ProjectCompanion( - title: moor.Value("Project #$nb"), - description: moor.Value(""), + final newProject = ProjectsCompanion( + title: drift.Value("Project #$nb"), + description: drift.Value(""), ); dao.insertProject(newProject).then((id) async { @@ -74,13 +74,13 @@ class MenuPageState extends State { @override Widget build(BuildContext context) { SharedPreferences.getInstance().then((prefs) async { - if (!prefs.containsKey('discaimer_displayed') || !prefs.getBool('discaimer_displayed')) { + if (!prefs.containsKey('discaimer_displayed') || !prefs.getBool('discaimer_displayed')!) { await _showDisclaimer(); prefs.setBool('discaimer_displayed', true); await Future.delayed(Duration(seconds: 1)); } - if (!prefs.containsKey('tutorial_displayed') || !prefs.getBool('tutorial_displayed')) { + if (!prefs.containsKey('tutorial_displayed') || !prefs.getBool('tutorial_displayed')!) { await _showTutorial(); prefs.setBool('tutorial_displayed', true); } @@ -140,13 +140,13 @@ class MenuPageState extends State { } openProject(item) { - ScaffoldMessenger.of(context).removeCurrentSnackBar(); + ScaffoldMessenger.of(context).hideCurrentSnackBar(); Navigator.pushNamed(context, ProjectPage.routeName, arguments: item); } deleteProject(Project item, ProjectsDao dao) { dao.deleteProject(item); - ScaffoldMessenger.of(context).removeCurrentSnackBar(); + ScaffoldMessenger.of(context).hideCurrentSnackBar(); ScaffoldFeatureController controller = ScaffoldMessenger.of(context) .showSnackBar(SnackBar( content: Text("${item.title} deleted"), @@ -188,22 +188,24 @@ class MenuPageState extends State { onTap: () => openProject(item), child: Slidable( key: ValueKey(item.id), - actionPane: SlidableDrawerActionPane(), child: ProjectThumbnail(project: item), closeOnScroll: true, - actionExtentRatio: 0.0, - secondaryActions: [ - IconSlideAction( - caption: 'Delete', - color: Colors.red, - icon: Icons.delete, + endActionPane: ActionPane( + motion: const DrawerMotion(), + extentRatio: 0.35, + children: [ + SlidableAction( + onPressed: (_) => deleteProject(item, dao), + icon: Icons.delete, + label: 'Delete', + backgroundColor: Colors.red + ) + ], + dismissible: DismissiblePane( + onDismissed: () => deleteProject(item, dao), + closeOnCancel: true, + dismissThreshold: 0.6, ), - ], - dismissal: SlidableDismissal( - dismissThresholds: { SlideActionType.secondary : 0.5 }, - child: SlidableDrawerDismissal(), - onDismissed: (direction) => deleteProject(item, dao), - closeOnCanceled: true, ), ), ), @@ -289,7 +291,7 @@ Additionnaly, the need for an ISO sized card as a dimensionnal reference prevent ), ), actions: [ - FlatButton( + TextButton( child: Text('Close'), onPressed: () => Navigator.pop(context), ) @@ -311,7 +313,7 @@ Additionnaly, the need for an ISO sized card as a dimensionnal reference prevent height: MediaQuery.of(context).size.width / 8, fit: BoxFit.scaleDown, ), - applicationVersion: "v1.0", + applicationVersion: "v1.1.0", applicationLegalese: "© AT Security SAS", children: [ Text("\nApp developped by :", textScaleFactor: txtscale), @@ -319,7 +321,11 @@ Additionnaly, the need for an ISO sized card as a dimensionnal reference prevent Center( child: InkWell( onTap: () { - canLaunch('https://twitter.com/maxime_beasse').then((canLaunch) => (canLaunch) ? launch('https://twitter.com/maxime_beasse') : null); + try { + launchUrlString('https://twitter.com/maxime_beasse'); + } catch (e) { + print(e); + } }, child: Text("@maxime_beasse", style: TextStyle(color: Colors.blue, decoration: TextDecoration.underline,), textScaleFactor: txtscale) ), @@ -329,23 +335,38 @@ Additionnaly, the need for an ISO sized card as a dimensionnal reference prevent Center( child: InkWell( onTap: () { - canLaunch('https://twitter.com/0x2f2f').then((canLaunch) => (canLaunch) ? launch('https://twitter.com/0x2f2f') : null); + try { + launchUrlString('https://twitter.com/0x2f2f'); + } catch (e) { + print(e); + } }, child: Text("@0x2f2f", style: TextStyle(color: Colors.blue, decoration: TextDecoration.underline,), textScaleFactor: txtscale), ), ), Text("\n\n", textScaleFactor: txtscale/4), - InkWell( - onTap: () { - canLaunch('https://github.com/MaximeBeasse/KeyDecoder').then((canLaunch) => (canLaunch) ? launch('https://github.com/MaximeBeasse/KeyDecoder') : null); - }, - child: Text("GitHub Repository", style: TextStyle(color: Colors.blue, decoration: TextDecoration.underline,), textScaleFactor: txtscale), - ), + Align( + alignment: Alignment.centerLeft, + child: InkWell( + onTap: () { + try { + launchUrlString('https://github.com/MaximeBeasse/KeyDecoder'); + } catch (e) { + print(e); + } + }, + child: Text("GitHub Repository", style: TextStyle(color: Colors.blue, decoration: TextDecoration.underline,), textScaleFactor: txtscale), + ), + ), Text("\n\nIn partnership with FrenchKey ", textScaleFactor: txtscale), Center( child: InkWell( onTap: () { - canLaunch('https://twitter.com/frenchkey_fr').then((canLaunch) => (canLaunch) ? launch('https://twitter.com/frenchkey_fr') : null); + try { + launchUrlString('https://twitter.com/frenchkey_fr'); + } catch (e) { + print(e); + } }, child: Text("@FrenchKey_fr", style: TextStyle(color: Colors.blue, decoration: TextDecoration.underline,), textScaleFactor: txtscale), ), @@ -359,7 +380,7 @@ Additionnaly, the need for an ISO sized card as a dimensionnal reference prevent context: context, builder: (context) => AlertDialog( actions: [ - FlatButton( + TextButton( child: Text('Close'), onPressed: () => Navigator.pop(context), ) diff --git a/lib/ProjectPage.dart b/lib/ProjectPage.dart index c0eedc7..c0307a2 100644 --- a/lib/ProjectPage.dart +++ b/lib/ProjectPage.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:animate_icons/animate_icons.dart'; +import 'package:animate_icons/animate_icons.dart' show AnimateIconController, AnimateIcons; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; @@ -9,6 +9,8 @@ import 'package:image_picker/image_picker.dart' show ImageSource; import 'package:keydecoder/utils/gesture_x_detector.dart'; import 'package:provider/provider.dart'; +import 'package:drift/drift.dart' as drift; + import 'EditorBase.dart'; import 'MeasurePage.dart'; import 'projects/model/projects.dart'; @@ -23,7 +25,7 @@ class ProjectPage extends StatefulWidget { final String title = 'Project Page'; static const routeName = '/project'; - static Route route(Object args) { + static Route route(Object? args) { return MaterialPageRoute( builder: (BuildContext context) => ProjectPage(args as Project), ); @@ -35,14 +37,14 @@ class ProjectPage extends StatefulWidget { class ProjectPageState extends State { - TextEditingController _titleController; - TextEditingController _descriptionController; + late TextEditingController _titleController; + late TextEditingController _descriptionController; - FocusNode _fnTitle; - FocusNode _fnBrief; - FocusNode _fnFabs; + late FocusNode _fnTitle; + late FocusNode _fnBrief; + late FocusNode _fnFabs; - Project project; + late Project project; bool _updated = false; @@ -73,9 +75,9 @@ class ProjectPageState extends State { kvc.onChange.listen((bool visible) { if (!visible) { - _fnTitle?.unfocus(); - _fnBrief?.unfocus(); - _fnFabs?.unfocus(); + _fnTitle.unfocus(); + _fnBrief.unfocus(); + _fnFabs.unfocus(); } }); @@ -84,13 +86,13 @@ class ProjectPageState extends State { @override void dispose() { - _titleController?.dispose(); - _fnTitle?.dispose(); + _titleController.dispose(); + _fnTitle.dispose(); - _descriptionController?.dispose(); - _fnBrief?.dispose(); + _descriptionController.dispose(); + _fnBrief.dispose(); - _fnFabs?.dispose(); + _fnFabs.dispose(); super.dispose(); } @@ -108,7 +110,8 @@ class ProjectPageState extends State { ], controller: _titleController, onChanged: (text) { - project.title = text; + project = project.copyWith(title: text); + ProjectsDatabase.dao.updateProject(project); _updated = true; }, focusNode: _fnTitle, @@ -126,7 +129,8 @@ class ProjectPageState extends State { maxLines: 2, controller: _descriptionController, onChanged: (text) { - project.description = text; + project = project.copyWith(description: text); + ProjectsDatabase.dao.updateProject(project); _updated = true; }, focusNode: _fnBrief, @@ -139,13 +143,15 @@ class ProjectPageState extends State { List gaps = []; List depthsText = []; List gapsText = []; - Matrix4 bittingMat = Matrix4.inverted(Matrix4.translationValues(project.originX, project.originY, 0)..rotateZ(project.angle)); + Matrix4 bittingMat = Matrix4.inverted(Matrix4.translationValues(project.originX!, project.originY!, 0)..rotateZ(project.angle!)); for (var i = 0; i < markers.length; i++) { markers[i] = transformOffset(bittingMat, markers[i]); - depths.add(markers[i].dy.abs() * project.isoRatio); + depths.add(markers[i].dy.abs() * project.isoRatio!); if (i > 0) - gaps.add((markers[i-1].dx.abs() - markers[i].dx.abs()).abs() * project.isoRatio); + gaps.add((markers[i-1].dx.abs() - markers[i].dx.abs()).abs() * project.isoRatio!); + else + gaps.add(markers[i].dx.abs() * project.isoRatio!); } depths.forEach((d) { @@ -169,6 +175,20 @@ class ProjectPageState extends State { ) ); }); + + depthsText.insert(0, Center( + child: Container( + padding: EdgeInsets.symmetric(vertical: 2), + child: Text('Depth') + ) + )); + + gapsText.insert(0, Center( + child: Container( + padding: EdgeInsets.symmetric(vertical: 2), + child: Text('Dist') + ) + )); return DefaultTextStyle( style: TextStyle( @@ -180,26 +200,30 @@ class ProjectPageState extends State { Table( border: TableBorder.all(), children: [ + TableRow( + children: List.generate(depthsText.length, (index) { + if (index == 0) + return Center( + child: Container( + padding: EdgeInsets.symmetric(vertical: 2), + child: Text('N°') + ) + ); + return Center( + child: Container( + padding: EdgeInsets.symmetric(vertical: 2), + child: Text('$index') + ) + ); + }) + ), TableRow( children: depthsText - ) - ] - ), - Padding( - padding: EdgeInsets.symmetric(horizontal: MediaQuery.of(context).size.width / depthsText.length / 2), - child: Table( - border: TableBorder( - bottom: BorderSide(), - left: BorderSide(), - right: BorderSide(), - verticalInside: BorderSide(), ), - children: [ - TableRow( - children: gapsText - ) - ] - ), + TableRow( + children: gapsText + ) + ] ), ], ), @@ -215,14 +239,14 @@ class ProjectPageState extends State { Divider(height: 10.0,), description(), Visibility( - visible: project.markers != null && project.markers.isNotEmpty, + visible: project.markers != null && project.markers!.isNotEmpty, child: Padding( padding: const EdgeInsets.all(8.0), child: Column( children: [ Builder( builder: (ctxt) { - List markers = fromBlob(project.markers); + List markers = fromBlob(project.markers!); if (markers.length >= 2) return generateTableForAxis(markers.reversed.toList()); return Container(); @@ -238,7 +262,7 @@ class ProjectPageState extends State { } void selectedImageSource(ImageSource src) async { - File savedFile = await Picture.getImageFromSource(src); + File? savedFile = await Picture.getImageFromSource(src); // Image picker canceled if (savedFile == null) @@ -247,14 +271,10 @@ class ProjectPageState extends State { if (project.pathRawPic.isNotEmpty) File(project.pathRawPic).deleteSync(); - setState(() { - project.pathRawPic = savedFile.path; - }); - + project = project.copyWith(pathRawPic: savedFile.path); ProjectsDatabase.dao.updateProject(project); - EditorBase.initEditorBase().then((_) - => cropRawImage().then((cropped) { + cropRawImage().then((cropped) { if(cropped) measureCuts().then((_) { EditorBase.disposeEditorBase(); @@ -262,7 +282,7 @@ class ProjectPageState extends State { }); else EditorBase.disposeEditorBase(); - })); + }); } Future cropRawImage() async { @@ -274,16 +294,15 @@ class ProjectPageState extends State { return false; // Existing file overwritten - setState(() { - project.pathCroppedPic = result as String; - }); - - project.originX = null; - project.originX = null; - project.angle = null; - project.markers = null; - ProjectsDatabase.dao.updateProject(widget.project); + project = project.copyWith( + pathCroppedPic: result as String, + originX: drift.Value(null), + originY: drift.Value(null), + angle: drift.Value(null), + markers: drift.Value(null), + ); + setState(() {}); await ProjectsDatabase.dao.updateProject(project); return true; @@ -291,10 +310,11 @@ class ProjectPageState extends State { Future measureCuts() async { await Navigator.of(context).pushNamed(MeasurePage.routeName, arguments: project); - - await ProjectsDatabase.dao.updateProject(project); - - setState(() {}); + + ProjectsDatabase.dao.getProjectByID(project.id).then((p) { + project = p; + setState(() {}); + }); } Future _onBackPressed() async { @@ -320,7 +340,7 @@ class ProjectPageState extends State { ProjectFloatingActionButton(), ] ), - resizeToAvoidBottomPadding: false, + resizeToAvoidBottomInset: false, ), onWillPop: _onBackPressed, ); @@ -337,29 +357,29 @@ class ProjectFloatingActionButton extends StatefulWidget { class ProjectFloatingActionButtonState extends State with SingleTickerProviderStateMixin { - ProjectPageState get parent => context.findAncestorStateOfType(); + ProjectPageState? get parent => context.findAncestorStateOfType(); bool isOpened = false; - AnimationController _animationController; - Animation _buttonColor; - AnimateIconController _animateIcon; - Animation _translateButton; + late AnimationController _animationController; + late Animation _buttonColor; + late AnimateIconController _animateIcon; + late Animation _translateButton; Curve _curve = Curves.easeOut; double _fabHeight = 56.0; - final Color _colorDisable = Colors.grey[600]; + final Color _colorDisable = Colors.grey.shade600; final Color _colorActive = Colors.blue; - final Color _colorDone = Colors.lightGreen[400]; + final Color _colorDone = Colors.lightGreen.shade400; @override initState() { - parent._fnTitle.addListener(() { + parent?._fnTitle.addListener(() { animate(forceClose: true); _animateIcon.animateToStart(); }); - parent._fnBrief.addListener(() { + parent?._fnBrief.addListener(() { animate(forceClose: true); _animateIcon.animateToStart(); }); @@ -421,7 +441,7 @@ class ProjectFloatingActionButtonState extends State EditorBase.initEditorBase() - .then((_) => parent.cropRawImage() + onPressed: (active || completed) ? () => /*EditorBase.initEditorBase()*/Future.value(null) + .then((_) => parent?.cropRawImage() .then((_) => EditorBase.disposeEditorBase())) : null, tooltip: 'Crop image', child: Icon(Icons.crop), @@ -512,8 +533,8 @@ class ProjectFloatingActionButtonState extends State EditorBase.initEditorBase() - .then((_) => parent.measureCuts() + onPressed: (active || completed) ? () => /*EditorBase.initEditorBase()*/Future.value(null) + .then((_) => parent?.measureCuts() .then((_) => EditorBase.disposeEditorBase())) : null, tooltip: 'Measure key', child: Icon(Icons.straighten), @@ -541,30 +562,33 @@ class ProjectFloatingActionButtonState extends State portraitModeOnly().then((_) => true), + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + Positioned( + width: MediaQuery.of(context).size.width, + bottom: 20, + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + mainAxisSize: MainAxisSize.min, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: content()..add(fab()), + ), + lineDiv(show: true), + cropFab(active: parent!.project.pathCroppedPic.isEmpty && parent!.project.pathRawPic.isNotEmpty, completed: parent!.project.pathCroppedPic.isNotEmpty), + lineDiv(show: true), + measureFab(active: parent!.project.pathCroppedPic.isNotEmpty, completed: parent?.project.markers != null) + ], + ), + ) + ], + ), ); } } \ No newline at end of file diff --git a/lib/disclamer_dialog.dart b/lib/disclamer_dialog.dart index de723d7..aaebf06 100644 --- a/lib/disclamer_dialog.dart +++ b/lib/disclamer_dialog.dart @@ -38,16 +38,16 @@ The authors DO NOT ALLOW any users to sell keys created with the help of this ap @override Widget build(BuildContext context) { return AlertDialog( - title: Text(_texts[_curPage]['title'], textAlign: (_texts[_curPage]['content'] != null) ? TextAlign.start : TextAlign.center,), - content: _texts[_curPage]['content'] == null ? null : Text(_texts[_curPage]['content'], textAlign: TextAlign.justify,), + title: Text(_texts[_curPage]['title']!, textAlign: (_texts[_curPage]['content'] != null) ? TextAlign.start : TextAlign.center,), + content: _texts[_curPage]['content'] == null ? null : Text(_texts[_curPage]['content']!, textAlign: TextAlign.justify,), actions: (_curPage > 0) ? ([ - FlatButton( + TextButton( onPressed: () { setState(() => _curPage--); }, child: Text('Back'), ), - FlatButton( + TextButton( onPressed: () { if (_curPage + 1 >= _texts.length) Navigator.pop(context); @@ -57,7 +57,7 @@ The authors DO NOT ALLOW any users to sell keys created with the help of this ap child: Text('Continue'), ), ]) : ([ - FlatButton( + TextButton( onPressed: () { setState(() => _curPage++); }, diff --git a/lib/main.dart b/lib/main.dart index 11f8308..c31314f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -32,11 +32,12 @@ class App extends StatelessWidget { } class Routes { - static Route onGenerateRoute(RouteSettings settings){ - switch (settings.name.toLowerCase()){ - case MenuPage.routeName: - return MenuPage.route(settings.arguments); - case ProjectPage.routeName: + static Route? onGenerateRoute(RouteSettings settings){ + + switch (settings.name?.toLowerCase()){ + case MenuPage.routeName: + return MenuPage.route(settings.arguments); + case ProjectPage.routeName: return ProjectPage.route(settings.arguments); case CropPage.routeName: return CropPage.route(settings.arguments); @@ -44,6 +45,6 @@ class Routes { return MeasurePage.route(settings.arguments); default: return null; - } + } } } \ No newline at end of file diff --git a/lib/native_cv/native_cv.dart b/lib/native_cv/native_cv.dart index 9bbcac0..9fa5f8c 100644 --- a/lib/native_cv/native_cv.dart +++ b/lib/native_cv/native_cv.dart @@ -1,59 +1,30 @@ import 'dart:async'; import 'dart:ffi'; import 'dart:io'; -import 'dart:ui'; import 'package:ffi/ffi.dart'; import 'package:flutter/material.dart'; -class Coordinate extends Struct { +final class Coordinate extends Struct { @Double() - double x; + external double x; @Double() - double y; - - factory Coordinate.allocate(double x, double y) => - allocate().ref - ..x = x - ..y = y; - - factory Coordinate.fromOffset(Offset o) => - allocate().ref - ..x = o.dx - ..y = o.dy; + external double y; } -class NativeIntersection extends Struct { - Pointer topLeft; - Pointer topRight; - Pointer bottomLeft; - Pointer bottomRight; - - factory NativeIntersection.allocate( - Pointer topLeft, - Pointer topRight, - Pointer bottomLeft, - Pointer bottomRight) => - allocate().ref - ..topLeft = topLeft - ..topRight = topRight - ..bottomLeft = bottomLeft - ..bottomRight = bottomRight; - - factory NativeIntersection.fromDart(DartIntersection dinter) => - allocate().ref - ..topLeft = Coordinate.fromOffset(dinter.topLeft).addressOf - ..topRight = Coordinate.fromOffset(dinter.topRight).addressOf - ..bottomLeft = Coordinate.fromOffset(dinter.bottomLeft).addressOf - ..bottomRight = Coordinate.fromOffset(dinter.bottomRight).addressOf; +final class NativeIntersection extends Struct { + external Coordinate topLeft; + external Coordinate topRight; + external Coordinate bottomLeft; + external Coordinate bottomRight; } class DartIntersection { DartIntersection({ - @required this.topLeft, - @required this.topRight, - @required this.bottomLeft, - @required this.bottomRight, + required this.topLeft, + required this.topRight, + required this.bottomLeft, + required this.bottomRight, }); DartIntersection.fromList(List l) { @@ -62,14 +33,14 @@ class DartIntersection { topLeft = l[0]; topRight = l[1]; - bottomRight = l[2]; bottomLeft = l[3]; + bottomRight = l[2]; } - Offset topLeft; - Offset topRight; - Offset bottomLeft; - Offset bottomRight; + late Offset topLeft; + late Offset topRight; + late Offset bottomLeft; + late Offset bottomRight; @override String toString() { @@ -82,31 +53,80 @@ class DartIntersection { } } -typedef homogaphy_warp_function = Int8 Function( - Pointer points, Pointer src, Pointer dst +typedef CreateCoordinateNative = Coordinate Function(Double x, Double y); +typedef CreateCoordinate = Coordinate Function(double x, double y); + +typedef CreateNativeIntersectionNative = NativeIntersection Function( + Coordinate topLeft, + Coordinate topRight, + Coordinate bottomLeft, + Coordinate bottomRight +); +typedef CreateNativeIntersection = NativeIntersection Function( + Coordinate topLeft, + Coordinate topRight, + Coordinate bottomLeft, + Coordinate bottomRight ); +typedef HomogaphyWarpFunctionNative = Int8 Function( + NativeIntersection points, Pointer src, Pointer dst +); typedef HomogaphyWarpFunction = int Function( - Pointer points, + NativeIntersection points, Pointer src, Pointer dst ); +typedef CroplessWarpFunctionNative = Double Function( + NativeIntersection points, Pointer src, Pointer dst, Double width, Double length +); +typedef CroplessWarpFunction = double Function( + NativeIntersection points, + Pointer src, + Pointer dst, + double width, + double length +); + +NativeIntersection createNativeIntersectionFromDart(DynamicLibrary dynamicLibrary, DartIntersection points) { + + final createCoordinate = dynamicLibrary.lookupFunction("create_coordinate"); + final createIntersection = dynamicLibrary.lookupFunction("create_intersection"); + + Coordinate topLeft = createCoordinate(points.topLeft.dx, points.topLeft.dy); + Coordinate topRight = createCoordinate(points.topRight.dx, points.topRight.dy); + Coordinate bottomLeft = createCoordinate(points.bottomLeft.dx, points.bottomLeft.dy); + Coordinate bottomRight = createCoordinate(points.bottomRight.dx, points.bottomRight.dy); + + return createIntersection(topLeft, topRight, bottomLeft, bottomRight); +} + class HomographyWarp { - static Future homographyWarp(DartIntersection points, String src, String dst) async { - DynamicLibrary nativeCvLib = _getDynamicLibrary(); - - var lookup = nativeCvLib.lookup>("homography_warp"); - final homographicWarp = lookup.asFunction(); - - NativeIntersection ninter = NativeIntersection.fromDart(points); - - return homographicWarp(ninter.addressOf, Utf8.toUtf8(src), Utf8.toUtf8(dst)); - } - static DynamicLibrary _getDynamicLibrary() { - final DynamicLibrary nativeCvLib = Platform.isAndroid - ? DynamicLibrary.open("libnative_cv.so") - : DynamicLibrary.process(); - return nativeCvLib; - } + static Future homographyWarp(DartIntersection points, String src, String dst) async { + DynamicLibrary nativeCvLib = _getDynamicLibrary(); + + final homographicWarp = nativeCvLib.lookupFunction("homography_warp"); + + NativeIntersection ninter = createNativeIntersectionFromDart(nativeCvLib, points); + + return homographicWarp(ninter, src.toNativeUtf8(), dst.toNativeUtf8()); + } + + static Future croplessWarp(DartIntersection points, String src, String dst, double width, double length) async { + DynamicLibrary nativeCvLib = _getDynamicLibrary(); + + final croplessWarp = nativeCvLib.lookupFunction("cropless_warp"); + + NativeIntersection ninter = createNativeIntersectionFromDart(nativeCvLib, points); + + return croplessWarp(ninter, src.toNativeUtf8(), dst.toNativeUtf8(), width, length); + } + + static DynamicLibrary _getDynamicLibrary() { + final DynamicLibrary nativeCvLib = Platform.isAndroid + ? DynamicLibrary.open("libnative_cv.so") + : DynamicLibrary.process(); + return nativeCvLib; + } } \ No newline at end of file diff --git a/lib/projects/model/projects.dart b/lib/projects/model/projects.dart index 36b7a8e..27a911c 100644 --- a/lib/projects/model/projects.dart +++ b/lib/projects/model/projects.dart @@ -1,7 +1,7 @@ -import 'package:moor/ffi.dart'; +import 'package:drift/native.dart'; import 'package:path_provider/path_provider.dart'; import 'package:path/path.dart' as p; -import 'package:moor/moor.dart'; +import 'package:drift/drift.dart'; import 'dart:io'; part 'projects.g.dart'; @@ -29,29 +29,29 @@ LazyDatabase _openConnection() { // put the database file, called db.sqlite here, into the documents folder // for your app. final dbFolder = await getApplicationDocumentsDirectory(); - final file = File(p.join(dbFolder.path, 'projectsdb.sqlite')); - return VmDatabase(file, logStatements: true); + File file = File(p.join(dbFolder.path, 'projectsdb.sqlite')); + return NativeDatabase(file, logStatements: true); }); } -@UseMoor(tables: [Projects], daos: [ProjectsDao]) +@DriftDatabase(tables: [Projects], daos: [ProjectsDao]) class ProjectsDatabase extends _$ProjectsDatabase { // we tell the database where to store the data with this constructor ProjectsDatabase() : super(_openConnection()); - static ProjectsDatabase _instance; + static ProjectsDatabase? _instance; static ProjectsDatabase get db { if(_instance == null) _instance = ProjectsDatabase(); - return _instance; + return _instance!; } static ProjectsDao get dao { if(_instance == null) _instance = ProjectsDatabase(); - return _instance.projectsDao; + return _instance!.projectsDao; } @override @@ -83,12 +83,12 @@ class ProjectsDatabase extends _$ProjectsDatabase { ); } -@UseDao(tables: [Projects]) +@DriftAccessor(tables: [Projects]) class ProjectsDao extends DatabaseAccessor with _$ProjectsDaoMixin { ProjectsDao(ProjectsDatabase db) : super(db); - Future get nbProjects { + Future get nbProjects { final count = projects.id.count(); final query = selectOnly(projects) ..addColumns([count]); diff --git a/lib/projects/model/projects.g.dart b/lib/projects/model/projects.g.dart index 986c8e8..29d2f5f 100644 --- a/lib/projects/model/projects.g.dart +++ b/lib/projects/model/projects.g.dart @@ -2,80 +2,216 @@ part of 'projects.dart'; -// ************************************************************************** -// MoorGenerator -// ************************************************************************** +// ignore_for_file: type=lint +class $ProjectsTable extends Projects with TableInfo<$ProjectsTable, Project> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $ProjectsTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _idMeta = const VerificationMeta('id'); + @override + late final GeneratedColumn id = GeneratedColumn( + 'id', aliasedName, false, + hasAutoIncrement: true, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT')); + static const VerificationMeta _titleMeta = const VerificationMeta('title'); + @override + late final GeneratedColumn title = GeneratedColumn( + 'title', aliasedName, false, + type: DriftSqlType.string, requiredDuringInsert: true); + static const VerificationMeta _descriptionMeta = + const VerificationMeta('description'); + @override + late final GeneratedColumn description = GeneratedColumn( + 'description', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const Constant('')); + static const VerificationMeta _pathRawPicMeta = + const VerificationMeta('pathRawPic'); + @override + late final GeneratedColumn pathRawPic = GeneratedColumn( + 'path_raw_pic', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const Constant('')); + static const VerificationMeta _pathCroppedPicMeta = + const VerificationMeta('pathCroppedPic'); + @override + late final GeneratedColumn pathCroppedPic = GeneratedColumn( + 'path_cropped_pic', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const Constant('')); + static const VerificationMeta _markersMeta = + const VerificationMeta('markers'); + @override + late final GeneratedColumn markers = GeneratedColumn( + 'markers', aliasedName, true, + type: DriftSqlType.blob, requiredDuringInsert: false); + static const VerificationMeta _originXMeta = + const VerificationMeta('originX'); + @override + late final GeneratedColumn originX = GeneratedColumn( + 'origin_x', aliasedName, true, + type: DriftSqlType.double, requiredDuringInsert: false); + static const VerificationMeta _originYMeta = + const VerificationMeta('originY'); + @override + late final GeneratedColumn originY = GeneratedColumn( + 'origin_y', aliasedName, true, + type: DriftSqlType.double, requiredDuringInsert: false); + static const VerificationMeta _angleMeta = const VerificationMeta('angle'); + @override + late final GeneratedColumn angle = GeneratedColumn( + 'angle', aliasedName, true, + type: DriftSqlType.double, requiredDuringInsert: false); + static const VerificationMeta _isoRatioMeta = + const VerificationMeta('isoRatio'); + @override + late final GeneratedColumn isoRatio = GeneratedColumn( + 'iso_ratio', aliasedName, true, + type: DriftSqlType.double, requiredDuringInsert: false); + @override + List get $columns => [ + id, + title, + description, + pathRawPic, + pathCroppedPic, + markers, + originX, + originY, + angle, + isoRatio + ]; + @override + String get aliasedName => _alias ?? 'projects'; + @override + String get actualTableName => 'projects'; + @override + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); + } + if (data.containsKey('title')) { + context.handle( + _titleMeta, title.isAcceptableOrUnknown(data['title']!, _titleMeta)); + } else if (isInserting) { + context.missing(_titleMeta); + } + if (data.containsKey('description')) { + context.handle( + _descriptionMeta, + description.isAcceptableOrUnknown( + data['description']!, _descriptionMeta)); + } + if (data.containsKey('path_raw_pic')) { + context.handle( + _pathRawPicMeta, + pathRawPic.isAcceptableOrUnknown( + data['path_raw_pic']!, _pathRawPicMeta)); + } + if (data.containsKey('path_cropped_pic')) { + context.handle( + _pathCroppedPicMeta, + pathCroppedPic.isAcceptableOrUnknown( + data['path_cropped_pic']!, _pathCroppedPicMeta)); + } + if (data.containsKey('markers')) { + context.handle(_markersMeta, + markers.isAcceptableOrUnknown(data['markers']!, _markersMeta)); + } + if (data.containsKey('origin_x')) { + context.handle(_originXMeta, + originX.isAcceptableOrUnknown(data['origin_x']!, _originXMeta)); + } + if (data.containsKey('origin_y')) { + context.handle(_originYMeta, + originY.isAcceptableOrUnknown(data['origin_y']!, _originYMeta)); + } + if (data.containsKey('angle')) { + context.handle( + _angleMeta, angle.isAcceptableOrUnknown(data['angle']!, _angleMeta)); + } + if (data.containsKey('iso_ratio')) { + context.handle(_isoRatioMeta, + isoRatio.isAcceptableOrUnknown(data['iso_ratio']!, _isoRatioMeta)); + } + return context; + } + + @override + Set get $primaryKey => {id}; + @override + Project map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return Project( + id: attachedDatabase.typeMapping + .read(DriftSqlType.int, data['${effectivePrefix}id'])!, + title: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}title'])!, + description: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}description'])!, + pathRawPic: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}path_raw_pic'])!, + pathCroppedPic: attachedDatabase.typeMapping.read( + DriftSqlType.string, data['${effectivePrefix}path_cropped_pic'])!, + markers: attachedDatabase.typeMapping + .read(DriftSqlType.blob, data['${effectivePrefix}markers']), + originX: attachedDatabase.typeMapping + .read(DriftSqlType.double, data['${effectivePrefix}origin_x']), + originY: attachedDatabase.typeMapping + .read(DriftSqlType.double, data['${effectivePrefix}origin_y']), + angle: attachedDatabase.typeMapping + .read(DriftSqlType.double, data['${effectivePrefix}angle']), + isoRatio: attachedDatabase.typeMapping + .read(DriftSqlType.double, data['${effectivePrefix}iso_ratio']), + ); + } + + @override + $ProjectsTable createAlias(String alias) { + return $ProjectsTable(attachedDatabase, alias); + } +} -// ignore_for_file: unnecessary_brace_in_string_interps, unnecessary_this class Project extends DataClass implements Insertable { - int id; - String title; - String description; - String pathRawPic; - String pathCroppedPic; - Uint8List markers; - double originX; - double originY; - double angle; - double isoRatio; - Project( - {@required this.id, - @required this.title, - @required this.description, - @required this.pathRawPic, - @required this.pathCroppedPic, + final int id; + final String title; + final String description; + final String pathRawPic; + final String pathCroppedPic; + final Uint8List? markers; + final double? originX; + final double? originY; + final double? angle; + final double? isoRatio; + const Project( + {required this.id, + required this.title, + required this.description, + required this.pathRawPic, + required this.pathCroppedPic, this.markers, this.originX, this.originY, this.angle, this.isoRatio}); - factory Project.fromData(Map data, GeneratedDatabase db, - {String prefix}) { - final effectivePrefix = prefix ?? ''; - final intType = db.typeSystem.forDartType(); - final stringType = db.typeSystem.forDartType(); - final uint8ListType = db.typeSystem.forDartType(); - final doubleType = db.typeSystem.forDartType(); - return Project( - id: intType.mapFromDatabaseResponse(data['${effectivePrefix}id']), - title: - stringType.mapFromDatabaseResponse(data['${effectivePrefix}title']), - description: stringType - .mapFromDatabaseResponse(data['${effectivePrefix}description']), - pathRawPic: stringType - .mapFromDatabaseResponse(data['${effectivePrefix}path_raw_pic']), - pathCroppedPic: stringType - .mapFromDatabaseResponse(data['${effectivePrefix}path_cropped_pic']), - markers: uint8ListType - .mapFromDatabaseResponse(data['${effectivePrefix}markers']), - originX: doubleType - .mapFromDatabaseResponse(data['${effectivePrefix}origin_x']), - originY: doubleType - .mapFromDatabaseResponse(data['${effectivePrefix}origin_y']), - angle: - doubleType.mapFromDatabaseResponse(data['${effectivePrefix}angle']), - isoRatio: doubleType - .mapFromDatabaseResponse(data['${effectivePrefix}iso_ratio']), - ); - } @override Map toColumns(bool nullToAbsent) { final map = {}; - if (!nullToAbsent || id != null) { - map['id'] = Variable(id); - } - if (!nullToAbsent || title != null) { - map['title'] = Variable(title); - } - if (!nullToAbsent || description != null) { - map['description'] = Variable(description); - } - if (!nullToAbsent || pathRawPic != null) { - map['path_raw_pic'] = Variable(pathRawPic); - } - if (!nullToAbsent || pathCroppedPic != null) { - map['path_cropped_pic'] = Variable(pathCroppedPic); - } + map['id'] = Variable(id); + map['title'] = Variable(title); + map['description'] = Variable(description); + map['path_raw_pic'] = Variable(pathRawPic); + map['path_cropped_pic'] = Variable(pathCroppedPic); if (!nullToAbsent || markers != null) { map['markers'] = Variable(markers); } @@ -94,20 +230,13 @@ class Project extends DataClass implements Insertable { return map; } - ProjectCompanion toCompanion(bool nullToAbsent) { - return ProjectCompanion( - id: id == null && nullToAbsent ? const Value.absent() : Value(id), - title: - title == null && nullToAbsent ? const Value.absent() : Value(title), - description: description == null && nullToAbsent - ? const Value.absent() - : Value(description), - pathRawPic: pathRawPic == null && nullToAbsent - ? const Value.absent() - : Value(pathRawPic), - pathCroppedPic: pathCroppedPic == null && nullToAbsent - ? const Value.absent() - : Value(pathCroppedPic), + ProjectsCompanion toCompanion(bool nullToAbsent) { + return ProjectsCompanion( + id: Value(id), + title: Value(title), + description: Value(description), + pathRawPic: Value(pathRawPic), + pathCroppedPic: Value(pathCroppedPic), markers: markers == null && nullToAbsent ? const Value.absent() : Value(markers), @@ -126,64 +255,60 @@ class Project extends DataClass implements Insertable { } factory Project.fromJson(Map json, - {ValueSerializer serializer}) { - serializer ??= moorRuntimeOptions.defaultSerializer; + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; return Project( id: serializer.fromJson(json['id']), title: serializer.fromJson(json['title']), description: serializer.fromJson(json['description']), pathRawPic: serializer.fromJson(json['pathRawPic']), pathCroppedPic: serializer.fromJson(json['pathCroppedPic']), - markers: serializer.fromJson(json['markers']), - originX: serializer.fromJson(json['originX']), - originY: serializer.fromJson(json['originY']), - angle: serializer.fromJson(json['angle']), - isoRatio: serializer.fromJson(json['isoRatio']), + markers: serializer.fromJson(json['markers']), + originX: serializer.fromJson(json['originX']), + originY: serializer.fromJson(json['originY']), + angle: serializer.fromJson(json['angle']), + isoRatio: serializer.fromJson(json['isoRatio']), ); } - factory Project.fromJsonString(String encodedJson, - {ValueSerializer serializer}) => - Project.fromJson(DataClass.parseJson(encodedJson) as Map, - serializer: serializer); @override - Map toJson({ValueSerializer serializer}) { - serializer ??= moorRuntimeOptions.defaultSerializer; + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; return { 'id': serializer.toJson(id), 'title': serializer.toJson(title), 'description': serializer.toJson(description), 'pathRawPic': serializer.toJson(pathRawPic), 'pathCroppedPic': serializer.toJson(pathCroppedPic), - 'markers': serializer.toJson(markers), - 'originX': serializer.toJson(originX), - 'originY': serializer.toJson(originY), - 'angle': serializer.toJson(angle), - 'isoRatio': serializer.toJson(isoRatio), + 'markers': serializer.toJson(markers), + 'originX': serializer.toJson(originX), + 'originY': serializer.toJson(originY), + 'angle': serializer.toJson(angle), + 'isoRatio': serializer.toJson(isoRatio), }; } Project copyWith( - {int id, - String title, - String description, - String pathRawPic, - String pathCroppedPic, - Uint8List markers, - double originX, - double originY, - double angle, - double isoRatio}) => + {int? id, + String? title, + String? description, + String? pathRawPic, + String? pathCroppedPic, + Value markers = const Value.absent(), + Value originX = const Value.absent(), + Value originY = const Value.absent(), + Value angle = const Value.absent(), + Value isoRatio = const Value.absent()}) => Project( id: id ?? this.id, title: title ?? this.title, description: description ?? this.description, pathRawPic: pathRawPic ?? this.pathRawPic, pathCroppedPic: pathCroppedPic ?? this.pathCroppedPic, - markers: markers ?? this.markers, - originX: originX ?? this.originX, - originY: originY ?? this.originY, - angle: angle ?? this.angle, - isoRatio: isoRatio ?? this.isoRatio, + markers: markers.present ? markers.value : this.markers, + originX: originX.present ? originX.value : this.originX, + originY: originY.present ? originY.value : this.originY, + angle: angle.present ? angle.value : this.angle, + isoRatio: isoRatio.present ? isoRatio.value : this.isoRatio, ); @override String toString() { @@ -203,26 +328,19 @@ class Project extends DataClass implements Insertable { } @override - int get hashCode => $mrjf($mrjc( - id.hashCode, - $mrjc( - title.hashCode, - $mrjc( - description.hashCode, - $mrjc( - pathRawPic.hashCode, - $mrjc( - pathCroppedPic.hashCode, - $mrjc( - markers.hashCode, - $mrjc( - originX.hashCode, - $mrjc( - originY.hashCode, - $mrjc(angle.hashCode, - isoRatio.hashCode)))))))))); + int get hashCode => Object.hash( + id, + title, + description, + pathRawPic, + pathCroppedPic, + $driftBlobEquality.hash(markers), + originX, + originY, + angle, + isoRatio); @override - bool operator ==(dynamic other) => + bool operator ==(Object other) => identical(this, other) || (other is Project && other.id == this.id && @@ -230,25 +348,25 @@ class Project extends DataClass implements Insertable { other.description == this.description && other.pathRawPic == this.pathRawPic && other.pathCroppedPic == this.pathCroppedPic && - other.markers == this.markers && + $driftBlobEquality.equals(other.markers, this.markers) && other.originX == this.originX && other.originY == this.originY && other.angle == this.angle && other.isoRatio == this.isoRatio); } -class ProjectCompanion extends UpdateCompanion { - Value id; - Value title; - Value description; - Value pathRawPic; - Value pathCroppedPic; - Value markers; - Value originX; - Value originY; - Value angle; - Value isoRatio; - ProjectCompanion({ +class ProjectsCompanion extends UpdateCompanion { + final Value id; + final Value title; + final Value description; + final Value pathRawPic; + final Value pathCroppedPic; + final Value markers; + final Value originX; + final Value originY; + final Value angle; + final Value isoRatio; + const ProjectsCompanion({ this.id = const Value.absent(), this.title = const Value.absent(), this.description = const Value.absent(), @@ -260,9 +378,9 @@ class ProjectCompanion extends UpdateCompanion { this.angle = const Value.absent(), this.isoRatio = const Value.absent(), }); - ProjectCompanion.insert({ + ProjectsCompanion.insert({ this.id = const Value.absent(), - @required String title, + required String title, this.description = const Value.absent(), this.pathRawPic = const Value.absent(), this.pathCroppedPic = const Value.absent(), @@ -273,16 +391,16 @@ class ProjectCompanion extends UpdateCompanion { this.isoRatio = const Value.absent(), }) : title = Value(title); static Insertable custom({ - Expression id, - Expression title, - Expression description, - Expression pathRawPic, - Expression pathCroppedPic, - Expression markers, - Expression originX, - Expression originY, - Expression angle, - Expression isoRatio, + Expression? id, + Expression? title, + Expression? description, + Expression? pathRawPic, + Expression? pathCroppedPic, + Expression? markers, + Expression? originX, + Expression? originY, + Expression? angle, + Expression? isoRatio, }) { return RawValuesInsertable({ if (id != null) 'id': id, @@ -298,18 +416,18 @@ class ProjectCompanion extends UpdateCompanion { }); } - ProjectCompanion copyWith( - {Value id, - Value title, - Value description, - Value pathRawPic, - Value pathCroppedPic, - Value markers, - Value originX, - Value originY, - Value angle, - Value isoRatio}) { - return ProjectCompanion( + ProjectsCompanion copyWith( + {Value? id, + Value? title, + Value? description, + Value? pathRawPic, + Value? pathCroppedPic, + Value? markers, + Value? originX, + Value? originY, + Value? angle, + Value? isoRatio}) { + return ProjectsCompanion( id: id ?? this.id, title: title ?? this.title, description: description ?? this.description, @@ -361,7 +479,7 @@ class ProjectCompanion extends UpdateCompanion { @override String toString() { - return (StringBuffer('ProjectCompanion(') + return (StringBuffer('ProjectsCompanion(') ..write('id: $id, ') ..write('title: $title, ') ..write('description: $description, ') @@ -377,227 +495,17 @@ class ProjectCompanion extends UpdateCompanion { } } -class $ProjectsTable extends Projects with TableInfo<$ProjectsTable, Project> { - final GeneratedDatabase _db; - final String _alias; - $ProjectsTable(this._db, [this._alias]); - final VerificationMeta _idMeta = const VerificationMeta('id'); - GeneratedIntColumn _id; - @override - GeneratedIntColumn get id => _id ??= _constructId(); - GeneratedIntColumn _constructId() { - return GeneratedIntColumn('id', $tableName, false, - hasAutoIncrement: true, declaredAsPrimaryKey: true); - } - - final VerificationMeta _titleMeta = const VerificationMeta('title'); - GeneratedTextColumn _title; - @override - GeneratedTextColumn get title => _title ??= _constructTitle(); - GeneratedTextColumn _constructTitle() { - return GeneratedTextColumn( - 'title', - $tableName, - false, - ); - } - - final VerificationMeta _descriptionMeta = - const VerificationMeta('description'); - GeneratedTextColumn _description; - @override - GeneratedTextColumn get description => - _description ??= _constructDescription(); - GeneratedTextColumn _constructDescription() { - return GeneratedTextColumn('description', $tableName, false, - defaultValue: const Constant('')); - } - - final VerificationMeta _pathRawPicMeta = const VerificationMeta('pathRawPic'); - GeneratedTextColumn _pathRawPic; - @override - GeneratedTextColumn get pathRawPic => _pathRawPic ??= _constructPathRawPic(); - GeneratedTextColumn _constructPathRawPic() { - return GeneratedTextColumn('path_raw_pic', $tableName, false, - defaultValue: const Constant('')); - } - - final VerificationMeta _pathCroppedPicMeta = - const VerificationMeta('pathCroppedPic'); - GeneratedTextColumn _pathCroppedPic; - @override - GeneratedTextColumn get pathCroppedPic => - _pathCroppedPic ??= _constructPathCroppedPic(); - GeneratedTextColumn _constructPathCroppedPic() { - return GeneratedTextColumn('path_cropped_pic', $tableName, false, - defaultValue: const Constant('')); - } - - final VerificationMeta _markersMeta = const VerificationMeta('markers'); - GeneratedBlobColumn _markers; - @override - GeneratedBlobColumn get markers => _markers ??= _constructMarkers(); - GeneratedBlobColumn _constructMarkers() { - return GeneratedBlobColumn( - 'markers', - $tableName, - true, - ); - } - - final VerificationMeta _originXMeta = const VerificationMeta('originX'); - GeneratedRealColumn _originX; - @override - GeneratedRealColumn get originX => _originX ??= _constructOriginX(); - GeneratedRealColumn _constructOriginX() { - return GeneratedRealColumn( - 'origin_x', - $tableName, - true, - ); - } - - final VerificationMeta _originYMeta = const VerificationMeta('originY'); - GeneratedRealColumn _originY; - @override - GeneratedRealColumn get originY => _originY ??= _constructOriginY(); - GeneratedRealColumn _constructOriginY() { - return GeneratedRealColumn( - 'origin_y', - $tableName, - true, - ); - } - - final VerificationMeta _angleMeta = const VerificationMeta('angle'); - GeneratedRealColumn _angle; - @override - GeneratedRealColumn get angle => _angle ??= _constructAngle(); - GeneratedRealColumn _constructAngle() { - return GeneratedRealColumn( - 'angle', - $tableName, - true, - ); - } - - final VerificationMeta _isoRatioMeta = const VerificationMeta('isoRatio'); - GeneratedRealColumn _isoRatio; - @override - GeneratedRealColumn get isoRatio => _isoRatio ??= _constructIsoRatio(); - GeneratedRealColumn _constructIsoRatio() { - return GeneratedRealColumn( - 'iso_ratio', - $tableName, - true, - ); - } - - @override - List get $columns => [ - id, - title, - description, - pathRawPic, - pathCroppedPic, - markers, - originX, - originY, - angle, - isoRatio - ]; - @override - $ProjectsTable get asDslTable => this; - @override - String get $tableName => _alias ?? 'projects'; - @override - final String actualTableName = 'projects'; - @override - VerificationContext validateIntegrity(Insertable instance, - {bool isInserting = false}) { - final context = VerificationContext(); - final data = instance.toColumns(true); - if (data.containsKey('id')) { - context.handle(_idMeta, id.isAcceptableOrUnknown(data['id'], _idMeta)); - } - if (data.containsKey('title')) { - context.handle( - _titleMeta, title.isAcceptableOrUnknown(data['title'], _titleMeta)); - } else if (isInserting) { - context.missing(_titleMeta); - } - if (data.containsKey('description')) { - context.handle( - _descriptionMeta, - description.isAcceptableOrUnknown( - data['description'], _descriptionMeta)); - } - if (data.containsKey('path_raw_pic')) { - context.handle( - _pathRawPicMeta, - pathRawPic.isAcceptableOrUnknown( - data['path_raw_pic'], _pathRawPicMeta)); - } - if (data.containsKey('path_cropped_pic')) { - context.handle( - _pathCroppedPicMeta, - pathCroppedPic.isAcceptableOrUnknown( - data['path_cropped_pic'], _pathCroppedPicMeta)); - } - if (data.containsKey('markers')) { - context.handle(_markersMeta, - markers.isAcceptableOrUnknown(data['markers'], _markersMeta)); - } - if (data.containsKey('origin_x')) { - context.handle(_originXMeta, - originX.isAcceptableOrUnknown(data['origin_x'], _originXMeta)); - } - if (data.containsKey('origin_y')) { - context.handle(_originYMeta, - originY.isAcceptableOrUnknown(data['origin_y'], _originYMeta)); - } - if (data.containsKey('angle')) { - context.handle( - _angleMeta, angle.isAcceptableOrUnknown(data['angle'], _angleMeta)); - } - if (data.containsKey('iso_ratio')) { - context.handle(_isoRatioMeta, - isoRatio.isAcceptableOrUnknown(data['iso_ratio'], _isoRatioMeta)); - } - return context; - } - - @override - Set get $primaryKey => {id}; - @override - Project map(Map data, {String tablePrefix}) { - final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : null; - return Project.fromData(data, _db, prefix: effectivePrefix); - } - - @override - $ProjectsTable createAlias(String alias) { - return $ProjectsTable(_db, alias); - } -} - abstract class _$ProjectsDatabase extends GeneratedDatabase { - _$ProjectsDatabase(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e); - $ProjectsTable _projects; - $ProjectsTable get projects => _projects ??= $ProjectsTable(this); - ProjectsDao _projectsDao; - ProjectsDao get projectsDao => - _projectsDao ??= ProjectsDao(this as ProjectsDatabase); + _$ProjectsDatabase(QueryExecutor e) : super(e); + late final $ProjectsTable projects = $ProjectsTable(this); + late final ProjectsDao projectsDao = ProjectsDao(this as ProjectsDatabase); @override - Iterable get allTables => allSchemaEntities.whereType(); + Iterable> get allTables => + allSchemaEntities.whereType>(); @override List get allSchemaEntities => [projects]; } -// ************************************************************************** -// DaoGenerator -// ************************************************************************** - mixin _$ProjectsDaoMixin on DatabaseAccessor { $ProjectsTable get projects => attachedDatabase.projects; } diff --git a/lib/projects/pictures/picture.dart b/lib/projects/pictures/picture.dart index b3148d8..1a30ac3 100644 --- a/lib/projects/pictures/picture.dart +++ b/lib/projects/pictures/picture.dart @@ -14,7 +14,7 @@ class Picture { return dir.create(recursive: true); } - static Future getImageFromSource(ImageSource selection) async { + static Future getImageFromSource(ImageSource selection) async { /** * Retrieve or Take picture and keep file in intern data. * @@ -24,7 +24,7 @@ class Picture { */ // Retrieve image via selected source - PickedFile pickedPicture = await _imagePicker.getImage(source: selection); + XFile? pickedPicture = await _imagePicker.pickImage(source: selection); if (pickedPicture == null) return null; diff --git a/lib/projects/pictures/shapes.dart b/lib/projects/pictures/shapes.dart index b0419d5..4d14196 100644 --- a/lib/projects/pictures/shapes.dart +++ b/lib/projects/pictures/shapes.dart @@ -3,7 +3,6 @@ import 'dart:math'; import 'package:flutter/material.dart' hide Rect; import 'dart:ui' as ui; import 'package:keydecoder/utils/gesture_x_detector.dart'; -import 'package:vector_math/vector_math_64.dart' hide Colors; abstract class Shape { @@ -60,15 +59,15 @@ class Line extends Shape { fixAngle = true; mAngle = l.mAngle + pi/2; a = Offset.fromDirection(mAngle) + p; - b = xtersect(l); + b = xtersect(l)!; } bool fixAngle = false; - Offset a; - Offset b; + late Offset a; + late Offset b; - double mAngle; + late double mAngle; double computeAngle() { return (b-a).direction; @@ -106,7 +105,7 @@ class Line extends Shape { } */ - Offset xtersect(Line other) { + Offset? xtersect(Line other) { if ((((mAngle - other.mAngle) % pi) + pi) % pi == 0) return null; if (((mAngle % pi) + pi) % pi == pi/2.0) { // vertical line at x = a.dx @@ -122,7 +121,7 @@ class Line extends Shape { return Offset(x, m0 * (x - a.dx) + a.dy); } - List xtersectList(List others, {ui.Rect bounds}) { + List xtersectList(List others, {ui.Rect? bounds}) { var m0 = tan(mAngle); // Line 0: y = m0 (x - a.dx) + a.dy bool thisIsVertical = (((mAngle % pi) + pi) % pi == pi/2.0); @@ -204,7 +203,7 @@ class RotatedRect extends Shape { vertices = ui.Vertices(ui.VertexMode.triangleFan, summits); } - ui.Vertices vertices; + late ui.Vertices vertices; @override void draw(Canvas canvas, BuildContext context) { @@ -279,15 +278,14 @@ class Crosshair extends Shape { final double baseSize; double size; - RotatedRect rr; double angle; - Offset measures; + Offset? measures; - TextPainter textPainter; - TextStyle textStyle; - TextSpan textSpan; + late TextPainter textPainter; + late TextStyle textStyle; + late TextSpan textSpan; static Paint get markerPaint => Paint() ..color = Color(0xFFCCCCCC) @@ -324,19 +322,19 @@ class Crosshair extends Shape { ); textPainter.layout(); - double sign = measures.dy.sign; + double sign = measures!.dy.sign; // Main measures - String mainStr = measures.dy.abs().toStringAsFixed(3); - Color mainColor = Colors.red[700]; + String mainStr = measures!.dy.abs().toStringAsFixed(3); + Color mainColor = Colors.red.shade700; drawText(canvas, mainStr, mainColor, center, sign * ((sign < 0) ? (-size) : (-textPainter.width - size)), sign * ((sign < 0) ? (textPainter.height / 2) : (-textPainter.height / 2)), angle + pi/2); - sign = measures.dx.sign; + sign = measures!.dx.sign; // Cross measures - String crossStr = measures.dx.abs().toStringAsFixed(3); - Color crossColor = Colors.blue[700]; + String crossStr = measures!.dx.abs().toStringAsFixed(3); + Color crossColor = Colors.blue.shade700; drawText(canvas, crossStr, crossColor, center, sign * ((sign < 0) ? (-size) : (-textPainter.width - size)), sign * ((sign < 0) ? (textPainter.height / 2) : (-textPainter.height / 2)), angle); } diff --git a/lib/projects/projectview.dart b/lib/projects/projectview.dart index 364b3c8..d47bf79 100644 --- a/lib/projects/projectview.dart +++ b/lib/projects/projectview.dart @@ -2,12 +2,12 @@ import 'dart:io'; import 'dart:math'; import 'package:flutter/material.dart'; -import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; +import 'package:material_design_icons_flutter/material_design_icons_flutter.dart' show MdiIcons; import '../utils/utils.dart'; import 'model/projects.dart'; class ProjectThumbnail extends StatelessWidget { - ProjectThumbnail({Key key, this.project}) : super(key: key); + ProjectThumbnail({Key? key, required this.project}) : super(key: key); final Project project; @@ -36,9 +36,9 @@ class ProjectThumbnail extends StatelessWidget { Widget projectStepper(Project project) { - final Color _colorDisable = Colors.grey[600]; - final Color _colorActive = Colors.lightBlue[400]; - final Color _colorDone = Colors.lightGreen[400]; + final Color _colorDisable = Colors.grey.shade600; + final Color _colorActive = Colors.lightBlue.shade400; + final Color _colorDone = Colors.lightGreen.shade400; int curStep = 0; diff --git a/lib/tutorial_dialog.dart b/lib/tutorial_dialog.dart index 883e171..688ba2b 100644 --- a/lib/tutorial_dialog.dart +++ b/lib/tutorial_dialog.dart @@ -4,7 +4,7 @@ class TutorialDialog extends StatefulWidget { TutorialDialog({this.onlyPage}); - final int onlyPage; + final int? onlyPage; @override _TutorialDialogState createState() => _TutorialDialogState(); @@ -12,7 +12,7 @@ class TutorialDialog extends StatefulWidget { class _TutorialDialogState extends State { - int _curPage; + int _curPage = 0; @override void initState() { @@ -80,6 +80,15 @@ Once done, you can validate and retrieve your measures on your project's page. ], ) }, + { + 'title' : Text('Delete project', style: TextStyle(fontWeight: FontWeight.bold),), + 'content' : Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text('''You can delete a project by swiping its tile in the project list to the left''', textAlign: TextAlign.justify,), + ], + ) + }, ]; @override @@ -91,14 +100,14 @@ Once done, you can validate and retrieve your measures on your project's page. actions: (_curPage > 0) ? ([ Visibility( visible: widget.onlyPage == null, - child: FlatButton( + child: TextButton( onPressed: () { setState(() => _curPage--); }, child: Text('Back'), ), ), - FlatButton( + TextButton( onPressed: () { if (_curPage + 1 >= _texts.length || widget.onlyPage != null) Navigator.pop(context); @@ -108,7 +117,7 @@ Once done, you can validate and retrieve your measures on your project's page. child: Text('Continue'), ), ]) : ([ - FlatButton( + TextButton( onPressed: () { if (_curPage + 1 >= _texts.length || widget.onlyPage != null) Navigator.pop(context); diff --git a/lib/utils/gesture_x_detector.dart b/lib/utils/gesture_x_detector.dart index 2490087..a1a70ee 100644 --- a/lib/utils/gesture_x_detector.dart +++ b/lib/utils/gesture_x_detector.dart @@ -12,20 +12,21 @@ import 'package:vector_math/vector_math_64.dart' hide Colors; /// For handle rotate event, please use rotateAngle on onScaleUpdate. class XGestureDetector extends StatefulWidget { /// Creates a widget that detects gestures. - XGestureDetector( - {@required this.child, - this.onTap, - this.onMoveUpdate, - this.onMoveEnd, - this.onMoveStart, - this.onScaleStart, - this.onScaleUpdate, - this.onScaleEnd, - this.onDoubleTap, - this.bypassTapEventOnDoubleTap = false, - this.doubleTapTimeConsider = 250, - this.longPressTimeConsider = 350, - this.onLongPress}); + XGestureDetector({ + required this.child, + this.onTap, + this.onMoveUpdate, + this.onMoveEnd, + this.onMoveStart, + this.onScaleStart, + this.onScaleUpdate, + this.onScaleEnd, + this.onDoubleTap, + this.bypassTapEventOnDoubleTap = false, + this.doubleTapTimeConsider = 250, + this.longPressTimeConsider = 350, + this.onLongPress + }); /// The widget below this widget in the tree. /// @@ -41,28 +42,28 @@ class XGestureDetector extends StatefulWidget { final int doubleTapTimeConsider; /// The pointer that previously triggered the onTapDown has also triggered onTapUp which ends up causing a tap. - final void Function(int pointer, Offset localPos, Offset position) onTap; + final void Function(int pointer, Offset localPos, Offset position)? onTap; /// A pointer has contacted the screen with a primary button and has begun to /// move. - final void Function(int pointer, Offset localPos, Offset position) + final void Function(int pointer, Offset localPos, Offset position)? onMoveStart; /// A pointer that is in contact with the screen with a primary button and /// moving has moved again. final void Function( - Offset localPos, Offset position, Offset localDelta, Offset delta) + Offset localPos, Offset position, Offset localDelta, Offset delta)? onMoveUpdate; /// A pointer that was previously in contact with the screen with a primary /// button and moving is no longer in contact with the screen and was moving /// at a specific velocity when it stopped contacting the screen. - final void Function(int pointer, Offset localPosition, Offset position) + final void Function(int pointer, Offset localPosition, Offset position)? onMoveEnd; /// The pointers in contact with the screen have established a focal point and /// initial scale of 1.0. - final void Function(Offset initialFocusPoint) onScaleStart; + final void Function(Offset initialFocusPoint)? onScaleStart; /// The pointers in contact with the screen have indicated a new focal point /// and/or scale. @@ -75,19 +76,19 @@ class XGestureDetector extends StatefulWidget { /// /// **rotationAngle** the rotate angle in radians - using for rotate final void Function( - Offset changedFocusPoint, double scale, double rotationAngle) + Offset changedFocusPoint, double scale, double rotationAngle)? onScaleUpdate; /// The pointers are no longer in contact with the screen. - final void Function() onScaleEnd; + final void Function()? onScaleEnd; /// The user has tapped the screen at the same location twice in quick succession. - final void Function(Offset localPos, Offset position) onDoubleTap; + final void Function(Offset localPos, Offset position)? onDoubleTap; /// A pointer has remained in contact with the screen at the same location for a long period of time /// /// @param - final void Function(int pointer, Offset localPos, Offset position) + final void Function(int pointer, Offset localPos, Offset position)? onLongPress; /// A specific duration to detect long press @@ -108,10 +109,10 @@ enum _GestureState { class _XGestureDetectorState extends State { List<_Touch> touches = []; - double initialScaleDistance; + double initialScaleDistance = 0.0; _GestureState state = _GestureState.Unknown; - Timer doubleTapTimer; - Timer longPressTimer; + Timer? doubleTapTimer; + Timer? longPressTimer; Offset lastTouchUpPos = Offset(0, 0); @override @@ -154,12 +155,12 @@ class _XGestureDetectorState extends State { state = _GestureState.MoveStart; touch.startOffset = event.localPosition; if (widget.onMoveStart != null) - widget.onMoveStart( + widget.onMoveStart!( event.pointer, event.localPosition, event.position); break; case _GestureState.MoveStart: if (widget.onMoveUpdate != null) - widget.onMoveUpdate(event.localPosition, event.position, + widget.onMoveUpdate!(event.localPosition, event.position, event.localDelta, event.delta); break; case _GestureState.ScaleStart: @@ -169,7 +170,7 @@ class _XGestureDetectorState extends State { if (widget.onScaleStart != null) { final centerOffset = (touches[0].currentOffset + touches[1].currentOffset) / 2; - widget.onScaleStart(centerOffset); + widget.onScaleStart!(centerOffset); } break; case _GestureState.Scalling: @@ -179,7 +180,7 @@ class _XGestureDetectorState extends State { (touches[0].currentOffset - touches[1].currentOffset).distance; final centerOffset = (touches[0].currentOffset + touches[1].currentOffset) / 2; - widget.onScaleUpdate( + widget.onScaleUpdate!( centerOffset, newDistance / initialScaleDistance, rotation); } break; @@ -215,7 +216,7 @@ class _XGestureDetectorState extends State { } else { cleanupTimer(); if ((event.localPosition - lastTouchUpPos).distanceSquared < 200) { - widget.onDoubleTap(event.localPosition, event.position); + widget.onDoubleTap!(event.localPosition, event.position); } else { startDoubleTapTimer( event.pointer, event.localPosition, event.position); @@ -225,11 +226,11 @@ class _XGestureDetectorState extends State { } else if (state == _GestureState.ScaleStart || state == _GestureState.Scalling) { state = _GestureState.Unknown; - if (widget.onScaleEnd != null) widget.onScaleEnd(); + if (widget.onScaleEnd != null) widget.onScaleEnd!(); } else if (state == _GestureState.MoveStart) { state = _GestureState.Unknown; if (widget.onMoveEnd != null) - widget.onMoveEnd(event.pointer, event.localPosition, event.position); + widget.onMoveEnd!(event.pointer, event.localPosition, event.position); } else if (state == _GestureState.Unknown && touchCount == 2) { state = _GestureState.ScaleStart; } else { @@ -242,14 +243,14 @@ class _XGestureDetectorState extends State { void startLongPressTimer(int pointer, Offset localPos, Offset position) { if (widget.onLongPress != null) { if (longPressTimer != null) { - longPressTimer.cancel(); + longPressTimer!.cancel(); longPressTimer = null; } longPressTimer = Timer(Duration(milliseconds: widget.longPressTimeConsider), () { if (touchCount == 1 && touches[0].id == pointer) { state = _GestureState.LongPress; - widget.onLongPress(pointer, localPos, position); + widget.onLongPress!(pointer, localPos, position); cleanupTimer(); } }); @@ -269,18 +270,18 @@ class _XGestureDetectorState extends State { void cleanupTimer() { if (doubleTapTimer != null) { - doubleTapTimer.cancel(); + doubleTapTimer!.cancel(); doubleTapTimer = null; } if (longPressTimer != null) { - longPressTimer.cancel(); + longPressTimer!.cancel(); longPressTimer = null; } } void callOnTap(int pointer, Offset localPos, Offset globalPos) { if (widget.onTap != null) { - widget.onTap(pointer, localPos, globalPos); + widget.onTap!(pointer, localPos, globalPos); } } @@ -301,7 +302,7 @@ class _XGestureDetectorState extends State { class _Touch { int id; Offset startOffset; - Offset currentOffset; + late Offset currentOffset; _Touch(this.id, this.startOffset) { this.currentOffset = startOffset; @@ -315,7 +316,7 @@ Offset transformOffset(Matrix4 matrix, Offset offset) { ); } -Offset vect2Offset(Vector2 v) => Offset(v?.x, v?.y); -Vector2 offset2Vect(Offset o) => Vector2(o?.dx, o?.dy); +Offset vect2Offset(Vector2 v) => Offset(v.x, v.y); +Vector2 offset2Vect(Offset o) => Vector2(o.dx, o.dy); Offset invertOffset(Offset o) => Offset(o.dy, o.dx); \ No newline at end of file diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 66244ba..d6562e8 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -2,7 +2,6 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:moor_flutter/moor_flutter.dart'; /// blocks rotation; sets orientation to: portrait Future landscapeModeOnly() { @@ -20,21 +19,28 @@ Future enableRotation() { ]); } +Future portraitModeOnly() { + return SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitDown, + DeviceOrientation.portraitUp, + ]); +} + class VisibleButton extends StatelessWidget { - final bool visible; + final bool visible; final void Function() onTap; final double padding; final bool keepSpace; - final Widget child; + final Widget child; VisibleButton({ - Key key, - this.visible, - this.onTap, + Key? key, + required this.visible, + required this.onTap, this.padding = 8.0, this.keepSpace = false, - this.child + required this.child }) : super(key: key); @override @@ -57,7 +63,7 @@ class VisibleButton extends StatelessWidget { class RoundIconContainer extends StatelessWidget { - RoundIconContainer({Key key, this.color, this.size = 40, this.padding = 4.0, this.tick = false, this.child}) : super(key: key); + RoundIconContainer({Key? key, required this.color, this.size = 40, this.padding = 4.0, this.tick = false, required this.child}) : super(key: key); final Color color; @@ -101,8 +107,8 @@ class RoundIconContainer extends StatelessWidget { class InvertedColorText extends StatelessWidget { InvertedColorText({ - Key key, - this.text + Key? key, + required this.text }) : super(key: key); final Text text; @@ -119,7 +125,7 @@ class InvertedColorText extends StatelessWidget { List fromBlob(Uint8List blob) { Float64x2List lf2 = Float64x2List.view(blob.buffer); - List res = List(); + List res = []; lf2.forEach((elt) { res.add(Offset(elt.x, elt.y)); }); diff --git a/native_cv/CMakeLists.txt b/native_cv/CMakeLists.txt index d3d8e6d..bc56121 100644 --- a/native_cv/CMakeLists.txt +++ b/native_cv/CMakeLists.txt @@ -7,16 +7,11 @@ set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${OpenCV_DIR}/libs find_library(log-lib log) add_library(native_cv - - SHARED - - ./core_cv.cpp - ) + SHARED + ./core_cv.cpp +) target_link_libraries(native_cv - - lib_opencv - - ${log-lib} - - ) \ No newline at end of file + lib_opencv + ${log-lib} +) \ No newline at end of file diff --git a/native_cv/core_cv.cpp b/native_cv/core_cv.cpp index 1367a9e..3dc246e 100644 --- a/native_cv/core_cv.cpp +++ b/native_cv/core_cv.cpp @@ -12,35 +12,58 @@ typedef struct sCoordinate typedef struct sNativeIntersection { - Coordinate* topLeft; - Coordinate* topRight; - Coordinate* bottomLeft; - Coordinate* bottomRight; + Coordinate topLeft; + Coordinate topRight; + Coordinate bottomLeft; + Coordinate bottomRight; } NativeIntersection; extern "C" -int homography_warp(NativeIntersection* points, char *src, char *dst); +Coordinate create_coordinate(double x, double y); + +extern "C" +NativeIntersection create_intersection(Coordinate topLeft, Coordinate topRight, Coordinate bottomLeft, Coordinate bottomRight); + +extern "C" +int homography_warp(NativeIntersection points, char *src, char *dst); #define ISOwidth 85.60f #define ISOheight 53.98f #define isoWidthDest (ISOwidth * 40.0f) #define isoHeightDest (isoWidthDest / ISOwidth * ISOheight) -cv::Point2f cvPointFromCoordinate(Coordinate* c) { - return cv::Point2f((float)(c->x), (float)(c->y)); +Coordinate create_coordinate(double x, double y) { + Coordinate res; + res.x = x; + res.y = y; + + return res; +} + +NativeIntersection create_intersection(Coordinate topLeft, Coordinate topRight, Coordinate bottomLeft, Coordinate bottomRight) { + NativeIntersection res; + res.topLeft = topLeft; + res.topRight = topRight; + res.bottomLeft = bottomLeft; + res.bottomRight = bottomRight; + + return res; +} + +cv::Point2f cvPointFromCoordinate(Coordinate c) { + return cv::Point2f((float)(c.x), (float)(c.y)); } -std::vector nativeInter2Vect(NativeIntersection* points) { +std::vector nativeInter2Vect(NativeIntersection points) { return std::vector({ - cvPointFromCoordinate(points->topLeft), - cvPointFromCoordinate(points->topRight), - cvPointFromCoordinate(points->bottomRight), - cvPointFromCoordinate(points->bottomLeft) + cvPointFromCoordinate(points.topLeft), + cvPointFromCoordinate(points.topRight), + cvPointFromCoordinate(points.bottomRight), + cvPointFromCoordinate(points.bottomLeft) }); } -extern "C" __attribute__((visibility("default"))) __attribute__((used)) -int homography_warp(NativeIntersection* points, char *src, char *dst) { +int homography_warp(NativeIntersection points, char *src, char *dst) { // Get Mat of original picture cv::Mat src_mat = cv::imread(src); diff --git a/pubspec.lock b/pubspec.lock index 4902efd..1253496 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,219 +5,298 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - url: "https://pub.dartlang.org" + sha256: "3444216bfd127af50bbe4862d8843ed44db946dd933554f0d7285e89f10e28ac" + url: "https://pub.dev" source: hosted - version: "12.0.0" + version: "50.0.0" analyzer: dependency: transitive description: name: analyzer - url: "https://pub.dartlang.org" + sha256: "68796c31f510c8455a06fed75fc97d8e5ad04d324a830322ab3efc9feb6201c1" + url: "https://pub.dev" source: hosted - version: "0.40.6" - analyzer_plugin_fork: + version: "5.2.0" + analyzer_plugin: dependency: transitive description: - name: analyzer_plugin_fork - url: "https://pub.dartlang.org" + name: analyzer_plugin + sha256: c1d5f167683de03d5ab6c3b53fc9aeefc5d59476e7810ba7bbddff50c6f4392d + url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "0.11.2" animate_icons: dependency: "direct main" description: name: animate_icons - url: "https://pub.dartlang.org" + sha256: "3201c60f2051997cf3cbde4b2f07d269e01fa53a6a3a2986ef26f614419880fd" + url: "https://pub.dev" source: hosted - version: "0.0.4" + version: "2.0.0" archive: dependency: transitive description: name: archive - url: "https://pub.dartlang.org" + sha256: "20071638cbe4e5964a427cfa0e86dce55d060bc7d82d56f3554095d7239a8765" + url: "https://pub.dev" source: hosted - version: "2.0.13" + version: "3.4.2" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + sha256: c372bb384f273f0c2a8aaaa226dad84dc27c8519a691b888725dec59518ad53a + url: "https://pub.dev" source: hosted - version: "1.6.0" + version: "2.4.1" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" source: hosted - version: "2.5.0-nullsafety.3" + version: "2.11.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0-nullsafety.3" + version: "2.1.1" build: dependency: transitive description: name: build - url: "https://pub.dartlang.org" + sha256: "3fbda25365741f8251b39f3917fb3c8e286a96fd068a5a242e11c2012d495777" + url: "https://pub.dev" source: hosted - version: "1.5.0" + version: "2.3.1" build_config: dependency: transitive description: name: build_config - url: "https://pub.dartlang.org" + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" source: hosted - version: "0.4.2" + version: "1.1.1" build_daemon: dependency: transitive description: name: build_daemon - url: "https://pub.dartlang.org" + sha256: "757153e5d9cd88253cb13f28c2fb55a537dc31fefd98137549895b5beb7c6169" + url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "3.1.1" build_resolvers: dependency: transitive description: name: build_resolvers - url: "https://pub.dartlang.org" + sha256: "7c35a3a7868626257d8aee47b51c26b9dba11eaddf3431117ed2744951416aab" + url: "https://pub.dev" source: hosted - version: "1.4.3" + version: "2.1.0" build_runner: dependency: "direct dev" description: name: build_runner - url: "https://pub.dartlang.org" + sha256: b0a8a7b8a76c493e85f1b84bffa0588859a06197863dba8c9036b15581fd9727 + url: "https://pub.dev" source: hosted - version: "1.10.4" + version: "2.3.3" build_runner_core: dependency: transitive description: name: build_runner_core - url: "https://pub.dartlang.org" + sha256: "14febe0f5bac5ae474117a36099b4de6f1dbc52df6c5e55534b3da9591bf4292" + url: "https://pub.dev" source: hosted - version: "6.0.3" + version: "7.2.7" built_collection: dependency: transitive description: name: built_collection - url: "https://pub.dartlang.org" + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" source: hosted - version: "4.3.2" + version: "5.1.1" built_value: dependency: transitive description: name: built_value - url: "https://pub.dartlang.org" + sha256: a8de5955205b4d1dbbbc267daddf2178bd737e4bab8987c04a500478c9651e74 + url: "https://pub.dev" source: hosted - version: "7.1.0" + version: "8.6.3" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" source: hosted - version: "1.1.0-nullsafety.5" + version: "1.3.0" charcode: dependency: transitive description: name: charcode - url: "https://pub.dartlang.org" + sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306 + url: "https://pub.dev" source: hosted - version: "1.2.0-nullsafety.3" + version: "1.3.1" checked_yaml: dependency: transitive description: name: checked_yaml - url: "https://pub.dartlang.org" + sha256: "3d1505d91afa809d177efd4eed5bb0eb65805097a1463abdd2add076effae311" + url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "2.0.2" cli_util: dependency: transitive description: name: cli_util - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.4" - clock: - dependency: transitive - description: - name: clock - url: "https://pub.dartlang.org" + sha256: "66f86e916d285c1a93d3b79587d94bd71984a66aac4ff74e524cfa7877f1395c" + url: "https://pub.dev" source: hosted - version: "1.1.0-nullsafety.3" + version: "0.3.5" code_builder: dependency: transitive description: name: code_builder - url: "https://pub.dartlang.org" + sha256: "0d43dd1288fd145de1ecc9a3948ad4a6d5a82f0a14c4fdd0892260787d975cbe" + url: "https://pub.dev" source: hosted - version: "3.5.0" + version: "4.4.0" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + url: "https://pub.dev" source: hosted - version: "1.15.0-nullsafety.5" + version: "1.17.2" community_material_icon: dependency: "direct main" description: name: community_material_icon - url: "https://pub.dartlang.org" + sha256: bb389689f6278158d7b9d9b0c9433e603933283104fea226594590f61503fd08 + url: "https://pub.dev" source: hosted - version: "5.4.55" + version: "5.9.55" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "3.1.1" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9" + url: "https://pub.dev" + source: hosted + version: "0.3.3+4" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "3.0.2" dart_style: dependency: transitive description: name: dart_style - url: "https://pub.dartlang.org" + sha256: "5be16bf1707658e4c03078d4a9b90208ded217fb02c163e207d334082412f2fb" + url: "https://pub.dev" source: hosted - version: "1.3.9" - fake_async: + version: "2.2.5" + drift: dependency: transitive description: - name: fake_async - url: "https://pub.dartlang.org" + name: drift + sha256: b8465fb684bae76ac98e102d831625bff32c0e802db38d9edff0fe338d915fd4 + url: "https://pub.dev" + source: hosted + version: "2.4.2" + drift_dev: + dependency: "direct dev" + description: + name: drift_dev + sha256: b237a939e9b4c55178187dacc78075e34184a0d6a3b2a7672fecc80a36dcf8f4 + url: "https://pub.dev" source: hosted - version: "1.2.0-nullsafety.3" + version: "2.4.1" + drift_sqflite: + dependency: "direct main" + description: + name: drift_sqflite + sha256: dd1afbd72555b7a72ebf053926078d8c302059af4f1eb22040fc27a056429acb + url: "https://pub.dev" + source: hosted + version: "2.0.1" ffi: - dependency: transitive + dependency: "direct main" description: name: ffi - url: "https://pub.dartlang.org" + sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99 + url: "https://pub.dev" source: hosted - version: "0.1.3" + version: "2.0.2" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + url: "https://pub.dev" source: hosted - version: "5.2.1" + version: "6.1.4" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "770eb1ab057b5ae4326d1c24cc57710758b9a46026349d021d6311bd27580046" + url: "https://pub.dev" + source: hosted + version: "0.9.2" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: "4ada532862917bf16e3adb3891fe3a5917a58bae03293e497082203a80909412" + url: "https://pub.dev" + source: hosted + version: "0.9.3+1" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: "412705a646a0ae90f33f37acfae6a0f7cbc02222d6cd34e479421c3e74d3853c" + url: "https://pub.dev" + source: hosted + version: "2.6.0" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: "1372760c6b389842b77156203308940558a2817360154084368608413835fc26" + url: "https://pub.dev" + source: hosted + version: "0.9.3" fixnum: dependency: transitive description: name: fixnum - url: "https://pub.dartlang.org" + sha256: "04be3e934c52e082558cc9ee21f42f5c1cd7a1262f4c63cd0357c08d5bba81ec" + url: "https://pub.dev" source: hosted - version: "0.10.11" + version: "1.0.1" flutter: dependency: "direct main" description: flutter @@ -227,49 +306,74 @@ packages: dependency: "direct main" description: name: flutter_keyboard_visibility - url: "https://pub.dartlang.org" + sha256: "4983655c26ab5b959252ee204c2fffa4afeb4413cd030455194ec0caa3b8e7cb" + url: "https://pub.dev" source: hosted - version: "4.0.2" + version: "5.4.1" + flutter_keyboard_visibility_linux: + dependency: transitive + description: + name: flutter_keyboard_visibility_linux + sha256: "6fba7cd9bb033b6ddd8c2beb4c99ad02d728f1e6e6d9b9446667398b2ac39f08" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + flutter_keyboard_visibility_macos: + dependency: transitive + description: + name: flutter_keyboard_visibility_macos + sha256: c5c49b16fff453dfdafdc16f26bdd8fb8d55812a1d50b0ce25fc8d9f2e53d086 + url: "https://pub.dev" + source: hosted + version: "1.0.0" flutter_keyboard_visibility_platform_interface: dependency: transitive description: name: flutter_keyboard_visibility_platform_interface - url: "https://pub.dartlang.org" + sha256: e43a89845873f7be10cb3884345ceb9aebf00a659f479d1c8f4293fcb37022a4 + url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "2.0.0" flutter_keyboard_visibility_web: dependency: transitive description: name: flutter_keyboard_visibility_web - url: "https://pub.dartlang.org" + sha256: d3771a2e752880c79203f8d80658401d0c998e4183edca05a149f5098ce6e3d1 + url: "https://pub.dev" source: hosted - version: "1.0.1" + version: "2.0.0" + flutter_keyboard_visibility_windows: + dependency: transitive + description: + name: flutter_keyboard_visibility_windows + sha256: fc4b0f0b6be9b93ae527f3d527fb56ee2d918cd88bbca438c478af7bcfd0ef73 + url: "https://pub.dev" + source: hosted + version: "1.0.0" flutter_launcher_icons: dependency: "direct dev" description: name: flutter_launcher_icons - url: "https://pub.dartlang.org" + sha256: ce0e501cfc258907842238e4ca605e74b7fd1cdf04b3b43e86c43f3e40a1592c + url: "https://pub.dev" source: hosted - version: "0.8.1" + version: "0.11.0" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle - url: "https://pub.dartlang.org" + sha256: "950e77c2bbe1692bc0874fc7fb491b96a4dc340457f4ea1641443d0a6c1ea360" + url: "https://pub.dev" source: hosted - version: "1.0.11" + version: "2.0.15" flutter_slidable: dependency: "direct main" description: name: flutter_slidable - url: "https://pub.dartlang.org" + sha256: "6c68e1fad129b4b807b2218ef4cf7f7f6f61c5ec8861c990dc2278d9d03cb09f" + url: "https://pub.dev" source: hosted - version: "0.5.7" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" + version: "2.0.0" flutter_web_plugins: dependency: transitive description: flutter @@ -279,366 +383,442 @@ packages: dependency: "direct main" description: name: fluttericon - url: "https://pub.dartlang.org" + sha256: "252fa8043826e93d972a602497a260cb3d62b5aea6d045793e4381590f2c1e99" + url: "https://pub.dev" source: hosted - version: "1.0.7" + version: "2.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" + source: hosted + version: "3.2.0" glob: dependency: transitive description: name: glob - url: "https://pub.dartlang.org" + sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c" + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "2.1.1" graphs: dependency: transitive description: name: graphs - url: "https://pub.dartlang.org" + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "2.3.1" http: dependency: transitive description: name: http - url: "https://pub.dartlang.org" + sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + url: "https://pub.dev" source: hosted - version: "0.12.2" + version: "0.13.5" http_multi_server: dependency: transitive description: name: http_multi_server - url: "https://pub.dartlang.org" + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "3.2.1" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" source: hosted - version: "3.1.4" + version: "4.0.2" image: dependency: "direct main" description: name: image - url: "https://pub.dartlang.org" + sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6" + url: "https://pub.dev" source: hosted - version: "2.1.19" + version: "3.3.0" image_picker: dependency: "direct main" description: name: image_picker - url: "https://pub.dartlang.org" + sha256: b6951e25b795d053a6ba03af5f710069c99349de9341af95155d52665cb4607c + url: "https://pub.dev" source: hosted - version: "0.6.7+14" + version: "0.8.9" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: "8179b54039b50eee561676232304f487602e2950ffb3e8995ed9034d6505ca34" + url: "https://pub.dev" + source: hosted + version: "0.8.7+4" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: "869fe8a64771b7afbc99fc433a5f7be2fea4d1cb3d7c11a48b6b579eb9c797f0" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: b3e2f21feb28b24dd73a35d7ad6e83f568337c70afab5eabac876e23803f264b + url: "https://pub.dev" + source: hosted + version: "0.8.8" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "02cbc21fe1706b97942b575966e5fbbeaac535e76deef70d3a242e4afb857831" + url: "https://pub.dev" + source: hosted + version: "0.2.1" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: cee2aa86c56780c13af2c77b5f2f72973464db204569e1ba2dd744459a065af4 + url: "https://pub.dev" + source: hosted + version: "0.2.1" image_picker_platform_interface: dependency: transitive description: name: image_picker_platform_interface - url: "https://pub.dartlang.org" + sha256: c1134543ae2187e85299996d21c526b2f403854994026d575ae4cf30d7bb2a32 + url: "https://pub.dev" source: hosted - version: "1.1.1" - intl: + version: "2.9.0" + image_picker_windows: dependency: transitive description: - name: intl - url: "https://pub.dartlang.org" + name: image_picker_windows + sha256: c3066601ea42113922232c7b7b3330a2d86f029f685bba99d82c30e799914952 + url: "https://pub.dev" source: hosted - version: "0.16.1" + version: "0.2.1" io: dependency: transitive description: name: io - url: "https://pub.dartlang.org" + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" source: hosted - version: "0.3.4" + version: "1.0.4" js: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + sha256: a5e201311cb08bf3912ebbe9a2be096e182d703f881136ec1e81a2338a9e120d + url: "https://pub.dev" source: hosted - version: "0.6.3-nullsafety.3" + version: "0.6.4" json_annotation: dependency: transitive description: name: json_annotation - url: "https://pub.dartlang.org" + sha256: c33da08e136c3df0190bd5bbe51ae1df4a7d96e7954d1d7249fea2968a72d317 + url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "4.8.0" logger: dependency: transitive description: name: logger - url: "https://pub.dartlang.org" + sha256: "6bbb9d6f7056729537a4309bda2e74e18e5d9f14302489cc1e93f33b3fe32cac" + url: "https://pub.dev" source: hosted - version: "0.9.4" + version: "2.0.2+1" logging: dependency: transitive description: name: logging - url: "https://pub.dartlang.org" + sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d" + url: "https://pub.dev" source: hosted - version: "0.11.4" + version: "1.1.1" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + url: "https://pub.dev" source: hosted - version: "0.12.10-nullsafety.3" + version: "0.12.16" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + url: "https://pub.dev" + source: hosted + version: "0.5.0" material_design_icons_flutter: dependency: "direct main" description: name: material_design_icons_flutter - url: "https://pub.dartlang.org" + sha256: "6f986b7a51f3ad4c00e33c5c84e8de1bdd140489bbcdc8b66fc1283dad4dea5a" + url: "https://pub.dev" source: hosted - version: "4.0.5755" + version: "7.0.7296" matrix4_transform: dependency: "direct main" description: name: matrix4_transform - url: "https://pub.dartlang.org" + sha256: "6ddeaa2c0e1f5c3f3a197f552377570b3e54fa0b8bf48507728a216fc0fd78a6" + url: "https://pub.dev" source: hosted - version: "1.1.6" + version: "2.0.1" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" source: hosted - version: "1.3.0-nullsafety.6" + version: "1.9.1" mime: dependency: transitive description: name: mime - url: "https://pub.dartlang.org" - source: hosted - version: "0.9.7" - moor: - dependency: transitive - description: - name: moor - url: "https://pub.dartlang.org" - source: hosted - version: "3.4.0" - moor_flutter: - dependency: "direct main" - description: - name: moor_flutter - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.0" - moor_generator: - dependency: "direct dev" - description: - name: moor_generator - url: "https://pub.dartlang.org" - source: hosted - version: "3.4.0" - node_interop: - dependency: transitive - description: - name: node_interop - url: "https://pub.dartlang.org" + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" source: hosted - version: "1.2.0" - node_io: + version: "1.0.4" + nested: dependency: transitive description: - name: node_io - url: "https://pub.dartlang.org" + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.0.0" package_config: dependency: transitive description: name: package_config - url: "https://pub.dartlang.org" + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" source: hosted - version: "1.9.3" + version: "2.1.0" path: dependency: "direct main" description: name: path - url: "https://pub.dartlang.org" + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" source: hosted - version: "1.8.0-nullsafety.3" + version: "1.8.3" path_provider: dependency: "direct main" description: name: path_provider - url: "https://pub.dartlang.org" + sha256: "909b84830485dbcd0308edf6f7368bc8fd76afa26a270420f34cabea2a6467a0" + url: "https://pub.dev" source: hosted - version: "1.6.24" - path_provider_linux: + version: "2.1.0" + path_provider_android: dependency: transitive description: - name: path_provider_linux - url: "https://pub.dartlang.org" + name: path_provider_android + sha256: "5d44fc3314d969b84816b569070d7ace0f1dea04bd94a83f74c4829615d22ad8" + url: "https://pub.dev" source: hosted - version: "0.0.1+2" - path_provider_macos: + version: "2.1.0" + path_provider_foundation: dependency: transitive description: - name: path_provider_macos - url: "https://pub.dartlang.org" + name: path_provider_foundation + sha256: "1b744d3d774e5a879bb76d6cd1ecee2ba2c6960c03b1020cd35212f6aa267ac5" + url: "https://pub.dev" source: hosted - version: "0.0.4+6" + version: "2.3.0" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: ba2b77f0c52a33db09fc8caf85b12df691bf28d983e84cf87ff6d693cfa007b3 + url: "https://pub.dev" + source: hosted + version: "2.2.0" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - url: "https://pub.dartlang.org" + sha256: bced5679c7df11190e1ddc35f3222c858f328fff85c3942e46e7f5589bf9eb84 + url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "2.1.0" path_provider_windows: dependency: transitive description: name: path_provider_windows - url: "https://pub.dartlang.org" - source: hosted - version: "0.0.4+3" - pedantic: - dependency: transitive - description: - name: pedantic - url: "https://pub.dartlang.org" + sha256: ee0e0d164516b90ae1f970bdf29f726f1aa730d7cfc449ecc74c495378b705da + url: "https://pub.dev" source: hosted - version: "1.9.2" + version: "2.2.0" petitparser: dependency: transitive description: name: petitparser - url: "https://pub.dartlang.org" + sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" + url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "5.1.0" platform: dependency: transitive description: name: platform - url: "https://pub.dartlang.org" + sha256: "57c07bf82207aee366dfaa3867b3164e4f03a238a461a11b0e8a3a510d51203d" + url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "3.1.1" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dartlang.org" + sha256: "43798d895c929056255600343db8f049921cbec94d31ec87f1dc5c16c01935dd" + url: "https://pub.dev" source: hosted - version: "1.0.3" - pool: + version: "2.1.5" + pointycastle: dependency: transitive description: - name: pool - url: "https://pub.dartlang.org" + name: pointycastle + sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" + url: "https://pub.dev" source: hosted - version: "1.4.0" - process: + version: "3.7.3" + pool: dependency: transitive description: - name: process - url: "https://pub.dartlang.org" + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" source: hosted - version: "3.0.13" + version: "1.5.1" provider: dependency: "direct main" description: name: provider - url: "https://pub.dartlang.org" + sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f + url: "https://pub.dev" source: hosted - version: "3.2.0" + version: "6.0.5" pub_semver: dependency: transitive description: name: pub_semver - url: "https://pub.dartlang.org" + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" source: hosted - version: "1.4.4" + version: "2.1.4" pubspec_parse: dependency: transitive description: name: pubspec_parse - url: "https://pub.dartlang.org" + sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367 + url: "https://pub.dev" source: hosted - version: "0.1.5" - quiver: - dependency: transitive - description: - name: quiver - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.5" + version: "1.2.3" recase: dependency: transitive description: name: recase - url: "https://pub.dartlang.org" + sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213 + url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "4.1.0" rename: dependency: "direct main" description: name: rename - url: "https://pub.dartlang.org" + sha256: "4d08eafe78e0787167c2fcdd5e32bbb0a6b2d8a7d23b38280f590df2a051415c" + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "3.0.1" shared_preferences: dependency: "direct main" description: name: shared_preferences - url: "https://pub.dartlang.org" + sha256: "0344316c947ffeb3a529eac929e1978fcd37c26be4e8468628bac399365a3ca1" + url: "https://pub.dev" source: hosted - version: "0.5.12+4" - shared_preferences_linux: + version: "2.2.0" + shared_preferences_android: dependency: transitive description: - name: shared_preferences_linux - url: "https://pub.dartlang.org" + name: shared_preferences_android + sha256: fe8401ec5b6dcd739a0fe9588802069e608c3fdbfd3c3c93e546cf2f90438076 + url: "https://pub.dev" source: hosted - version: "0.0.2+4" - shared_preferences_macos: + version: "2.2.0" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: d29753996d8eb8f7619a1f13df6ce65e34bc107bef6330739ed76f18b22310ef + url: "https://pub.dev" + source: hosted + version: "2.3.3" + shared_preferences_linux: dependency: transitive description: - name: shared_preferences_macos - url: "https://pub.dartlang.org" + name: shared_preferences_linux + sha256: "71d6806d1449b0a9d4e85e0c7a917771e672a3d5dc61149cc9fac871115018e1" + url: "https://pub.dev" source: hosted - version: "0.0.1+11" + version: "2.3.0" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - url: "https://pub.dartlang.org" + sha256: "23b052f17a25b90ff2b61aad4cc962154da76fb62848a9ce088efe30d7c50ab1" + url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "2.3.0" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - url: "https://pub.dartlang.org" + sha256: "7347b194fb0bbeb4058e6a4e87ee70350b6b2b90f8ac5f8bd5b3a01548f6d33a" + url: "https://pub.dev" source: hosted - version: "0.1.2+7" + version: "2.2.0" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - url: "https://pub.dartlang.org" + sha256: f95e6a43162bce43c9c3405f3eb6f39e5b5d11f65fab19196cf8225e2777624d + url: "https://pub.dev" source: hosted - version: "0.0.1+3" + version: "2.3.0" shelf: dependency: transitive description: name: shelf - url: "https://pub.dartlang.org" + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" source: hosted - version: "0.7.9" + version: "1.4.1" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - url: "https://pub.dartlang.org" + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + url: "https://pub.dev" source: hosted - version: "0.2.3" + version: "1.0.4" sky_engine: dependency: transitive description: flutter @@ -648,205 +828,258 @@ packages: dependency: transitive description: name: source_gen - url: "https://pub.dartlang.org" + sha256: "373f96cf5a8744bc9816c1ff41cf5391bbdbe3d7a96fe98c622b6738a8a7bd33" + url: "https://pub.dev" source: hosted - version: "0.9.8" + version: "1.3.2" source_span: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" source: hosted - version: "1.8.0-nullsafety.4" + version: "1.10.0" sqflite: dependency: transitive description: name: sqflite - url: "https://pub.dartlang.org" + sha256: b4d6710e1200e96845747e37338ea8a819a12b51689a3bcf31eff0003b37a0b9 + url: "https://pub.dev" source: hosted - version: "1.3.2+1" + version: "2.2.8+4" sqflite_common: dependency: transitive description: name: sqflite_common - url: "https://pub.dartlang.org" + sha256: "8f7603f3f8f126740bc55c4ca2d1027aab4b74a1267a3e31ce51fe40e3b65b8f" + url: "https://pub.dev" source: hosted - version: "1.0.2+1" + version: "2.4.5+1" sqlite3: dependency: transitive description: name: sqlite3 - url: "https://pub.dartlang.org" + sha256: "281b672749af2edf259fc801f0fcba092257425bcd32a0ce1c8237130bc934c7" + url: "https://pub.dev" source: hosted - version: "0.1.8" + version: "1.11.2" sqlite3_flutter_libs: dependency: "direct main" description: name: sqlite3_flutter_libs - url: "https://pub.dartlang.org" + sha256: "11a41f380fbcbda5bbba03ddcdbe0545e46094ab043783c46c70e8335831df03" + url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.5.17" sqlparser: dependency: transitive description: name: sqlparser - url: "https://pub.dartlang.org" + sha256: "2740266bc5b200a71b52296b05985fd9b79cab41f510620d2f42dffab5875123" + url: "https://pub.dev" source: hosted - version: "0.11.0" + version: "0.26.1" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" source: hosted - version: "1.10.0-nullsafety.6" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" source: hosted - version: "2.1.0-nullsafety.3" + version: "2.1.1" stream_transform: dependency: transitive description: name: stream_transform - url: "https://pub.dartlang.org" + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" source: hosted - version: "1.2.0" + version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.0-nullsafety.3" + version: "1.2.0" synchronized: dependency: transitive description: name: synchronized - url: "https://pub.dartlang.org" + sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60" + url: "https://pub.dev" source: hosted - version: "2.2.0+2" + version: "3.1.0" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted - version: "1.2.0-nullsafety.3" + version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + url: "https://pub.dev" source: hosted - version: "0.2.19-nullsafety.6" + version: "0.6.0" timing: dependency: transitive description: name: timing - url: "https://pub.dartlang.org" + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" source: hosted - version: "0.1.1+2" + version: "1.0.1" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" source: hosted - version: "1.3.0-nullsafety.5" + version: "1.3.2" url_launcher: dependency: "direct main" description: name: url_launcher - url: "https://pub.dartlang.org" + sha256: c512655380d241a337521703af62d2c122bf7b77a46ff7dd750092aa9433499c + url: "https://pub.dev" source: hosted - version: "5.7.10" + version: "6.2.4" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: "507dc655b1d9cb5ebc756032eb785f114e415f91557b73bf60b7e201dfedeb2f" + url: "https://pub.dev" + source: hosted + version: "6.2.2" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" + url: "https://pub.dev" + source: hosted + version: "6.2.4" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - url: "https://pub.dartlang.org" + sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811 + url: "https://pub.dev" source: hosted - version: "0.0.1+4" + version: "3.1.1" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - url: "https://pub.dartlang.org" + sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234 + url: "https://pub.dev" source: hosted - version: "0.0.1+9" + version: "3.1.0" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - url: "https://pub.dartlang.org" + sha256: "4aca1e060978e19b2998ee28503f40b5ba6226819c2b5e3e4d1821e8ccd92198" + url: "https://pub.dev" source: hosted - version: "1.0.9" + version: "2.3.0" url_launcher_web: dependency: transitive description: name: url_launcher_web - url: "https://pub.dartlang.org" + sha256: "7fd2f55fe86cea2897b963e864dc01a7eb0719ecc65fcef4c1cc3d686d718bb2" + url: "https://pub.dev" source: hosted - version: "0.1.5+1" + version: "2.2.0" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - url: "https://pub.dartlang.org" + sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7 + url: "https://pub.dev" source: hosted - version: "0.0.1+3" + version: "3.1.1" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.0-nullsafety.5" + version: "2.1.4" watcher: dependency: transitive description: name: watcher - url: "https://pub.dartlang.org" + sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0" + url: "https://pub.dev" source: hosted - version: "0.9.7+15" + version: "1.0.2" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" web_socket_channel: dependency: transitive description: name: web_socket_channel - url: "https://pub.dartlang.org" + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "2.4.0" win32: dependency: transitive description: name: win32 - url: "https://pub.dartlang.org" + sha256: "5a751eddf9db89b3e5f9d50c20ab8612296e4e8db69009788d6c8b060a84191c" + url: "https://pub.dev" source: hosted - version: "1.7.4" + version: "4.1.4" xdg_directories: dependency: transitive description: name: xdg_directories - url: "https://pub.dartlang.org" + sha256: f0c26453a2d47aa4c2570c6a033246a3fc62da2fe23c7ffdd0a7495086dc0247 + url: "https://pub.dev" source: hosted - version: "0.1.2" + version: "1.0.2" xml: dependency: transitive description: name: xml - url: "https://pub.dartlang.org" + sha256: ac0e3f4bf00ba2708c33fbabbbe766300e509f8c82dbd4ab6525039813f7e2fb + url: "https://pub.dev" source: hosted - version: "4.5.1" + version: "6.1.0" yaml: dependency: transitive description: name: yaml - url: "https://pub.dartlang.org" + sha256: "23812a9b125b48d4007117254bca50abb6c712352927eece9e155207b1db2370" + url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "3.1.1" sdks: - dart: ">=2.12.0-0.0 <3.0.0" - flutter: ">=1.22.2 <2.0.0" + dart: ">=3.1.0 <3.13.6" + flutter: ">=3.13.0" diff --git a/pubspec.yaml b/pubspec.yaml index 42fdd3e..8bb02fe 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,90 +1,46 @@ name: keydecoder description: A key decoding app that lets you decode your key from a picture. -# The following line prevents the package from being accidentally published to -# pub.dev using `pub publish`. This is preferred for private packages. -publish_to: "none" # Remove this line if you wish to publish to pub.dev +publish_to: "none" -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# In Android, build-name is used as versionName while build-number used as versionCode. -# Read more about Android versioning at https://developer.android.com/studio/publish/versioning -# 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: 1.0.0+3 +version: 1.1.0+4 environment: - sdk: ">=2.7.0 <3.0.0" + sdk: ">=3.0.0 <3.13.6" dependencies: + animate_icons: ^2.0.0 + community_material_icon: ^5.4.55 + drift_sqflite: ^2.0.0 + ffi: ^2.0.1 flutter: sdk: flutter - animate_icons: ^0.0.4 - community_material_icon: ^5.4.55 - flutter_keyboard_visibility: ^4.0.2 - flutter_slidable: ^0.5.7 - fluttericon: ^1.0.7 - image: ^2.1.19 - image_picker: ^0.6.7+11 - material_design_icons_flutter: ^4.0.5755 - matrix4_transform: ^1.1.5 - moor_flutter: ^3.1.0 + flutter_keyboard_visibility: ^5.4.0 + flutter_slidable: ^2.0.0 + fluttericon: ^2.0.0 + image: ^3.3.0 + image_picker: ^0.8.6 + material_design_icons_flutter: ^7.0.7296 + matrix4_transform: ^2.0.1 path: ^1.7.0 - path_provider: ^1.6.14 - provider: ^3.2.0 - rename: ^1.2.0 - shared_preferences: ^0.5.12+4 - sqlite3_flutter_libs: ^0.2.0 - url_launcher: ^5.7.10 + path_provider: ^2.0.11 + provider: ^6.0.5 + rename: ^3.0.1 + shared_preferences: ^2.0.15 + sqlite3_flutter_libs: ^0.5.12 + url_launcher: ^6.2.4 dev_dependencies: - flutter_test: - sdk: flutter - build_runner: ^1.10.2 # https://pub.dev/packages/build_runner - flutter_launcher_icons: ^0.8.0 - - moor_generator: ^3.3.1 # https://pub.dev/packages/moor_generator + build_runner: ^2.3.3 + drift_dev: ^2.4.1 + flutter_launcher_icons: ^0.11.0 flutter_icons: android: true ios: true image_path: "assets/icon.png" -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec -# The following section is specific to Flutter. flutter: - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. uses-material-design: true - # To add assets to your application, add an assets section, like this: assets: - assets/ - # 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