chore: screenshots

This commit is contained in:
lollipopkit
2023-12-03 13:16:51 +08:00
parent 440dabfca8
commit 66d344c910
21 changed files with 171 additions and 181 deletions

View File

@@ -6,4 +6,12 @@ extension ListX<T> on List<T> {
}
return list;
}
List<T> combine(List<T> other, [bool self = true]) {
final list = self ? this : List<T>.from(this);
for (var i = 0; i < length; i++) {
list[i] = other[i];
}
return list;
}
}

View File

@@ -1,9 +1,8 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:toolbox/data/res/path.dart';
import 'package:toolbox/core/utils/misc.dart';
// abstract final class SecureStore {
// static const _secureStorage = FlutterSecureStorage();
@@ -30,8 +29,8 @@ import 'package:toolbox/data/res/path.dart';
// }
// }
class PersistentStore<E> {
late final Box<E> box;
class PersistentStore {
late final Box box;
final String boxName;
@@ -41,35 +40,48 @@ class PersistentStore<E> {
boxName,
//encryptionCipher: SecureStore._cipher,
);
}
/// Get all db filenames.
///
/// - [suffixs] defaults to ['.hive']
///
/// - If [hideSetting] is true, hide 'setting.hive'
static Future<List<String>> getFileNames({
bool hideSetting = false,
List<String>? suffixs,
}) async {
final docPath = await Paths.doc;
final dir = Directory(docPath);
final files = await dir.list().toList();
if (suffixs != null) {
files.removeWhere((e) => !suffixs.contains(e.path.split('.').last));
} else {
// filter out non-hive(db) files
files.removeWhere((e) => !e.path.endsWith('.hive'));
extension BoxX on Box {
static const _internalPreffix = '_sbi_';
/// Last modified timestamp
static const String lastModifiedKey = '${_internalPreffix}lastModified';
int? get lastModified {
final val = get(lastModifiedKey);
if (val == null || val is! int) {
final time = timeStamp;
put(lastModifiedKey, time);
return time;
}
if (hideSetting) {
files.removeWhere((e) => e.path.endsWith('setting.hive'));
}
final paths =
files.map((e) => e.path.replaceFirst('$docPath/', '')).toList();
return paths;
return val;
}
Future<void> updateLastModified() => put(lastModifiedKey, timeStamp);
/// Convert db to json
Map<String, dynamic> toJson() => {for (var e in box.keys) e: box.get(e)};
Map<String, dynamic> toJson({bool includeInternal = true}) {
final json = <String, dynamic>{};
for (final key in keys) {
if (key is String &&
key.startsWith(_internalPreffix) &&
!includeInternal) {
continue;
}
json[key] = get(key);
}
return json;
}
}
extension StoreX on PersistentStore {
_StoreProperty<T> property<T>(String key, T defaultValue) {
return _StoreProperty<T>(box, key, defaultValue);
}
_StoreListProperty<T> listProperty<T>(String key, List<T> defaultValue) {
return _StoreListProperty<T>(box, key, defaultValue);
}
}
abstract class StorePropertyBase<T> {
@@ -79,8 +91,8 @@ abstract class StorePropertyBase<T> {
Future<void> delete();
}
class StoreProperty<T> implements StorePropertyBase<T> {
StoreProperty(this._box, this._key, this.defaultValue);
class _StoreProperty<T> implements StorePropertyBase<T> {
_StoreProperty(this._box, this._key, this.defaultValue);
final Box _box;
final String _key;
@@ -102,6 +114,7 @@ class StoreProperty<T> implements StorePropertyBase<T> {
@override
Future<void> put(T value) {
_box.updateLastModified();
return _box.put(_key, value);
}
@@ -111,8 +124,8 @@ class StoreProperty<T> implements StorePropertyBase<T> {
}
}
class StoreListProperty<T> implements StorePropertyBase<List<T>> {
StoreListProperty(this._box, this._key, this.defaultValue);
class _StoreListProperty<T> implements StorePropertyBase<List<T>> {
_StoreListProperty(this._box, this._key, this.defaultValue);
final Box _box;
final String _key;

View File

@@ -2,29 +2,13 @@ import 'dart:async';
import 'dart:io';
import 'package:icloud_storage/icloud_storage.dart';
import 'package:toolbox/data/model/app/sync.dart';
import 'package:toolbox/data/res/logger.dart';
import '../../data/model/app/error.dart';
import '../../data/model/app/json.dart';
import '../../data/res/path.dart';
class SyncResult<T, E> {
final List<T> up;
final List<T> down;
final Map<T, E> err;
const SyncResult({
required this.up,
required this.down,
required this.err,
});
@override
String toString() {
return 'SyncResult{up: $up, down: $down, err: $err}';
}
}
abstract final class ICloud {
static const _containerId = 'iCloud.tech.lolli.serverbox';
@@ -111,7 +95,7 @@ abstract final class ICloud {
/// Return `null` if upload success, `ICloudErr` otherwise
///
/// TODO: consider merge strategy, use [SyncAble] and [JsonSerializable]
static Future<SyncResult<String, ICloudErr>> sync({
static Future<SyncResult<String, ICloudErr>> syncFiles({
required Iterable<String> relativePaths,
String? bakPrefix,
}) async {
@@ -196,4 +180,5 @@ abstract final class ICloud {
Loggers.app.info('iCloud sync, up: $uploadFiles, down: $downloadFiles');
}
}
}

View File

@@ -37,3 +37,5 @@ String pathJoin(String path1, String path2) {
/// Check if a url is a file url (ends with a file extension)
bool isFileUrl(String url) => url.split('/').last.contains('.');
int get timeStamp => DateTime.now().millisecondsSinceEpoch;