1
0
Fork 0
mirror of https://gitlab.com/nkming2/nc-photos.git synced 2025-03-09 16:58:55 +01:00

Refactor: extract universal storage

This commit is contained in:
Ming Ming 2023-08-29 01:22:29 +08:00
parent fd5b7f7e5b
commit 866720fa3a
18 changed files with 141 additions and 61 deletions

View file

@ -1,8 +1,7 @@
import 'package:nc_photos/entity/pref.dart'; 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:nc_photos/use_case/compat/v34.dart';
import 'package:np_common/type.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/shared_preferences.dart';
import 'package:shared_preferences_platform_interface/shared_preferences_platform_interface.dart'; import 'package:shared_preferences_platform_interface/shared_preferences_platform_interface.dart';
@ -14,7 +13,7 @@ class PrefSharedPreferencesProvider extends PrefProvider {
// await CompatV32.migratePref(); // await CompatV32.migratePref();
// } // }
if (await CompatV34.isPrefNeedMigration()) { if (await CompatV34.isPrefNeedMigration()) {
await CompatV34.migratePref(platform.UniversalStorage()); await CompatV34.migratePref(UniversalStorage());
} }
return SharedPreferences.getInstance().then((pref) { return SharedPreferences.getInstance().then((pref) {
_pref = pref; _pref = pref;

View file

@ -1,16 +1,15 @@
import 'dart:convert'; import 'dart:convert';
import 'package:nc_photos/entity/pref.dart'; 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_common/type.dart';
import 'package:np_universal_storage/np_universal_storage.dart';
/// [Pref] backed by [UniversalStorage] /// [Pref] backed by [UniversalStorage]
class PrefUniversalStorageProvider extends PrefProvider { class PrefUniversalStorageProvider extends PrefProvider {
PrefUniversalStorageProvider(this.name); PrefUniversalStorageProvider(this.name);
Future<void> init() async { Future<void> init() async {
final prefStr = await platform.UniversalStorage().getString(name) ?? "{}"; final prefStr = await UniversalStorage().getString(name) ?? "{}";
_data _data
..clear() ..clear()
..addAll(jsonDecode(prefStr)); ..addAll(jsonDecode(prefStr));
@ -41,14 +40,14 @@ class PrefUniversalStorageProvider extends PrefProvider {
@override @override
Future<bool> remove(PrefKeyInterface key) async { Future<bool> remove(PrefKeyInterface key) async {
final newData = Map.of(_data)..remove(key.toStringKey()); 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()); _data.remove(key.toStringKey());
return true; return true;
} }
@override @override
Future<bool> clear() async { Future<bool> clear() async {
await platform.UniversalStorage().remove(name); await UniversalStorage().remove(name);
_data.clear(); _data.clear();
return true; return true;
} }
@ -61,7 +60,7 @@ class PrefUniversalStorageProvider extends PrefProvider {
Future<bool> _set<T>(PrefKeyInterface key, T value) async { Future<bool> _set<T>(PrefKeyInterface key, T value) async {
final newData = Map.of(_data) final newData = Map.of(_data)
..addEntries([MapEntry(key.toStringKey(), value)]); ..addEntries([MapEntry(key.toStringKey(), value)]);
await platform.UniversalStorage().putString(name, jsonEncode(newData)); await UniversalStorage().putString(name, jsonEncode(newData));
_data[key.toStringKey()] = value; _data[key.toStringKey()] = value;
return true; return true;
} }

View file

@ -3,4 +3,3 @@ export 'download.dart';
export 'file_saver.dart'; export 'file_saver.dart';
export 'google_gps_map.dart'; export 'google_gps_map.dart';
export 'notification.dart'; export 'notification.dart';
export 'universal_storage.dart';

View file

@ -6,14 +6,13 @@ import 'package:nc_photos/di_container.dart';
import 'package:nc_photos/entity/file.dart'; import 'package:nc_photos/entity/file.dart';
import 'package:nc_photos/entity/file_descriptor.dart'; import 'package:nc_photos/entity/file_descriptor.dart';
import 'package:nc_photos/exception.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/remote_storage_util.dart' as remote_storage_util;
import 'package:nc_photos/throttler.dart'; import 'package:nc_photos/throttler.dart';
import 'package:nc_photos/use_case/ls_single_file.dart'; import 'package:nc_photos/use_case/ls_single_file.dart';
import 'package:nc_photos/use_case/put_file_binary.dart'; import 'package:nc_photos/use_case/put_file_binary.dart';
import 'package:np_codegen/np_codegen.dart'; import 'package:np_codegen/np_codegen.dart';
import 'package:np_common/or_null.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:path/path.dart' as path_lib;
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
@ -116,10 +115,10 @@ class TouchManager {
Future<void> setLocalEtag(Account account, File dir, String? etag) { Future<void> setLocalEtag(Account account, File dir, String? etag) {
final name = _getLocalStorageName(account, dir); final name = _getLocalStorageName(account, dir);
if (etag == null) { if (etag == null) {
return platform.UniversalStorage().remove(name); return UniversalStorage().remove(name);
} else { } else {
_log.info("[setLocalEtag] Set local etag for file '${dir.path}': $etag"); _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<String?> _getLocalEtag(Account account, File file) async { Future<String?> _getLocalEtag(Account account, File file) async {
final name = _getLocalStorageName(account, file); final name = _getLocalStorageName(account, file);
return platform.UniversalStorage().getString(name); return UniversalStorage().getString(name);
} }
String _getLocalStorageName(Account account, File file) { String _getLocalStorageName(Account account, File file) {

View file

@ -2,9 +2,9 @@ import 'dart:convert';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:nc_photos/account.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_codegen/np_codegen.dart';
import 'package:np_common/type.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/shared_preferences.dart';
part 'v34.g.dart'; part 'v34.g.dart';
@ -39,7 +39,8 @@ class CompatV34 {
final id = Account.newId(); final id = Account.newId();
account2["account"]["id"] = id; account2["account"]["id"] = id;
newJsons.add(account2["account"]); 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( if (await pref.setStringList(
"accounts3", newJsons.map((e) => jsonEncode(e)).toList())) { "accounts3", newJsons.map((e) => jsonEncode(e)).toList())) {

View file

@ -3,4 +3,3 @@ export 'download.dart';
export 'file_saver.dart'; export 'file_saver.dart';
export 'google_gps_map.dart'; export 'google_gps_map.dart';
export 'notification.dart'; export 'notification.dart';
export 'universal_storage.dart';

View file

@ -1039,6 +1039,13 @@ packages:
relative: true relative: true
source: path source: path
version: "0.0.1" 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: octo_image:
dependency: "direct main" dependency: "direct main"
description: description:

View file

@ -117,6 +117,8 @@ dependencies:
path: ../np_string path: ../np_string
np_ui: np_ui:
path: ../np_ui path: ../np_ui
np_universal_storage:
path: ../np_universal_storage
octo_image: any octo_image: any
page_view_indicators: ^2.0.0 page_view_indicators: ^2.0.0
path: ^1.8.0 path: ^1.8.0

View file

@ -1,7 +1,7 @@
import 'dart:convert'; import 'dart:convert';
import 'package:nc_photos/platform/universal_storage.dart';
import 'package:nc_photos/use_case/compat/v34.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:shared_preferences/shared_preferences.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';

30
np_universal_storage/.gitignore vendored Normal file
View file

@ -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/

View file

@ -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

View file

@ -0,0 +1 @@
include: package:np_lints/np.yaml

View file

@ -0,0 +1,4 @@
library np_universal_storage;
export 'src/memory_storage.dart';
export 'src/universal_storage.dart';

View file

@ -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<void> putBinary(String name, Uint8List content) async {
data[name] = content;
}
@override
Future<Uint8List?> getBinary(String name) async => data[name];
@override
Future<void> putString(String name, String content) async {
data[name] = content;
}
@override
Future<String?> getString(String name) async => data[name];
@override
Future<void> remove(String name) async {
data.remove(name);
}
final data = <String, dynamic>{};
}

View file

@ -1,21 +1,21 @@
import 'dart:io'; import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:nc_photos/platform/universal_storage.dart' as itf;
import 'package:np_string/np_string.dart'; 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/path.dart' as path_lib;
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
class UniversalStorage extends itf.UniversalStorage { class UniversalStorage implements itf.UniversalStorage {
@override @override
putBinary(String name, Uint8List content) async { Future<void> putBinary(String name, Uint8List content) async {
final storageDir = await _openStorageDirForFile(name); final storageDir = await _openStorageDirForFile(name);
final file = File("${storageDir.path}/$name"); final file = File("${storageDir.path}/$name");
await file.writeAsBytes(content, flush: true); await file.writeAsBytes(content, flush: true);
} }
@override @override
getBinary(String name) async { Future<Uint8List?> getBinary(String name) async {
final storageDir = await _openStorageDirForFile(name); final storageDir = await _openStorageDirForFile(name);
final file = File("${storageDir.path}/$name"); final file = File("${storageDir.path}/$name");
if (await file.exists()) { if (await file.exists()) {
@ -26,14 +26,14 @@ class UniversalStorage extends itf.UniversalStorage {
} }
@override @override
putString(String name, String content) async { Future<void> putString(String name, String content) async {
final storageDir = await _openStorageDirForFile(name); final storageDir = await _openStorageDirForFile(name);
final file = File("${storageDir.path}/$name"); final file = File("${storageDir.path}/$name");
await file.writeAsString(content, flush: true); await file.writeAsString(content, flush: true);
} }
@override @override
getString(String name) async { Future<String?> getString(String name) async {
final storageDir = await _openStorageDirForFile(name); final storageDir = await _openStorageDirForFile(name);
final file = File("${storageDir.path}/$name"); final file = File("${storageDir.path}/$name");
if (await file.exists()) { if (await file.exists()) {
@ -44,7 +44,7 @@ class UniversalStorage extends itf.UniversalStorage {
} }
@override @override
remove(String name) async { Future<void> remove(String name) async {
final storageDir = await _openStorageDirForFile(name); final storageDir = await _openStorageDirForFile(name);
final file = File("${storageDir.path}/$name"); final file = File("${storageDir.path}/$name");
if (await file.exists()) { if (await file.exists()) {

View file

@ -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 /// Store simple contents across different platforms
/// ///
/// On mobile, the contents will be persisted as a file. On web, the contents /// On mobile, the contents will be persisted as a file. On web, the contents
/// will be stored in local storage /// will be stored in local storage
abstract class UniversalStorage { abstract class UniversalStorage {
factory UniversalStorage() => impl.UniversalStorage();
Future<void> putBinary(String name, Uint8List content); Future<void> putBinary(String name, Uint8List content);
/// Return the content associated with [name], or null if no such association /// Return the content associated with [name], or null if no such association
@ -19,30 +25,3 @@ abstract class UniversalStorage {
Future<void> remove(String name); Future<void> 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 = <String, dynamic>{};
}

View file

@ -1,14 +1,14 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:typed_data'; 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'; import 'package:shared_preferences/shared_preferences.dart';
const String _prefix = "_universal_storage"; const String _prefix = "_universal_storage";
class UniversalStorage extends itf.UniversalStorage { class UniversalStorage implements itf.UniversalStorage {
@override @override
putBinary(String name, Uint8List content) async { Future<void> putBinary(String name, Uint8List content) async {
// SharedPreferences happens to save to local storage on web, we'll just use // SharedPreferences happens to save to local storage on web, we'll just use
// that // that
final pref = await SharedPreferences.getInstance(); final pref = await SharedPreferences.getInstance();
@ -16,7 +16,7 @@ class UniversalStorage extends itf.UniversalStorage {
} }
@override @override
getBinary(String name) async { Future<Uint8List?> getBinary(String name) async {
final pref = await SharedPreferences.getInstance(); final pref = await SharedPreferences.getInstance();
final contentStr = pref.getString("$_prefix.$name"); final contentStr = pref.getString("$_prefix.$name");
if (contentStr == null) { if (contentStr == null) {
@ -27,7 +27,7 @@ class UniversalStorage extends itf.UniversalStorage {
} }
@override @override
putString(String name, String content) async { Future<void> putString(String name, String content) async {
// SharedPreferences happens to save to local storage on web, we'll just use // SharedPreferences happens to save to local storage on web, we'll just use
// that // that
final pref = await SharedPreferences.getInstance(); final pref = await SharedPreferences.getInstance();
@ -35,13 +35,13 @@ class UniversalStorage extends itf.UniversalStorage {
} }
@override @override
getString(String name) async { Future<String?> getString(String name) async {
final pref = await SharedPreferences.getInstance(); final pref = await SharedPreferences.getInstance();
return pref.getString("$_prefix.$name"); return pref.getString("$_prefix.$name");
} }
@override @override
remove(String name) async { Future<void> remove(String name) async {
final pref = await SharedPreferences.getInstance(); final pref = await SharedPreferences.getInstance();
await pref.remove("$_prefix.$name"); await pref.remove("$_prefix.$name");
} }

View file

@ -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