feature(mobile): no longer wait for background backup in settings (#1984)

* feature(mobile): no longer wait for background backup in settings

migrate all Hive boxes required for the backup process to Isar

* add final modifier
This commit is contained in:
Fynn Petersen-Frey
2023-03-18 15:55:11 +01:00
committed by GitHub
parent f56eaae019
commit 05cf5d57a9
12 changed files with 1533 additions and 379 deletions

View File

@@ -1,3 +1,4 @@
import 'package:collection/collection.dart';
import 'package:immich_mobile/shared/models/user.dart';
import 'package:isar/isar.dart';
import 'dart:convert';
@@ -9,7 +10,8 @@ part 'store.g.dart';
/// Can be used concurrently from multiple isolates
class Store {
static late final Isar _db;
static final List<dynamic> _cache = List.filled(StoreKey.values.length, null);
static final List<dynamic> _cache =
List.filled(StoreKey.values.map((e) => e.id).max + 1, null);
/// Initializes the store (call exactly once per app start)
static void init(Isar db) {
@@ -70,23 +72,44 @@ class StoreValue {
int? intValue;
String? strValue;
T? _extract<T>(StoreKey key) => key.isInt
? (key.fromDb == null ? intValue : key.fromDb!.call(Store._db, intValue!))
: (key.fromJson != null
? key.fromJson!(json.decode(strValue!))
: strValue);
static Future<StoreValue> _of(dynamic value, StoreKey key) async =>
StoreValue(
key.id,
intValue: key.isInt
? (key.toDb == null
? value
: await key.toDb!.call(Store._db, value))
: null,
strValue: key.isInt
dynamic _extract(StoreKey key) {
switch (key.type) {
case int:
return key.fromDb == null
? intValue
: key.fromDb!.call(Store._db, intValue!);
case bool:
return intValue == null ? null : intValue! == 1;
case DateTime:
return intValue == null
? null
: (key.fromJson == null ? value : json.encode(value.toJson())),
);
: DateTime.fromMicrosecondsSinceEpoch(intValue!);
case String:
return key.fromJson != null
? key.fromJson!.call(json.decode(strValue!))
: strValue;
}
}
static Future<StoreValue> _of(dynamic value, StoreKey key) async {
int? i;
String? s;
switch (key.type) {
case int:
i = (key.toDb == null ? value : await key.toDb!.call(Store._db, value));
break;
case bool:
i = value == null ? null : (value ? 1 : 0);
break;
case DateTime:
i = value == null ? null : (value as DateTime).microsecondsSinceEpoch;
break;
case String:
s = key.fromJson == null ? value : json.encode(value.toJson());
break;
}
return StoreValue(key.id, intValue: i, strValue: s);
}
}
/// Key for each possible value in the `Store`.
@@ -94,21 +117,24 @@ class StoreValue {
enum StoreKey {
userRemoteId(0),
assetETag(1),
currentUser(2, isInt: true, fromDb: _getUser, toDb: _toUser),
deviceIdHash(3, isInt: true),
currentUser(2, type: int, fromDb: _getUser, toDb: _toUser),
deviceIdHash(3, type: int),
deviceId(4),
;
backupFailedSince(5, type: DateTime),
backupRequireWifi(6, type: bool),
backupRequireCharging(7, type: bool),
backupTriggerDelay(8, type: int);
const StoreKey(
this.id, {
this.isInt = false,
this.type = String,
this.fromDb,
this.toDb,
// ignore: unused_element
this.fromJson,
});
final int id;
final bool isInt;
final Type type;
final dynamic Function(Isar, int)? fromDb;
final Future<int> Function(Isar, dynamic)? toDb;
final Function(dynamic)? fromJson;