Improve album compatibility handling

This commit is contained in:
Ming Ming 2021-06-24 22:54:41 +08:00
parent 8d1fbea069
commit d4785b1f74
4 changed files with 72 additions and 85 deletions

View file

@ -4,6 +4,7 @@ import 'package:idb_shim/idb.dart';
import 'package:logging/logging.dart';
import 'package:nc_photos/account.dart';
import 'package:nc_photos/entity/album.dart';
import 'package:nc_photos/entity/album/upgrader.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;
@ -134,7 +135,10 @@ class AppDbAlbumEntry {
return AppDbAlbumEntry(
json["path"],
json["index"],
Album.fromJson(json["album"].cast<String, dynamic>()),
Album.fromJson(
json["album"].cast<String, dynamic>(),
upgraderV1: AlbumUpgraderV1(),
),
);
}

View file

@ -8,6 +8,7 @@ import 'package:idb_sqflite/idb_sqflite.dart';
import 'package:logging/logging.dart';
import 'package:nc_photos/account.dart';
import 'package:nc_photos/app_db.dart';
import 'package:nc_photos/entity/album/upgrader.dart';
import 'package:nc_photos/entity/file.dart';
import 'package:nc_photos/entity/file/data_source.dart';
import 'package:nc_photos/exception.dart';
@ -131,34 +132,19 @@ class Album with EquatableMixin {
this.name = name ?? "",
this.items = UnmodifiableListView(items);
factory Album.versioned({
int version,
DateTime lastUpdated,
@required String name,
@required List<AlbumItem> items,
File albumFile,
factory Album.fromJson(
Map<String, dynamic> json, {
AlbumUpgraderV1 upgraderV1,
}) {
// there's only one version right now
if (version < 2) {
return Album(
lastUpdated: lastUpdated,
name: name,
items: [],
albumFile: albumFile,
);
} else {
return Album(
lastUpdated: lastUpdated,
name: name,
items: items,
albumFile: albumFile,
);
final jsonVersion = json["version"];
if (jsonVersion < 2) {
json = upgraderV1?.call(json);
if (json == null) {
_log.info("[fromJson] Version $jsonVersion not compatible");
return null;
}
}
}
factory Album.fromJson(Map<String, dynamic> json) {
return Album.versioned(
version: json["version"],
return Album(
lastUpdated: json["lastUpdated"] == null
? null
: DateTime.parse(json["lastUpdated"]),
@ -292,8 +278,10 @@ class AlbumRemoteDataSource implements AlbumDataSource {
final fileRepo = FileRepo(FileWebdavDataSource());
final data = await GetFileBinary(fileRepo)(account, albumFile);
try {
return Album.fromJson(jsonDecode(utf8.decode(data)))
.copyWith(albumFile: albumFile);
return Album.fromJson(
jsonDecode(utf8.decode(data)),
upgraderV1: AlbumUpgraderV1(),
).copyWith(albumFile: albumFile);
} catch (e, stacktrace) {
dynamic d = data;
try {

View file

@ -0,0 +1,25 @@
import 'package:logging/logging.dart';
abstract class AlbumUpgrader {
Map<String, dynamic> call(Map<String, dynamic> json);
}
/// Upgrade v1 Album to v2
class AlbumUpgraderV1 implements AlbumUpgrader {
AlbumUpgraderV1({
this.logFilePath,
});
Map<String, dynamic> call(Map<String, dynamic> json) {
// v1 album items are corrupted in one of the updates, drop it
_log.fine("[call] Upgrade v1 Album for file: $logFilePath");
final result = Map<String, dynamic>.from(json);
result["items"] = [];
return result;
}
/// File path for logging only
final String logFilePath;
static final _log = Logger("entity.album.upgrader.AlbumUpgraderV1");
}

View file

@ -1,4 +1,5 @@
import 'package:nc_photos/entity/album.dart';
import 'package:nc_photos/entity/album/upgrader.dart';
import 'package:nc_photos/entity/file.dart';
import 'package:test/test.dart';
@ -250,62 +251,31 @@ void main() {
});
});
group("versioned", () {
test("v1", () {
final album = Album.versioned(
version: 1,
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
name: "album",
items: [
AlbumFileItem(
file: File(path: "remote.php/dav/files/admin/test1.jpg"),
),
AlbumFileItem(
file: File(path: "remote.php/dav/files/admin/test2.jpg"),
),
],
albumFile: File(path: "remote.php/dav/files/admin/test1.jpg"),
);
expect(
album,
Album(
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
name: "album",
items: [],
albumFile: File(path: "remote.php/dav/files/admin/test1.jpg"),
));
});
test("v2", () {
final album = Album.versioned(
version: 2,
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
name: "album",
items: [
AlbumFileItem(
file: File(path: "remote.php/dav/files/admin/test1.jpg"),
),
AlbumFileItem(
file: File(path: "remote.php/dav/files/admin/test2.jpg"),
),
],
albumFile: File(path: "remote.php/dav/files/admin/test1.jpg"),
);
expect(
album,
Album(
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
name: "album",
items: [
AlbumFileItem(
file: File(path: "remote.php/dav/files/admin/test1.jpg"),
),
AlbumFileItem(
file: File(path: "remote.php/dav/files/admin/test2.jpg"),
),
],
albumFile: File(path: "remote.php/dav/files/admin/test1.jpg"),
));
test("AlbumUpgraderV1", () {
final json = <String, dynamic>{
"version": 1,
"lastUpdated": "2020-01-02T03:04:05.678901Z",
"items": [
<String, dynamic>{
"type": "file",
"content": <String, dynamic>{
"file": <String, dynamic>{
"path": "remote.php/dav/files/admin/test1.jpg",
},
},
},
],
"albumFile": <String, dynamic>{
"path": "remote.php/dav/files/admin/test1.json",
},
};
expect(AlbumUpgraderV1()(json), <String, dynamic>{
"version": 1,
"lastUpdated": "2020-01-02T03:04:05.678901Z",
"items": [],
"albumFile": <String, dynamic>{
"path": "remote.php/dav/files/admin/test1.json",
},
});
});
});