diff --git a/app/lib/entity/pref/provider/shared_preferences.dart b/app/lib/entity/pref/provider/shared_preferences.dart index ceb665bd..1a439715 100644 --- a/app/lib/entity/pref/provider/shared_preferences.dart +++ b/app/lib/entity/pref/provider/shared_preferences.dart @@ -1,8 +1,7 @@ import 'package:nc_photos/entity/pref.dart'; -import 'package:nc_photos/mobile/platform.dart' - if (dart.library.html) 'package:nc_photos/web/platform.dart' as platform; import 'package:nc_photos/use_case/compat/v34.dart'; import 'package:np_common/type.dart'; +import 'package:np_universal_storage/np_universal_storage.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences_platform_interface/shared_preferences_platform_interface.dart'; @@ -14,7 +13,7 @@ class PrefSharedPreferencesProvider extends PrefProvider { // await CompatV32.migratePref(); // } if (await CompatV34.isPrefNeedMigration()) { - await CompatV34.migratePref(platform.UniversalStorage()); + await CompatV34.migratePref(UniversalStorage()); } return SharedPreferences.getInstance().then((pref) { _pref = pref; diff --git a/app/lib/entity/pref/provider/universal_storage.dart b/app/lib/entity/pref/provider/universal_storage.dart index eb4785e7..8e57966b 100644 --- a/app/lib/entity/pref/provider/universal_storage.dart +++ b/app/lib/entity/pref/provider/universal_storage.dart @@ -1,16 +1,15 @@ import 'dart:convert'; import 'package:nc_photos/entity/pref.dart'; -import 'package:nc_photos/mobile/platform.dart' - if (dart.library.html) 'package:nc_photos/web/platform.dart' as platform; import 'package:np_common/type.dart'; +import 'package:np_universal_storage/np_universal_storage.dart'; /// [Pref] backed by [UniversalStorage] class PrefUniversalStorageProvider extends PrefProvider { PrefUniversalStorageProvider(this.name); Future init() async { - final prefStr = await platform.UniversalStorage().getString(name) ?? "{}"; + final prefStr = await UniversalStorage().getString(name) ?? "{}"; _data ..clear() ..addAll(jsonDecode(prefStr)); @@ -41,14 +40,14 @@ class PrefUniversalStorageProvider extends PrefProvider { @override Future remove(PrefKeyInterface key) async { final newData = Map.of(_data)..remove(key.toStringKey()); - await platform.UniversalStorage().putString(name, jsonEncode(newData)); + await UniversalStorage().putString(name, jsonEncode(newData)); _data.remove(key.toStringKey()); return true; } @override Future clear() async { - await platform.UniversalStorage().remove(name); + await UniversalStorage().remove(name); _data.clear(); return true; } @@ -61,7 +60,7 @@ class PrefUniversalStorageProvider extends PrefProvider { Future _set(PrefKeyInterface key, T value) async { final newData = Map.of(_data) ..addEntries([MapEntry(key.toStringKey(), value)]); - await platform.UniversalStorage().putString(name, jsonEncode(newData)); + await UniversalStorage().putString(name, jsonEncode(newData)); _data[key.toStringKey()] = value; return true; } diff --git a/app/lib/mobile/platform.dart b/app/lib/mobile/platform.dart index 07b05654..a7be646c 100644 --- a/app/lib/mobile/platform.dart +++ b/app/lib/mobile/platform.dart @@ -3,4 +3,3 @@ export 'download.dart'; export 'file_saver.dart'; export 'google_gps_map.dart'; export 'notification.dart'; -export 'universal_storage.dart'; diff --git a/app/lib/touch_manager.dart b/app/lib/touch_manager.dart index f687e0aa..2f2830ef 100644 --- a/app/lib/touch_manager.dart +++ b/app/lib/touch_manager.dart @@ -6,14 +6,13 @@ import 'package:nc_photos/di_container.dart'; import 'package:nc_photos/entity/file.dart'; import 'package:nc_photos/entity/file_descriptor.dart'; import 'package:nc_photos/exception.dart'; -import 'package:nc_photos/mobile/platform.dart' - if (dart.library.html) 'package:nc_photos/web/platform.dart' as platform; import 'package:nc_photos/remote_storage_util.dart' as remote_storage_util; import 'package:nc_photos/throttler.dart'; import 'package:nc_photos/use_case/ls_single_file.dart'; import 'package:nc_photos/use_case/put_file_binary.dart'; import 'package:np_codegen/np_codegen.dart'; import 'package:np_common/or_null.dart'; +import 'package:np_universal_storage/np_universal_storage.dart'; import 'package:path/path.dart' as path_lib; import 'package:uuid/uuid.dart'; @@ -116,10 +115,10 @@ class TouchManager { Future setLocalEtag(Account account, File dir, String? etag) { final name = _getLocalStorageName(account, dir); if (etag == null) { - return platform.UniversalStorage().remove(name); + return UniversalStorage().remove(name); } else { _log.info("[setLocalEtag] Set local etag for file '${dir.path}': $etag"); - return platform.UniversalStorage().putString(name, etag); + return UniversalStorage().putString(name, etag); } } @@ -175,7 +174,7 @@ class TouchManager { Future _getLocalEtag(Account account, File file) async { final name = _getLocalStorageName(account, file); - return platform.UniversalStorage().getString(name); + return UniversalStorage().getString(name); } String _getLocalStorageName(Account account, File file) { diff --git a/app/lib/use_case/compat/v34.dart b/app/lib/use_case/compat/v34.dart index 0cbb854c..454fd320 100644 --- a/app/lib/use_case/compat/v34.dart +++ b/app/lib/use_case/compat/v34.dart @@ -2,9 +2,9 @@ import 'dart:convert'; import 'package:logging/logging.dart'; import 'package:nc_photos/account.dart'; -import 'package:nc_photos/platform/universal_storage.dart'; import 'package:np_codegen/np_codegen.dart'; import 'package:np_common/type.dart'; +import 'package:np_universal_storage/np_universal_storage.dart'; import 'package:shared_preferences/shared_preferences.dart'; part 'v34.g.dart'; @@ -39,7 +39,8 @@ class CompatV34 { final id = Account.newId(); account2["account"]["id"] = id; newJsons.add(account2["account"]); - await storage.putString("accounts/$id/pref", jsonEncode(account2["settings"])); + await storage.putString( + "accounts/$id/pref", jsonEncode(account2["settings"])); } if (await pref.setStringList( "accounts3", newJsons.map((e) => jsonEncode(e)).toList())) { diff --git a/app/lib/web/platform.dart b/app/lib/web/platform.dart index 07b05654..a7be646c 100644 --- a/app/lib/web/platform.dart +++ b/app/lib/web/platform.dart @@ -3,4 +3,3 @@ export 'download.dart'; export 'file_saver.dart'; export 'google_gps_map.dart'; export 'notification.dart'; -export 'universal_storage.dart'; diff --git a/app/pubspec.lock b/app/pubspec.lock index 22ae786f..f5e5563b 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -1039,6 +1039,13 @@ packages: relative: true source: path version: "0.0.1" + np_universal_storage: + dependency: "direct main" + description: + path: "../np_universal_storage" + relative: true + source: path + version: "0.0.1" octo_image: dependency: "direct main" description: diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 87133471..379405a4 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -117,6 +117,8 @@ dependencies: path: ../np_string np_ui: path: ../np_ui + np_universal_storage: + path: ../np_universal_storage octo_image: any page_view_indicators: ^2.0.0 path: ^1.8.0 diff --git a/app/test/use_case/compat/v34_test.dart b/app/test/use_case/compat/v34_test.dart index c655f8ff..6b77307e 100644 --- a/app/test/use_case/compat/v34_test.dart +++ b/app/test/use_case/compat/v34_test.dart @@ -1,7 +1,7 @@ import 'dart:convert'; -import 'package:nc_photos/platform/universal_storage.dart'; import 'package:nc_photos/use_case/compat/v34.dart'; +import 'package:np_universal_storage/np_universal_storage.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:test/test.dart'; diff --git a/np_universal_storage/.gitignore b/np_universal_storage/.gitignore new file mode 100644 index 00000000..96486fd9 --- /dev/null +++ b/np_universal_storage/.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_universal_storage/.metadata b/np_universal_storage/.metadata new file mode 100644 index 00000000..788b91db --- /dev/null +++ b/np_universal_storage/.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_universal_storage/analysis_options.yaml b/np_universal_storage/analysis_options.yaml new file mode 100644 index 00000000..f92d2567 --- /dev/null +++ b/np_universal_storage/analysis_options.yaml @@ -0,0 +1 @@ +include: package:np_lints/np.yaml diff --git a/np_universal_storage/lib/np_universal_storage.dart b/np_universal_storage/lib/np_universal_storage.dart new file mode 100644 index 00000000..d8874f98 --- /dev/null +++ b/np_universal_storage/lib/np_universal_storage.dart @@ -0,0 +1,4 @@ +library np_universal_storage; + +export 'src/memory_storage.dart'; +export 'src/universal_storage.dart'; diff --git a/np_universal_storage/lib/src/memory_storage.dart b/np_universal_storage/lib/src/memory_storage.dart new file mode 100644 index 00000000..46820448 --- /dev/null +++ b/np_universal_storage/lib/src/memory_storage.dart @@ -0,0 +1,29 @@ +import 'package:flutter/foundation.dart'; +import 'package:np_universal_storage/src/universal_storage.dart'; + +/// UniversalStorage backed by memory, useful in unit tests +@visibleForTesting +class UniversalMemoryStorage implements UniversalStorage { + @override + Future putBinary(String name, Uint8List content) async { + data[name] = content; + } + + @override + Future getBinary(String name) async => data[name]; + + @override + Future putString(String name, String content) async { + data[name] = content; + } + + @override + Future getString(String name) async => data[name]; + + @override + Future remove(String name) async { + data.remove(name); + } + + final data = {}; +} diff --git a/app/lib/mobile/universal_storage.dart b/np_universal_storage/lib/src/native/universal_storage.dart similarity index 81% rename from app/lib/mobile/universal_storage.dart rename to np_universal_storage/lib/src/native/universal_storage.dart index d52fd075..469ed2f3 100644 --- a/app/lib/mobile/universal_storage.dart +++ b/np_universal_storage/lib/src/native/universal_storage.dart @@ -1,21 +1,21 @@ import 'dart:io'; import 'dart:typed_data'; -import 'package:nc_photos/platform/universal_storage.dart' as itf; import 'package:np_string/np_string.dart'; +import 'package:np_universal_storage/src/universal_storage.dart' as itf; import 'package:path/path.dart' as path_lib; import 'package:path_provider/path_provider.dart'; -class UniversalStorage extends itf.UniversalStorage { +class UniversalStorage implements itf.UniversalStorage { @override - putBinary(String name, Uint8List content) async { + Future putBinary(String name, Uint8List content) async { final storageDir = await _openStorageDirForFile(name); final file = File("${storageDir.path}/$name"); await file.writeAsBytes(content, flush: true); } @override - getBinary(String name) async { + Future getBinary(String name) async { final storageDir = await _openStorageDirForFile(name); final file = File("${storageDir.path}/$name"); if (await file.exists()) { @@ -26,14 +26,14 @@ class UniversalStorage extends itf.UniversalStorage { } @override - putString(String name, String content) async { + Future putString(String name, String content) async { final storageDir = await _openStorageDirForFile(name); final file = File("${storageDir.path}/$name"); await file.writeAsString(content, flush: true); } @override - getString(String name) async { + Future getString(String name) async { final storageDir = await _openStorageDirForFile(name); final file = File("${storageDir.path}/$name"); if (await file.exists()) { @@ -44,7 +44,7 @@ class UniversalStorage extends itf.UniversalStorage { } @override - remove(String name) async { + Future remove(String name) async { final storageDir = await _openStorageDirForFile(name); final file = File("${storageDir.path}/$name"); if (await file.exists()) { diff --git a/app/lib/platform/universal_storage.dart b/np_universal_storage/lib/src/universal_storage.dart similarity index 51% rename from app/lib/platform/universal_storage.dart rename to np_universal_storage/lib/src/universal_storage.dart index 4bcd7bdc..56153825 100644 --- a/app/lib/platform/universal_storage.dart +++ b/np_universal_storage/lib/src/universal_storage.dart @@ -1,10 +1,16 @@ -import 'package:flutter/foundation.dart'; +import 'dart:typed_data'; + +import 'package:np_universal_storage/src/native/universal_storage.dart' + if (dart.library.html) 'package:np_universal_storage/src/web/universal_storage.dart' + as impl; /// Store simple contents across different platforms /// /// On mobile, the contents will be persisted as a file. On web, the contents /// will be stored in local storage abstract class UniversalStorage { + factory UniversalStorage() => impl.UniversalStorage(); + Future putBinary(String name, Uint8List content); /// Return the content associated with [name], or null if no such association @@ -19,30 +25,3 @@ abstract class UniversalStorage { Future remove(String name); } - -/// UniversalStorage backed by memory, useful in unit tests -@visibleForTesting -class UniversalMemoryStorage implements UniversalStorage { - @override - putBinary(String name, Uint8List content) async { - data[name] = content; - } - - @override - getBinary(String name) async => data[name]; - - @override - putString(String name, String content) async { - data[name] = content; - } - - @override - getString(String name) async => data[name]; - - @override - remove(String name) async { - data.remove(name); - } - - final data = {}; -} diff --git a/app/lib/web/universal_storage.dart b/np_universal_storage/lib/src/web/universal_storage.dart similarity index 72% rename from app/lib/web/universal_storage.dart rename to np_universal_storage/lib/src/web/universal_storage.dart index 3856a340..5d7d6958 100644 --- a/app/lib/web/universal_storage.dart +++ b/np_universal_storage/lib/src/web/universal_storage.dart @@ -1,14 +1,14 @@ import 'dart:convert'; import 'dart:typed_data'; -import 'package:nc_photos/platform/universal_storage.dart' as itf; +import 'package:np_universal_storage/src/universal_storage.dart' as itf; import 'package:shared_preferences/shared_preferences.dart'; const String _prefix = "_universal_storage"; -class UniversalStorage extends itf.UniversalStorage { +class UniversalStorage implements itf.UniversalStorage { @override - putBinary(String name, Uint8List content) async { + Future putBinary(String name, Uint8List content) async { // SharedPreferences happens to save to local storage on web, we'll just use // that final pref = await SharedPreferences.getInstance(); @@ -16,7 +16,7 @@ class UniversalStorage extends itf.UniversalStorage { } @override - getBinary(String name) async { + Future getBinary(String name) async { final pref = await SharedPreferences.getInstance(); final contentStr = pref.getString("$_prefix.$name"); if (contentStr == null) { @@ -27,7 +27,7 @@ class UniversalStorage extends itf.UniversalStorage { } @override - putString(String name, String content) async { + Future putString(String name, String content) async { // SharedPreferences happens to save to local storage on web, we'll just use // that final pref = await SharedPreferences.getInstance(); @@ -35,13 +35,13 @@ class UniversalStorage extends itf.UniversalStorage { } @override - getString(String name) async { + Future getString(String name) async { final pref = await SharedPreferences.getInstance(); return pref.getString("$_prefix.$name"); } @override - remove(String name) async { + Future remove(String name) async { final pref = await SharedPreferences.getInstance(); await pref.remove("$_prefix.$name"); } diff --git a/np_universal_storage/pubspec.yaml b/np_universal_storage/pubspec.yaml new file mode 100644 index 00000000..abf83442 --- /dev/null +++ b/np_universal_storage/pubspec.yaml @@ -0,0 +1,22 @@ +name: np_universal_storage +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 + np_string: + path: ../np_string + path: ^1.8.0 + path_provider: ^2.0.15 + shared_preferences: ^2.0.8 + +dev_dependencies: + np_lints: + path: ../np_lints