Migrate AlbumAutoCoverProvider to use FileDescriptor

This commit is contained in:
Ming Ming 2023-04-18 00:58:09 +08:00
parent 72bd5fa38e
commit 7bd33c8444
12 changed files with 191 additions and 64 deletions

View file

@ -65,7 +65,7 @@ abstract class AlbumCoverProvider with EquatableMixin {
/// Cover selected automatically by us
@toString
class AlbumAutoCoverProvider extends AlbumCoverProvider {
AlbumAutoCoverProvider({
const AlbumAutoCoverProvider({
this.coverFile,
});
@ -73,7 +73,7 @@ class AlbumAutoCoverProvider extends AlbumCoverProvider {
return AlbumAutoCoverProvider(
coverFile: json["coverFile"] == null
? null
: File.fromJson(json["coverFile"].cast<String, dynamic>()),
: FileDescriptor.fromJson(json["coverFile"].cast<String, dynamic>()),
);
}
@ -81,7 +81,7 @@ class AlbumAutoCoverProvider extends AlbumCoverProvider {
String toString() => _$toString();
@override
getCover(Album album) {
FileDescriptor? getCover(Album album) {
if (coverFile == null) {
try {
// use the latest file as cover
@ -103,18 +103,18 @@ class AlbumAutoCoverProvider extends AlbumCoverProvider {
}
@override
get props => [
List<Object?> get props => [
coverFile,
];
@override
_toContentJson() {
JsonObj _toContentJson() {
return {
if (coverFile != null) "coverFile": coverFile!.toJson(),
};
}
final File? coverFile;
final FileDescriptor? coverFile;
static const _type = "auto";
}

View file

@ -20,7 +20,7 @@ extension _$AlbumCoverProviderNpLog on AlbumCoverProvider {
extension _$AlbumAutoCoverProviderToString on AlbumAutoCoverProvider {
String _$toString() {
// ignore: unnecessary_string_interpolations
return "AlbumAutoCoverProvider {coverFile: ${coverFile == null ? null : "${coverFile!.path}"}}";
return "AlbumAutoCoverProvider {coverFile: ${coverFile == null ? null : "${coverFile!.fdPath}"}}";
}
}

View file

@ -252,25 +252,23 @@ class AlbumUpgraderV8 implements AlbumUpgrader {
_log.fine("[call] Upgrade v8 Album for file: $logFilePath");
final result = JsonObj.from(json);
try {
if (result["coverProvider"]["type"] != "manual") {
if (result["coverProvider"]["type"] == "manual") {
final content = (result["coverProvider"]["content"]["coverFile"] as Map)
.cast<String, dynamic>();
final fd = _fileJsonToFileDescriptorJson(content);
result["coverProvider"]["content"]["coverFile"] = fd;
} else if (result["coverProvider"]["type"] == "auto") {
final content =
(result["coverProvider"]["content"]["coverFile"] as Map?)
?.cast<String, dynamic>();
if (content != null) {
final fd = _fileJsonToFileDescriptorJson(content);
result["coverProvider"]["content"]["coverFile"] = fd;
}
return result;
} else {
return result;
}
final content = (result["coverProvider"]["content"]["coverFile"] as Map)
.cast<String, dynamic>();
final fd = {
"fdPath": content["path"],
"fdId": content["fileId"],
"fdMime": content["contentType"],
"fdIsArchived": content["isArchived"] ?? false,
"fdIsFavorite": content["isFavorite"] ?? false,
"fdDateTime": content["overrideDateTime"] ??
(content["metadata"]?["exif"]?["DateTimeOriginal"] as String?)?.run(
(d) =>
Exif.dateTimeFormat.parse(d).toUtc().toIso8601String()) ??
content["lastModified"] ??
clock.now().toUtc().toIso8601String(),
};
result["coverProvider"]["content"]["coverFile"] = fd;
} catch (e, stackTrace) {
// this upgrade is not a must, if it failed then just leave it and it'll
// be upgraded the next time the album is saved
@ -279,6 +277,21 @@ class AlbumUpgraderV8 implements AlbumUpgrader {
return result;
}
static JsonObj _fileJsonToFileDescriptorJson(JsonObj json) {
return {
"fdPath": json["path"],
"fdId": json["fileId"],
"fdMime": json["contentType"],
"fdIsArchived": json["isArchived"] ?? false,
"fdIsFavorite": json["isFavorite"] ?? false,
"fdDateTime": json["overrideDateTime"] ??
(json["metadata"]?["exif"]?["DateTimeOriginal"] as String?)?.run(
(d) => Exif.dateTimeFormat.parse(d).toUtc().toIso8601String()) ??
json["lastModified"] ??
clock.now().toUtc().toIso8601String(),
};
}
/// File path for logging only
final String? logFilePath;
}

View file

@ -50,7 +50,7 @@ class EditAlbum {
if (cover != null) {
if (cover.obj == null) {
newAlbum = newAlbum.copyWith(
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
);
} else {
newAlbum = newAlbum.copyWith(

View file

@ -103,7 +103,7 @@ class RemoveFromAlbum {
true) {
// revert to auto cover so [UpdateAutoAlbumCover] can do its work
newAlbum = newAlbum.copyWith(
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
);
isNeedUpdate = true;
break;

View file

@ -34,8 +34,8 @@ class UpdateAutoAlbumCover {
Album _updateWithSortedItems(Album album, List<AlbumItem> sortedItems) {
if (sortedItems.isEmpty) {
if (album.coverProvider != AlbumAutoCoverProvider()) {
return album.copyWith(coverProvider: AlbumAutoCoverProvider());
if (album.coverProvider != const AlbumAutoCoverProvider()) {
return album.copyWith(coverProvider: const AlbumAutoCoverProvider());
} else {
return album;
}

View file

@ -211,7 +211,7 @@ mixin AlbumBrowserMixin<T extends StatefulWidget>
await UpdateAlbum(albumRepo)(
account,
album.copyWith(
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
));
},
L10n.global().unsetAlbumCoverProcessingNotification,

View file

@ -245,7 +245,7 @@ class _AlbumImporterState extends State<AlbumImporter> {
provider: AlbumDirProvider(
dirs: [p],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumTimeSortProvider(isAscending: false),
);
_log.info("[_createAllAlbums] Creating dir album: $album");

View file

@ -73,7 +73,7 @@ class _Bloc extends Bloc<_Event, _State> {
album: Album(
name: state.formValue.name,
provider: AlbumStaticProvider(items: const []),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumTimeSortProvider(isAscending: false),
),
);
@ -84,7 +84,7 @@ class _Bloc extends Bloc<_Event, _State> {
album: Album(
name: state.formValue.name,
provider: AlbumDirProvider(dirs: state.formValue.dirs),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumTimeSortProvider(isAscending: false),
),
);
@ -95,7 +95,7 @@ class _Bloc extends Bloc<_Event, _State> {
album: Album(
name: state.formValue.name,
provider: AlbumTagProvider(tags: state.formValue.tags),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumTimeSortProvider(isAscending: false),
),
);

View file

@ -47,7 +47,7 @@ void main() {
provider: AlbumStaticProvider(
items: [],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
));
});
@ -83,7 +83,7 @@ void main() {
provider: AlbumStaticProvider(
items: [],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
));
});
@ -152,7 +152,7 @@ void main() {
),
],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
));
});
@ -203,7 +203,7 @@ void main() {
),
],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
));
});
@ -286,7 +286,7 @@ void main() {
provider: AlbumStaticProvider(
items: [],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumTimeSortProvider(
isAscending: true,
),
@ -326,7 +326,7 @@ void main() {
provider: AlbumStaticProvider(
items: [],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumFilenameSortProvider(
isAscending: true,
),
@ -369,7 +369,7 @@ void main() {
provider: AlbumStaticProvider(
items: [],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
albumFile: File(path: "remote.php/dav/files/admin/test1.jpg"),
));
@ -384,7 +384,7 @@ void main() {
provider: AlbumStaticProvider(
items: [],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
);
expect(album.toRemoteJson(), <String, dynamic>{
@ -415,7 +415,7 @@ void main() {
provider: AlbumStaticProvider(
items: [],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
);
expect(album.toRemoteJson(), <String, dynamic>{
@ -458,7 +458,7 @@ void main() {
),
],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
);
expect(album.toRemoteJson(), <String, dynamic>{
@ -516,7 +516,7 @@ void main() {
),
],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
);
expect(album.toRemoteJson(), <String, dynamic>{
@ -593,7 +593,7 @@ void main() {
provider: AlbumStaticProvider(
items: [],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumTimeSortProvider(
isAscending: true,
),
@ -628,7 +628,7 @@ void main() {
provider: AlbumStaticProvider(
items: [],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumFilenameSortProvider(
isAscending: true,
),
@ -667,7 +667,7 @@ void main() {
provider: AlbumStaticProvider(
items: [],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
);
expect(album.toAppDbJson(), <String, dynamic>{
@ -698,7 +698,7 @@ void main() {
provider: AlbumStaticProvider(
items: [],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
);
expect(album.toAppDbJson(), <String, dynamic>{
@ -741,7 +741,7 @@ void main() {
),
],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
);
expect(album.toAppDbJson(), <String, dynamic>{
@ -799,7 +799,7 @@ void main() {
),
],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
);
expect(album.toAppDbJson(), <String, dynamic>{
@ -879,7 +879,7 @@ void main() {
provider: AlbumStaticProvider(
items: [],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumTimeSortProvider(
isAscending: true,
),
@ -914,7 +914,7 @@ void main() {
provider: AlbumStaticProvider(
items: [],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumFilenameSortProvider(
isAscending: true,
),
@ -951,7 +951,7 @@ void main() {
provider: AlbumStaticProvider(
items: [],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
albumFile: File(path: "remote.php/dav/files/admin/test1.jpg"),
);
@ -1762,8 +1762,16 @@ void main() {
group("AlbumUpgraderV8", () {
test("non manual cover", _upgradeV8NonManualCover);
test("manual cover", _upgradeV8ManualCover);
test("manual cover (exif time)", _upgradeV8ManualExifTime);
group("manual cover", () {
test("now", _upgradeV8ManualNow);
test("exif time", _upgradeV8ManualExifTime);
});
group("auto cover", () {
test("null", _upgradeV8AutoNull);
test("last modified", _upgradeV8AutoLastModified);
});
});
});
}
@ -1806,7 +1814,7 @@ void _fromJsonShares() {
provider: AlbumStaticProvider(
items: [],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
shares: [util.buildAlbumShare(userId: "admin")],
));
@ -1819,7 +1827,7 @@ void _toRemoteJsonShares() {
provider: AlbumStaticProvider(
items: [],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
shares: [util.buildAlbumShare(userId: "admin")],
);
@ -1858,7 +1866,7 @@ void _toAppDbJsonShares() {
provider: AlbumStaticProvider(
items: [],
),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
shares: [util.buildAlbumShare(userId: "admin")],
);
@ -1953,7 +1961,7 @@ void _upgradeV8NonManualCover() {
});
}
void _upgradeV8ManualCover() {
void _upgradeV8ManualNow() {
withClock(Clock.fixed(DateTime.utc(2020, 1, 2, 3, 4, 5)), () {
final json = <String, dynamic>{
"version": 8,
@ -2079,6 +2087,112 @@ void _upgradeV8ManualExifTime() {
});
}
void _upgradeV8AutoNull() {
final json = <String, dynamic>{
"version": 8,
"lastUpdated": "2020-01-02T03:04:05.678901Z",
"provider": <String, dynamic>{
"type": "static",
"content": <String, dynamic>{
"items": [],
},
},
"coverProvider": <String, dynamic>{
"type": "auto",
"content": <String, dynamic>{},
},
"sortProvider": <String, dynamic>{
"type": "null",
"content": <String, dynamic>{},
},
"albumFile": <String, dynamic>{
"path": "remote.php/dav/files/admin/test1.json",
},
};
expect(const AlbumUpgraderV8()(json), <String, dynamic>{
"version": 8,
"lastUpdated": "2020-01-02T03:04:05.678901Z",
"provider": <String, dynamic>{
"type": "static",
"content": <String, dynamic>{
"items": [],
},
},
"coverProvider": <String, dynamic>{
"type": "auto",
"content": <String, dynamic>{},
},
"sortProvider": <String, dynamic>{
"type": "null",
"content": <String, dynamic>{},
},
"albumFile": <String, dynamic>{
"path": "remote.php/dav/files/admin/test1.json",
},
});
}
void _upgradeV8AutoLastModified() {
final json = <String, dynamic>{
"version": 8,
"lastUpdated": "2020-01-02T03:04:05.678901Z",
"provider": <String, dynamic>{
"type": "static",
"content": <String, dynamic>{
"items": [],
},
},
"coverProvider": <String, dynamic>{
"type": "auto",
"content": <String, dynamic>{
"coverFile": <String, dynamic>{
"path": "remote.php/dav/files/admin/test1.jpg",
"fileId": 1,
"lastModified": "2020-01-02T03:04:05.000Z",
},
},
},
"sortProvider": <String, dynamic>{
"type": "null",
"content": <String, dynamic>{},
},
"albumFile": <String, dynamic>{
"path": "remote.php/dav/files/admin/test1.json",
},
};
expect(const AlbumUpgraderV8()(json), <String, dynamic>{
"version": 8,
"lastUpdated": "2020-01-02T03:04:05.678901Z",
"provider": <String, dynamic>{
"type": "static",
"content": <String, dynamic>{
"items": [],
},
},
"coverProvider": <String, dynamic>{
"type": "auto",
"content": <String, dynamic>{
"coverFile": <String, dynamic>{
"fdPath": "remote.php/dav/files/admin/test1.jpg",
"fdId": 1,
"fdMime": null,
"fdIsArchived": false,
"fdIsFavorite": false,
// dart does not provide a way to mock timezone
"fdDateTime": "2020-01-02T03:04:05.000Z",
},
},
},
"sortProvider": <String, dynamic>{
"type": "null",
"content": <String, dynamic>{},
},
"albumFile": <String, dynamic>{
"path": "remote.php/dav/files/admin/test1.json",
},
});
}
class _NullAlbumUpgraderFactory extends AlbumUpgraderFactory {
const _NullAlbumUpgraderFactory();

View file

@ -74,7 +74,7 @@ Future<void> _removeLastFile() async {
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5),
name: "test",
provider: AlbumStaticProvider(items: []),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
albumFile: albumFile,
),

View file

@ -119,7 +119,7 @@ Future<void> _removeAlbumFile() async {
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5),
name: "test",
provider: AlbumStaticProvider(items: []),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
albumFile: albumFile,
),
@ -216,7 +216,7 @@ Future<void> _removeSharedAlbumFile() async {
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5),
name: "test",
provider: AlbumStaticProvider(items: []),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
albumFile: albumFile,
shares: [
@ -286,7 +286,7 @@ Future<void> _removeSharedAlbumSharedFile() async {
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5),
name: "test",
provider: AlbumStaticProvider(items: []),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
albumFile: albumFile,
shares: [
@ -351,7 +351,7 @@ Future<void> _removeSharedAlbumResyncedFile() async {
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5),
name: "test",
provider: AlbumStaticProvider(items: []),
coverProvider: AlbumAutoCoverProvider(),
coverProvider: const AlbumAutoCoverProvider(),
sortProvider: const AlbumNullSortProvider(),
albumFile: albumFile,
shares: [