From fd5b7f7e5b473a356030a936cfe8284c5609073b Mon Sep 17 00:00:00 2001 From: Ming Ming Date: Mon, 28 Aug 2023 00:54:18 +0800 Subject: [PATCH] Refactor: extract geocoder --- .../entity/sqlite/files_query_builder.dart | 6 +-- app/lib/geocoder_util.dart | 15 ++++++ app/lib/metadata_task_manager.dart | 2 +- app/lib/mobile/db_util.dart | 25 ---------- app/lib/service.dart | 2 +- app/lib/use_case/list_location_file.dart | 5 +- app/lib/use_case/list_location_group.dart | 4 +- app/lib/use_case/update_missing_metadata.dart | 3 +- app/lib/web/db_util.dart | 28 ----------- app/lib/widget/viewer_detail_pane.dart | 8 ++-- app/pubspec.lock | 9 +++- app/pubspec.yaml | 6 +-- np_geocoder/.gitignore | 30 ++++++++++++ np_geocoder/.metadata | 10 ++++ np_geocoder/analysis_options.yaml | 1 + np_geocoder/lib/np_geocoder.dart | 4 ++ .../lib/src}/location_util.dart | 0 np_geocoder/lib/src/native/db_util.dart | 29 +++++++++++ .../lib/src}/reverse_geocoder.dart | 20 ++------ .../lib/src}/reverse_geocoder.g.dart | 4 +- np_geocoder/lib/src/web/db_util.dart | 30 ++++++++++++ np_geocoder/pubspec.yaml | 48 +++++++++++++++++++ 22 files changed, 197 insertions(+), 92 deletions(-) create mode 100644 app/lib/geocoder_util.dart create mode 100644 np_geocoder/.gitignore create mode 100644 np_geocoder/.metadata create mode 100644 np_geocoder/analysis_options.yaml create mode 100644 np_geocoder/lib/np_geocoder.dart rename {app/lib => np_geocoder/lib/src}/location_util.dart (100%) create mode 100644 np_geocoder/lib/src/native/db_util.dart rename {app/lib => np_geocoder/lib/src}/reverse_geocoder.dart (89%) rename {app/lib => np_geocoder/lib/src}/reverse_geocoder.g.dart (72%) create mode 100644 np_geocoder/lib/src/web/db_util.dart create mode 100644 np_geocoder/pubspec.yaml diff --git a/app/lib/entity/sqlite/files_query_builder.dart b/app/lib/entity/sqlite/files_query_builder.dart index f157a7f8..ee2cfbe8 100644 --- a/app/lib/entity/sqlite/files_query_builder.dart +++ b/app/lib/entity/sqlite/files_query_builder.dart @@ -1,7 +1,7 @@ import 'package:drift/drift.dart'; import 'package:nc_photos/account.dart' as app; import 'package:nc_photos/entity/sqlite/database.dart'; -import 'package:nc_photos/location_util.dart' as location_util; +import 'package:np_geocoder/np_geocoder.dart'; import 'package:np_string/np_string.dart'; enum FilesQueryMode { @@ -181,11 +181,11 @@ class FilesQueryBuilder { var clause = db.imageLocations.name.like(_byLocation!) | db.imageLocations.admin1.like(_byLocation!) | db.imageLocations.admin2.like(_byLocation!); - final countryCode = location_util.nameToAlpha2Code(_byLocation!.toCi()); + final countryCode = nameToAlpha2Code(_byLocation!.toCi()); if (countryCode != null) { clause = clause | db.imageLocations.countryCode.equals(countryCode); } else if (_byLocation!.length == 2 && - location_util.alpha2CodeToName(_byLocation!.toUpperCase()) != null) { + alpha2CodeToName(_byLocation!.toUpperCase()) != null) { clause = clause | db.imageLocations.countryCode.equals(_byLocation!.toUpperCase()); } diff --git a/app/lib/geocoder_util.dart b/app/lib/geocoder_util.dart new file mode 100644 index 00000000..02f0db47 --- /dev/null +++ b/app/lib/geocoder_util.dart @@ -0,0 +1,15 @@ +import 'package:nc_photos/entity/file.dart'; +import 'package:np_geocoder/np_geocoder.dart'; + +extension ReverseGeocoderExtension on ReverseGeocoderLocation { + ImageLocation toImageLocation() { + return ImageLocation( + name: name, + latitude: latitude, + longitude: longitude, + countryCode: countryCode, + admin1: admin1, + admin2: admin2, + ); + } +} diff --git a/app/lib/metadata_task_manager.dart b/app/lib/metadata_task_manager.dart index a039531d..108b091b 100644 --- a/app/lib/metadata_task_manager.dart +++ b/app/lib/metadata_task_manager.dart @@ -9,9 +9,9 @@ import 'package:nc_photos/entity/file.dart'; import 'package:nc_photos/entity/file_util.dart' as file_util; import 'package:nc_photos/entity/pref.dart'; import 'package:nc_photos/event/event.dart'; -import 'package:nc_photos/reverse_geocoder.dart'; import 'package:nc_photos/use_case/update_missing_metadata.dart'; import 'package:np_codegen/np_codegen.dart'; +import 'package:np_geocoder/np_geocoder.dart'; import 'package:to_string/to_string.dart'; part 'metadata_task_manager.g.dart'; diff --git a/app/lib/mobile/db_util.dart b/app/lib/mobile/db_util.dart index 5fc962b2..fcba0e3c 100644 --- a/app/lib/mobile/db_util.dart +++ b/app/lib/mobile/db_util.dart @@ -2,13 +2,10 @@ import 'dart:io' as dart; import 'package:drift/drift.dart'; import 'package:drift/native.dart'; -import 'package:flutter/services.dart' show rootBundle; import 'package:nc_photos/entity/sqlite/database.dart' as sql; import 'package:nc_photos_plugin/nc_photos_plugin.dart'; import 'package:path/path.dart' as path_lib; import 'package:path_provider/path_provider.dart'; -import 'package:sqlite3/common.dart'; -import 'package:sqlite3/sqlite3.dart'; import 'package:sqlite3_flutter_libs/sqlite3_flutter_libs.dart' as sql; Future> getSqliteConnectionArgs() async { @@ -40,28 +37,6 @@ Future applyWorkaroundToOpenSqlite3OnOldAndroidVersions() { return sql.applyWorkaroundToOpenSqlite3OnOldAndroidVersions(); } -Future openRawSqliteDbFromAsset( - String assetRelativePath, - String outputFilename, { - bool isReadOnly = false, -}) async { - final dbFolder = await getApplicationDocumentsDirectory(); - final file = dart.File(path_lib.join(dbFolder.path, outputFilename)); - if (!await file.exists()) { - // copy file from assets - final blob = await rootBundle.load("assets/$assetRelativePath"); - final buffer = blob.buffer; - await file.writeAsBytes( - buffer.asUint8List(blob.offsetInBytes, blob.lengthInBytes), - flush: true, - ); - } - return sqlite3.open( - file.path, - mode: isReadOnly ? OpenMode.readOnly : OpenMode.readWriteCreate, - ); -} - Future exportSqliteDb(sql.SqliteDb db) async { final dir = await getApplicationDocumentsDirectory(); final file = dart.File(path_lib.join(dir.path, "export.sqlite")); diff --git a/app/lib/service.dart b/app/lib/service.dart index ea3fe6d5..3d1b2a56 100644 --- a/app/lib/service.dart +++ b/app/lib/service.dart @@ -19,11 +19,11 @@ import 'package:nc_photos/entity/pref.dart'; import 'package:nc_photos/event/event.dart'; import 'package:nc_photos/event/native_event.dart'; import 'package:nc_photos/language_util.dart' as language_util; -import 'package:nc_photos/reverse_geocoder.dart'; import 'package:nc_photos/use_case/update_missing_metadata.dart'; import 'package:nc_photos_plugin/nc_photos_plugin.dart'; import 'package:np_async/np_async.dart'; import 'package:np_codegen/np_codegen.dart'; +import 'package:np_geocoder/np_geocoder.dart'; part 'service.g.dart'; diff --git a/app/lib/use_case/list_location_file.dart b/app/lib/use_case/list_location_file.dart index 7005bb18..8d725dfd 100644 --- a/app/lib/use_case/list_location_file.dart +++ b/app/lib/use_case/list_location_file.dart @@ -6,8 +6,8 @@ import 'package:nc_photos/entity/file_descriptor.dart'; import 'package:nc_photos/entity/sqlite/database.dart' as sql; import 'package:nc_photos/entity/sqlite/files_query_builder.dart' as sql; import 'package:nc_photos/entity/sqlite/type_converter.dart'; -import 'package:nc_photos/location_util.dart' as location_util; import 'package:nc_photos/object_extension.dart'; +import 'package:np_geocoder/np_geocoder.dart'; class ListLocationFile { ListLocationFile(this._c) : assert(require(_c)); @@ -29,8 +29,7 @@ class ListLocationFile { }); return q.build(); }); - if (place == null || - location_util.alpha2CodeToName(countryCode) == place) { + if (place == null || alpha2CodeToName(countryCode) == place) { // some places in the DB have the same name as the country, in such // cases, we return all photos from the country query.where(db.imageLocations.countryCode.equals(countryCode)); diff --git a/app/lib/use_case/list_location_group.dart b/app/lib/use_case/list_location_group.dart index b9fc6069..2b4cb0dc 100644 --- a/app/lib/use_case/list_location_group.dart +++ b/app/lib/use_case/list_location_group.dart @@ -4,8 +4,8 @@ import 'package:logging/logging.dart'; import 'package:nc_photos/account.dart'; import 'package:nc_photos/di_container.dart'; import 'package:nc_photos/entity/sqlite/database.dart' as sql; -import 'package:nc_photos/location_util.dart' as location_util; import 'package:np_codegen/np_codegen.dart'; +import 'package:np_geocoder/np_geocoder.dart'; import 'package:to_string/to_string.dart'; part 'list_location_group.g.dart'; @@ -141,7 +141,7 @@ class ListLocationGroup { await countryCodeQ.map((r) { final cc = r.read(db.imageLocations.countryCode)!; return LocationGroup( - location_util.alpha2CodeToName(cc) ?? cc, + alpha2CodeToName(cc) ?? cc, cc, r.read(count)!, r.read(db.files.fileId)!, diff --git a/app/lib/use_case/update_missing_metadata.dart b/app/lib/use_case/update_missing_metadata.dart index b2c07140..a1d1206c 100644 --- a/app/lib/use_case/update_missing_metadata.dart +++ b/app/lib/use_case/update_missing_metadata.dart @@ -9,13 +9,14 @@ import 'package:nc_photos/entity/file.dart'; import 'package:nc_photos/event/event.dart'; import 'package:nc_photos/exception.dart'; import 'package:nc_photos/exception_event.dart'; -import 'package:nc_photos/reverse_geocoder.dart'; +import 'package:nc_photos/geocoder_util.dart'; import 'package:nc_photos/use_case/get_file_binary.dart'; import 'package:nc_photos/use_case/load_metadata.dart'; import 'package:nc_photos/use_case/scan_missing_metadata.dart'; import 'package:nc_photos/use_case/update_property.dart'; import 'package:np_codegen/np_codegen.dart'; import 'package:np_common/or_null.dart'; +import 'package:np_geocoder/np_geocoder.dart'; part 'update_missing_metadata.g.dart'; diff --git a/app/lib/web/db_util.dart b/app/lib/web/db_util.dart index 7c242f82..27c7ae6c 100644 --- a/app/lib/web/db_util.dart +++ b/app/lib/web/db_util.dart @@ -1,6 +1,5 @@ import 'package:drift/drift.dart'; import 'package:drift/wasm.dart'; -import 'package:flutter/services.dart' show rootBundle; import 'package:http/http.dart' as http; import 'package:nc_photos/entity/sqlite/database.dart' as sql; import 'package:sqlite3/wasm.dart'; @@ -36,33 +35,6 @@ Future applyWorkaroundToOpenSqlite3OnOldAndroidVersions() async { // not supported on web } -Future openRawSqliteDbFromAsset( - String assetRelativePath, - String outputFilename, { - bool isReadOnly = false, -}) async { - final response = await http.get(Uri.parse("sqlite3.wasm")); - final fs = await IndexedDbFileSystem.open(dbName: "nc-photos"); - final sqlite3 = await WasmSqlite3.load( - response.bodyBytes, - SqliteEnvironment(fileSystem: fs), - ); - - if (!fs.exists("/app-file/$outputFilename")) { - // copy file from assets - final blob = await rootBundle.load("assets/$assetRelativePath"); - final buffer = blob.buffer; - fs.createFile("/app-file/$outputFilename"); - fs.write( - "/app-file/$outputFilename", - buffer.asUint8List(blob.offsetInBytes, blob.lengthInBytes), - 0, - ); - await fs.flush(); - } - return sqlite3.open("/app-file/$outputFilename"); -} - Future exportSqliteDb(sql.SqliteDb db) async { throw UnimplementedError(); } diff --git a/app/lib/widget/viewer_detail_pane.dart b/app/lib/widget/viewer_detail_pane.dart index ffcd9c0c..ce2c9bed 100644 --- a/app/lib/widget/viewer_detail_pane.dart +++ b/app/lib/widget/viewer_detail_pane.dart @@ -19,7 +19,6 @@ import 'package:nc_photos/entity/file.dart'; import 'package:nc_photos/entity/file_descriptor.dart'; import 'package:nc_photos/entity/file_util.dart' as file_util; import 'package:nc_photos/k.dart' as k; -import 'package:nc_photos/location_util.dart' as location_util; import 'package:nc_photos/object_extension.dart'; import 'package:nc_photos/platform/features.dart' as features; import 'package:nc_photos/set_as_handler.dart'; @@ -35,6 +34,7 @@ import 'package:nc_photos/widget/list_tile_center_leading.dart'; import 'package:nc_photos/widget/photo_date_time_edit_dialog.dart'; import 'package:np_codegen/np_codegen.dart'; import 'package:np_common/or_null.dart'; +import 'package:np_geocoder/np_geocoder.dart'; import 'package:np_platform_util/np_platform_util.dart'; import 'package:np_string/np_string.dart'; import 'package:np_ui/np_ui.dart'; @@ -564,11 +564,11 @@ extension on ImageLocation { if (countryCode == null) { return null; } else if (admin1 == null) { - return location_util.alpha2CodeToName(countryCode!); + return alpha2CodeToName(countryCode!); } else if (admin2 == null) { - return "$admin1, ${location_util.alpha2CodeToName(countryCode!)}"; + return "$admin1, ${alpha2CodeToName(countryCode!)}"; } else { - return "$admin2, $admin1, ${location_util.alpha2CodeToName(countryCode!)}"; + return "$admin2, $admin1, ${alpha2CodeToName(countryCode!)}"; } } } diff --git a/app/pubspec.lock b/app/pubspec.lock index ff30859f..22ae786f 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -782,7 +782,7 @@ packages: source: hosted version: "4.8.1" kdtree: - dependency: "direct main" + dependency: transitive description: path: "." ref: "0.2.0-nc-photos-1" @@ -983,6 +983,13 @@ packages: relative: true source: path version: "0.0.1" + np_geocoder: + dependency: "direct main" + description: + path: "../np_geocoder" + relative: true + source: path + version: "0.0.1" np_lints: dependency: "direct dev" description: diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 757b6848..87133471 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -84,10 +84,6 @@ dependencies: ref: 1.0.0-nc-photos-2 path: library intl: ^0.17.0 - kdtree: - git: - url: https://gitlab.com/nc-photos/kd-tree-dart.git - ref: 0.2.0-nc-photos-1 kiwi: ^4.1.0 latlong2: any logging: ^1.1.1 @@ -107,6 +103,8 @@ dependencies: path: ../np_common np_collection: path: ../np_collection + np_geocoder: + path: ../np_geocoder np_log: path: ../np_log np_math: diff --git a/np_geocoder/.gitignore b/np_geocoder/.gitignore new file mode 100644 index 00000000..96486fd9 --- /dev/null +++ b/np_geocoder/.gitignore @@ -0,0 +1,30 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.packages +build/ diff --git a/np_geocoder/.metadata b/np_geocoder/.metadata new file mode 100644 index 00000000..788b91db --- /dev/null +++ b/np_geocoder/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 4d9e56e694b656610ab87fcf2efbcd226e0ed8cf + channel: stable + +project_type: package diff --git a/np_geocoder/analysis_options.yaml b/np_geocoder/analysis_options.yaml new file mode 100644 index 00000000..f92d2567 --- /dev/null +++ b/np_geocoder/analysis_options.yaml @@ -0,0 +1 @@ +include: package:np_lints/np.yaml diff --git a/np_geocoder/lib/np_geocoder.dart b/np_geocoder/lib/np_geocoder.dart new file mode 100644 index 00000000..50156686 --- /dev/null +++ b/np_geocoder/lib/np_geocoder.dart @@ -0,0 +1,4 @@ +library np_geocoder; + +export 'src/location_util.dart'; +export 'src/reverse_geocoder.dart'; diff --git a/app/lib/location_util.dart b/np_geocoder/lib/src/location_util.dart similarity index 100% rename from app/lib/location_util.dart rename to np_geocoder/lib/src/location_util.dart diff --git a/np_geocoder/lib/src/native/db_util.dart b/np_geocoder/lib/src/native/db_util.dart new file mode 100644 index 00000000..40ef2871 --- /dev/null +++ b/np_geocoder/lib/src/native/db_util.dart @@ -0,0 +1,29 @@ +import 'dart:io' as dart; + +import 'package:flutter/services.dart' show rootBundle; +import 'package:path/path.dart' as path_lib; +import 'package:path_provider/path_provider.dart'; +import 'package:sqlite3/common.dart'; +import 'package:sqlite3/sqlite3.dart'; + +Future openRawSqliteDbFromAsset( + String assetRelativePath, + String outputFilename, { + bool isReadOnly = false, +}) async { + final dbFolder = await getApplicationDocumentsDirectory(); + final file = dart.File(path_lib.join(dbFolder.path, outputFilename)); + if (!await file.exists()) { + // copy file from assets + final blob = await rootBundle.load("assets/$assetRelativePath"); + final buffer = blob.buffer; + await file.writeAsBytes( + buffer.asUint8List(blob.offsetInBytes, blob.lengthInBytes), + flush: true, + ); + } + return sqlite3.open( + file.path, + mode: isReadOnly ? OpenMode.readOnly : OpenMode.readWriteCreate, + ); +} diff --git a/app/lib/reverse_geocoder.dart b/np_geocoder/lib/src/reverse_geocoder.dart similarity index 89% rename from app/lib/reverse_geocoder.dart rename to np_geocoder/lib/src/reverse_geocoder.dart index 0295e7e4..550d04c9 100644 --- a/app/lib/reverse_geocoder.dart +++ b/np_geocoder/lib/src/reverse_geocoder.dart @@ -3,10 +3,9 @@ import 'dart:math' as math; import 'package:collection/collection.dart'; import 'package:kdtree/kdtree.dart'; import 'package:logging/logging.dart'; -import 'package:nc_photos/entity/file.dart'; -import 'package:nc_photos/mobile/platform.dart' - if (dart.library.html) 'package:nc_photos/web/platform.dart' as platform; import 'package:np_codegen/np_codegen.dart'; +import 'package:np_geocoder/src/native/db_util.dart' + if (dart.library.html) 'package:np_geocoder/src/web/db_util.dart'; import 'package:np_math/np_math.dart'; import 'package:sqlite3/common.dart'; import 'package:to_string/to_string.dart'; @@ -109,19 +108,6 @@ class ReverseGeocoder { late final KDTree _searchTree; } -extension ReverseGeocoderExtension on ReverseGeocoderLocation { - ImageLocation toImageLocation() { - return ImageLocation( - name: name, - latitude: latitude, - longitude: longitude, - countryCode: countryCode, - admin1: admin1, - admin2: admin2, - ); - } -} - class _DatabaseRow { const _DatabaseRow(this.name, this.latitude, this.longitude, this.countryCode, this.admin1, this.admin2); @@ -135,7 +121,7 @@ class _DatabaseRow { } Future _openDatabase() async { - return platform.openRawSqliteDbFromAsset("cities.sqlite", "cities.sqlite"); + return openRawSqliteDbFromAsset("cities.sqlite", "cities.sqlite"); } KDTree _buildSearchTree(CommonDatabase db) { diff --git a/app/lib/reverse_geocoder.g.dart b/np_geocoder/lib/src/reverse_geocoder.g.dart similarity index 72% rename from app/lib/reverse_geocoder.g.dart rename to np_geocoder/lib/src/reverse_geocoder.g.dart index a193d8d9..74b7e4b7 100644 --- a/app/lib/reverse_geocoder.g.dart +++ b/np_geocoder/lib/src/reverse_geocoder.g.dart @@ -10,7 +10,7 @@ extension _$ReverseGeocoderNpLog on ReverseGeocoder { // ignore: unused_element Logger get _log => log; - static final log = Logger("reverse_geocoder.ReverseGeocoder"); + static final log = Logger("src.reverse_geocoder.ReverseGeocoder"); } // ************************************************************************** @@ -20,6 +20,6 @@ extension _$ReverseGeocoderNpLog on ReverseGeocoder { extension _$ReverseGeocoderLocationToString on ReverseGeocoderLocation { String _$toString() { // ignore: unnecessary_string_interpolations - return "ReverseGeocoderLocation {name: $name, latitude: ${latitude.toStringAsFixed(3)}, longitude: ${longitude.toStringAsFixed(3)}, countryCode: $countryCode, admin1: $admin1, admin2: $admin2}"; + return "ReverseGeocoderLocation {name: $name, latitude: $latitude, longitude: $longitude, countryCode: $countryCode, admin1: $admin1, admin2: $admin2}"; } } diff --git a/np_geocoder/lib/src/web/db_util.dart b/np_geocoder/lib/src/web/db_util.dart new file mode 100644 index 00000000..f6bfcdee --- /dev/null +++ b/np_geocoder/lib/src/web/db_util.dart @@ -0,0 +1,30 @@ +import 'package:flutter/services.dart' show rootBundle; +import 'package:http/http.dart' as http; +import 'package:sqlite3/wasm.dart'; + +Future openRawSqliteDbFromAsset( + String assetRelativePath, + String outputFilename, { + bool isReadOnly = false, +}) async { + final response = await http.get(Uri.parse("sqlite3.wasm")); + final fs = await IndexedDbFileSystem.open(dbName: "nc-photos"); + final sqlite3 = await WasmSqlite3.load( + response.bodyBytes, + SqliteEnvironment(fileSystem: fs), + ); + + if (!fs.exists("/app-file/$outputFilename")) { + // copy file from assets + final blob = await rootBundle.load("assets/$assetRelativePath"); + final buffer = blob.buffer; + fs.createFile("/app-file/$outputFilename"); + fs.write( + "/app-file/$outputFilename", + buffer.asUint8List(blob.offsetInBytes, blob.lengthInBytes), + 0, + ); + await fs.flush(); + } + return sqlite3.open("/app-file/$outputFilename"); +} diff --git a/np_geocoder/pubspec.yaml b/np_geocoder/pubspec.yaml new file mode 100644 index 00000000..5ad6a5d0 --- /dev/null +++ b/np_geocoder/pubspec.yaml @@ -0,0 +1,48 @@ +name: np_geocoder +description: A new Flutter package project. +version: 0.0.1 +homepage: +publish_to: none + +environment: + sdk: '>=2.19.6 <3.0.0' + flutter: ">=3.3.0" + +dependencies: + flutter: + sdk: flutter + collection: ^1.15.0 + http: ^0.13.5 + kdtree: + git: + url: https://gitlab.com/nc-photos/kd-tree-dart.git + ref: 0.2.0-nc-photos-1 + logging: ^1.1.1 + np_codegen: + path: ../codegen + np_collection: + path: ../np_collection + np_math: + path: ../np_math + np_string: + path: ../np_string + path: ^1.8.0 + path_provider: ^2.0.15 + sqlite3: ^1.11.1 + to_string: + git: + url: https://gitlab.com/nkming2/dart-to-string + ref: to_string-1.0.0 + path: to_string + +dev_dependencies: + build_runner: ^2.2.1 + np_codegen_build: + path: ../codegen_build + np_lints: + path: ../np_lints + to_string_build: + git: + url: https://gitlab.com/nkming2/dart-to-string + ref: to_string_build-1.0.0 + path: to_string_build