mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-02-24 10:28:50 +01:00
Abstract album cover provider
This commit is contained in:
parent
0e7f2462b6
commit
8e46c604a8
6 changed files with 287 additions and 10 deletions
|
@ -7,6 +7,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/cover_provider.dart';
|
||||
import 'package:nc_photos/entity/album/provider.dart';
|
||||
import 'package:nc_photos/entity/album/upgrader.dart';
|
||||
import 'package:nc_photos/entity/file.dart';
|
||||
|
@ -127,6 +128,7 @@ class Album with EquatableMixin {
|
|||
DateTime lastUpdated,
|
||||
@required String name,
|
||||
@required this.provider,
|
||||
@required this.coverProvider,
|
||||
this.albumFile,
|
||||
}) : this.lastUpdated = (lastUpdated ?? DateTime.now()).toUtc(),
|
||||
this.name = name ?? "";
|
||||
|
@ -158,6 +160,8 @@ class Album with EquatableMixin {
|
|||
name: json["name"],
|
||||
provider:
|
||||
AlbumProvider.fromJson(json["provider"].cast<String, dynamic>()),
|
||||
coverProvider: AlbumCoverProvider.fromJson(
|
||||
json["coverProvider"].cast<String, dynamic>()),
|
||||
albumFile: json["albumFile"] == null
|
||||
? null
|
||||
: File.fromJson(json["albumFile"].cast<String, dynamic>()),
|
||||
|
@ -170,6 +174,7 @@ class Album with EquatableMixin {
|
|||
"lastUpdated: $lastUpdated, "
|
||||
"name: $name, "
|
||||
"provider: ${provider.toString(isDeep: isDeep)}, "
|
||||
"coverProvider: $coverProvider, "
|
||||
"albumFile: $albumFile, "
|
||||
"}";
|
||||
}
|
||||
|
@ -183,12 +188,14 @@ class Album with EquatableMixin {
|
|||
DateTime lastUpdated,
|
||||
String name,
|
||||
AlbumProvider provider,
|
||||
AlbumCoverProvider coverProvider,
|
||||
File albumFile,
|
||||
}) {
|
||||
return Album(
|
||||
lastUpdated: lastUpdated,
|
||||
name: name ?? this.name,
|
||||
provider: provider ?? this.provider,
|
||||
coverProvider: coverProvider ?? this.coverProvider,
|
||||
albumFile: albumFile ?? this.albumFile,
|
||||
);
|
||||
}
|
||||
|
@ -199,6 +206,7 @@ class Album with EquatableMixin {
|
|||
"lastUpdated": lastUpdated.toIso8601String(),
|
||||
"name": name,
|
||||
"provider": provider.toJson(),
|
||||
"coverProvider": coverProvider.toJson(),
|
||||
// ignore albumFile
|
||||
};
|
||||
}
|
||||
|
@ -209,6 +217,7 @@ class Album with EquatableMixin {
|
|||
"lastUpdated": lastUpdated.toIso8601String(),
|
||||
"name": name,
|
||||
"provider": provider.toJson(),
|
||||
"coverProvider": coverProvider.toJson(),
|
||||
if (albumFile != null) "albumFile": albumFile.toJson(),
|
||||
};
|
||||
}
|
||||
|
@ -218,6 +227,7 @@ class Album with EquatableMixin {
|
|||
lastUpdated,
|
||||
name,
|
||||
provider,
|
||||
coverProvider,
|
||||
albumFile,
|
||||
];
|
||||
|
||||
|
@ -225,6 +235,7 @@ class Album with EquatableMixin {
|
|||
final String name;
|
||||
|
||||
final AlbumProvider provider;
|
||||
final AlbumCoverProvider coverProvider;
|
||||
|
||||
/// How is this album stored on server
|
||||
///
|
||||
|
|
105
lib/entity/album/cover_provider.dart
Normal file
105
lib/entity/album/cover_provider.dart
Normal file
|
@ -0,0 +1,105 @@
|
|||
import 'package:equatable/equatable.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:nc_photos/entity/album.dart';
|
||||
import 'package:nc_photos/entity/album/provider.dart';
|
||||
import 'package:nc_photos/entity/file.dart';
|
||||
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
||||
import 'package:nc_photos/iterable_extension.dart' as iterable_extension;
|
||||
|
||||
abstract class AlbumCoverProvider with EquatableMixin {
|
||||
const AlbumCoverProvider();
|
||||
|
||||
factory AlbumCoverProvider.fromJson(Map<String, dynamic> json) {
|
||||
final type = json["type"];
|
||||
final content = json["content"];
|
||||
switch (type) {
|
||||
case AlbumAutoCoverProvider._type:
|
||||
return AlbumAutoCoverProvider.fromJson(content.cast<String, dynamic>());
|
||||
default:
|
||||
_log.shout("[fromJson] Unknown type: $type");
|
||||
throw ArgumentError.value(type, "type");
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
String getType() {
|
||||
if (this is AlbumAutoCoverProvider) {
|
||||
return AlbumAutoCoverProvider._type;
|
||||
} else {
|
||||
throw StateError("Unknwon subtype");
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
"type": getType(),
|
||||
"content": _toContentJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
toString();
|
||||
|
||||
File getCover(Album album);
|
||||
|
||||
Map<String, dynamic> _toContentJson();
|
||||
|
||||
static final _log = Logger("entity.album.cover_provider.AlbumCoverProvider");
|
||||
}
|
||||
|
||||
/// Cover selected automatically by us
|
||||
class AlbumAutoCoverProvider extends AlbumCoverProvider {
|
||||
AlbumAutoCoverProvider({
|
||||
this.coverFile,
|
||||
});
|
||||
|
||||
factory AlbumAutoCoverProvider.fromJson(Map<String, dynamic> json) {
|
||||
return AlbumAutoCoverProvider(
|
||||
coverFile: json["coverFile"] == null
|
||||
? null
|
||||
: File.fromJson(json["coverFile"].cast<String, dynamic>()),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
toString() {
|
||||
return "$runtimeType {"
|
||||
"coverFile: '${coverFile?.path}', "
|
||||
"}";
|
||||
}
|
||||
|
||||
File getCover(Album album) {
|
||||
if (coverFile == null) {
|
||||
try {
|
||||
// use the latest file as cover
|
||||
return AlbumStaticProvider.of(album)
|
||||
.items
|
||||
.whereType<AlbumFileItem>()
|
||||
.map((e) => e.file)
|
||||
.where((element) =>
|
||||
file_util.isSupportedFormat(element) && element.hasPreview)
|
||||
.sorted(compareFileDateTimeDescending)
|
||||
.first;
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return coverFile;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
get props => [
|
||||
coverFile,
|
||||
];
|
||||
|
||||
@override
|
||||
_toContentJson() {
|
||||
return {
|
||||
if (coverFile != null) "coverFile": coverFile.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
final File coverFile;
|
||||
|
||||
static const _type = "auto";
|
||||
}
|
|
@ -41,6 +41,12 @@ class AlbumUpgraderV2 implements AlbumUpgrader {
|
|||
}
|
||||
};
|
||||
result.remove("items");
|
||||
|
||||
// add the auto cover provider
|
||||
result["coverProvider"] = <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": {},
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -194,16 +194,8 @@ class _HomeAlbumsState extends State<HomeAlbums> {
|
|||
Widget _buildAlbumCover(BuildContext context, Album album) {
|
||||
Widget cover;
|
||||
try {
|
||||
// use the latest file as cover
|
||||
final latestFile = album.items
|
||||
.whereType<AlbumFileItem>()
|
||||
.map((e) => e.file)
|
||||
.where((element) =>
|
||||
file_util.isSupportedFormat(element) && element.hasPreview)
|
||||
.sorted(compareFileDateTimeDescending)
|
||||
.first;
|
||||
|
||||
final previewUrl = api_util.getFilePreviewUrl(widget.account, latestFile,
|
||||
final coverFile = album.coverProvider.getCover(album);
|
||||
final previewUrl = api_util.getFilePreviewUrl(widget.account, coverFile,
|
||||
width: 512, height: 512);
|
||||
cover = FittedBox(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.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/cover_provider.dart';
|
||||
import 'package:nc_photos/entity/album/provider.dart';
|
||||
import 'package:nc_photos/use_case/create_album.dart';
|
||||
|
||||
|
@ -67,6 +68,7 @@ class _NewAlbumDialogState extends State<NewAlbumDialog> {
|
|||
provider: AlbumStaticProvider(
|
||||
items: const [],
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(),
|
||||
);
|
||||
_log.info("[_onOkPressed] Creating album: $album");
|
||||
final albumRepo = AlbumRepo(AlbumCachedDataSource());
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:nc_photos/entity/album.dart';
|
||||
import 'package:nc_photos/entity/album/cover_provider.dart';
|
||||
import 'package:nc_photos/entity/album/provider.dart';
|
||||
import 'package:nc_photos/entity/album/upgrader.dart';
|
||||
import 'package:nc_photos/entity/file.dart';
|
||||
|
@ -17,6 +18,10 @@ void main() {
|
|||
"items": [],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
};
|
||||
expect(
|
||||
Album.fromJson(json),
|
||||
|
@ -26,6 +31,7 @@ void main() {
|
|||
provider: AlbumStaticProvider(
|
||||
items: [],
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(),
|
||||
));
|
||||
});
|
||||
|
||||
|
@ -40,6 +46,10 @@ void main() {
|
|||
"items": [],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
};
|
||||
expect(
|
||||
Album.fromJson(json),
|
||||
|
@ -49,6 +59,7 @@ void main() {
|
|||
provider: AlbumStaticProvider(
|
||||
items: [],
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(),
|
||||
));
|
||||
});
|
||||
|
||||
|
@ -80,6 +91,10 @@ void main() {
|
|||
],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
};
|
||||
expect(
|
||||
Album.fromJson(json),
|
||||
|
@ -96,6 +111,43 @@ void main() {
|
|||
),
|
||||
],
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(),
|
||||
));
|
||||
});
|
||||
|
||||
test("AlbumAutoCoverProvider", () {
|
||||
final json = <String, dynamic>{
|
||||
"version": Album.version,
|
||||
"lastUpdated": "2020-01-02T03:04:05.678901Z",
|
||||
"name": "",
|
||||
"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",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
expect(
|
||||
Album.fromJson(json),
|
||||
Album(
|
||||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
name: "",
|
||||
provider: AlbumStaticProvider(
|
||||
items: [],
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(
|
||||
coverFile: File(
|
||||
path: "remote.php/dav/files/admin/test1.jpg",
|
||||
),
|
||||
),
|
||||
));
|
||||
});
|
||||
|
||||
|
@ -109,6 +161,10 @@ void main() {
|
|||
"items": [],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"albumFile": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test1.jpg",
|
||||
},
|
||||
|
@ -121,6 +177,7 @@ void main() {
|
|||
provider: AlbumStaticProvider(
|
||||
items: [],
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(),
|
||||
albumFile: File(path: "remote.php/dav/files/admin/test1.jpg"),
|
||||
));
|
||||
});
|
||||
|
@ -134,6 +191,7 @@ void main() {
|
|||
provider: AlbumStaticProvider(
|
||||
items: [],
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(),
|
||||
);
|
||||
expect(album.toRemoteJson(), <String, dynamic>{
|
||||
"version": Album.version,
|
||||
|
@ -145,6 +203,10 @@ void main() {
|
|||
"items": [],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -155,6 +217,7 @@ void main() {
|
|||
provider: AlbumStaticProvider(
|
||||
items: [],
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(),
|
||||
);
|
||||
expect(album.toRemoteJson(), <String, dynamic>{
|
||||
"version": Album.version,
|
||||
|
@ -166,6 +229,10 @@ void main() {
|
|||
"items": [],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -183,6 +250,7 @@ void main() {
|
|||
),
|
||||
],
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(),
|
||||
);
|
||||
expect(album.toRemoteJson(), <String, dynamic>{
|
||||
"version": Album.version,
|
||||
|
@ -211,6 +279,41 @@ void main() {
|
|||
],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("AlbumAutoCoverProvider", () {
|
||||
final album = Album(
|
||||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
name: "",
|
||||
provider: AlbumStaticProvider(
|
||||
items: [],
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(
|
||||
coverFile: File(path: "remote.php/dav/files/admin/test1.jpg")),
|
||||
);
|
||||
expect(album.toRemoteJson(), <String, dynamic>{
|
||||
"version": Album.version,
|
||||
"lastUpdated": "2020-01-02T03:04:05.678901Z",
|
||||
"name": "",
|
||||
"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",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -223,6 +326,7 @@ void main() {
|
|||
provider: AlbumStaticProvider(
|
||||
items: [],
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(),
|
||||
);
|
||||
expect(album.toAppDbJson(), <String, dynamic>{
|
||||
"version": Album.version,
|
||||
|
@ -234,6 +338,10 @@ void main() {
|
|||
"items": [],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -244,6 +352,7 @@ void main() {
|
|||
provider: AlbumStaticProvider(
|
||||
items: [],
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(),
|
||||
);
|
||||
expect(album.toAppDbJson(), <String, dynamic>{
|
||||
"version": Album.version,
|
||||
|
@ -255,6 +364,10 @@ void main() {
|
|||
"items": [],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -272,6 +385,7 @@ void main() {
|
|||
),
|
||||
],
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(),
|
||||
);
|
||||
expect(album.toAppDbJson(), <String, dynamic>{
|
||||
"version": Album.version,
|
||||
|
@ -300,6 +414,44 @@ void main() {
|
|||
],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("AlbumAutoCoverProvider", () {
|
||||
final album = Album(
|
||||
lastUpdated: DateTime.utc(2020, 1, 2, 3, 4, 5, 678, 901),
|
||||
name: "",
|
||||
provider: AlbumStaticProvider(
|
||||
items: [],
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(
|
||||
coverFile: File(
|
||||
path: "remote.php/dav/files/admin/test1.jpg",
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(album.toAppDbJson(), <String, dynamic>{
|
||||
"version": Album.version,
|
||||
"lastUpdated": "2020-01-02T03:04:05.678901Z",
|
||||
"name": "",
|
||||
"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",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -310,6 +462,7 @@ void main() {
|
|||
provider: AlbumStaticProvider(
|
||||
items: [],
|
||||
),
|
||||
coverProvider: AlbumAutoCoverProvider(),
|
||||
albumFile: File(path: "remote.php/dav/files/admin/test1.jpg"),
|
||||
);
|
||||
expect(album.toAppDbJson(), <String, dynamic>{
|
||||
|
@ -322,6 +475,10 @@ void main() {
|
|||
"items": [],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"albumFile": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test1.jpg",
|
||||
},
|
||||
|
@ -393,6 +550,10 @@ void main() {
|
|||
],
|
||||
},
|
||||
},
|
||||
"coverProvider": <String, dynamic>{
|
||||
"type": "auto",
|
||||
"content": <String, dynamic>{},
|
||||
},
|
||||
"albumFile": <String, dynamic>{
|
||||
"path": "remote.php/dav/files/admin/test1.json",
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue