mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-01-23 17:26:18 +01:00
159 lines
3.7 KiB
Dart
159 lines
3.7 KiB
Dart
import 'package:equatable/equatable.dart';
|
|
import 'package:logging/logging.dart';
|
|
import 'package:nc_photos/entity/album/item.dart';
|
|
import 'package:nc_photos/entity/file.dart';
|
|
import 'package:nc_photos/iterable_extension.dart';
|
|
import 'package:nc_photos/type.dart';
|
|
import 'package:tuple/tuple.dart';
|
|
|
|
abstract class AlbumSortProvider with EquatableMixin {
|
|
const AlbumSortProvider();
|
|
|
|
factory AlbumSortProvider.fromJson(JsonObj json) {
|
|
final type = json["type"];
|
|
final content = json["content"];
|
|
switch (type) {
|
|
case AlbumNullSortProvider._type:
|
|
return AlbumNullSortProvider.fromJson(content.cast<String, dynamic>());
|
|
case AlbumTimeSortProvider._type:
|
|
return AlbumTimeSortProvider.fromJson(content.cast<String, dynamic>());
|
|
default:
|
|
_log.shout("[fromJson] Unknown type: $type");
|
|
throw ArgumentError.value(type, "type");
|
|
}
|
|
}
|
|
|
|
JsonObj toJson() {
|
|
String getType() {
|
|
if (this is AlbumNullSortProvider) {
|
|
return AlbumNullSortProvider._type;
|
|
} else if (this is AlbumTimeSortProvider) {
|
|
return AlbumTimeSortProvider._type;
|
|
} else {
|
|
throw StateError("Unknwon subtype");
|
|
}
|
|
}
|
|
|
|
return {
|
|
"type": getType(),
|
|
"content": _toContentJson(),
|
|
};
|
|
}
|
|
|
|
/// Return a sorted copy of [items]
|
|
List<AlbumItem> sort(List<AlbumItem> items);
|
|
|
|
JsonObj _toContentJson();
|
|
|
|
static final _log = Logger("entity.album.sort_provider.AlbumSortProvider");
|
|
}
|
|
|
|
/// Sort provider that does nothing
|
|
class AlbumNullSortProvider extends AlbumSortProvider {
|
|
const AlbumNullSortProvider();
|
|
|
|
factory AlbumNullSortProvider.fromJson(JsonObj json) {
|
|
return const AlbumNullSortProvider();
|
|
}
|
|
|
|
@override
|
|
toString() {
|
|
return "$runtimeType {"
|
|
"}";
|
|
}
|
|
|
|
@override
|
|
sort(List<AlbumItem> items) {
|
|
return List.from(items);
|
|
}
|
|
|
|
@override
|
|
get props => [];
|
|
|
|
@override
|
|
_toContentJson() {
|
|
return {};
|
|
}
|
|
|
|
static const _type = "null";
|
|
}
|
|
|
|
abstract class AlbumReversibleSortProvider extends AlbumSortProvider {
|
|
const AlbumReversibleSortProvider({
|
|
required this.isAscending,
|
|
});
|
|
|
|
@override
|
|
toString() {
|
|
return "$runtimeType {"
|
|
"isAscending: $isAscending, "
|
|
"}";
|
|
}
|
|
|
|
@override
|
|
get props => [
|
|
isAscending,
|
|
];
|
|
|
|
@override
|
|
_toContentJson() {
|
|
return {
|
|
"isAscending": isAscending,
|
|
};
|
|
}
|
|
|
|
final bool isAscending;
|
|
}
|
|
|
|
/// Sort based on the time of the files
|
|
class AlbumTimeSortProvider extends AlbumReversibleSortProvider {
|
|
const AlbumTimeSortProvider({
|
|
required bool isAscending,
|
|
}) : super(isAscending: isAscending);
|
|
|
|
factory AlbumTimeSortProvider.fromJson(JsonObj json) {
|
|
return AlbumTimeSortProvider(
|
|
isAscending: json["isAscending"] ?? true,
|
|
);
|
|
}
|
|
|
|
@override
|
|
toString() {
|
|
return "$runtimeType {"
|
|
"super: ${super.toString()}, "
|
|
"}";
|
|
}
|
|
|
|
@override
|
|
sort(List<AlbumItem> items) {
|
|
DateTime? prevFileTime;
|
|
return items
|
|
.map((e) {
|
|
if (e is AlbumFileItem) {
|
|
// take the file time
|
|
prevFileTime = e.file.bestDateTime;
|
|
}
|
|
// for non file items, use the sibling file's time
|
|
return Tuple2(prevFileTime, e);
|
|
})
|
|
.stableSorted((x, y) {
|
|
if (x.item1 == null && y.item1 == null) {
|
|
return 0;
|
|
} else if (x.item1 == null) {
|
|
return -1;
|
|
} else if (y.item1 == null) {
|
|
return 1;
|
|
} else {
|
|
if (isAscending) {
|
|
return x.item1!.compareTo(y.item1!);
|
|
} else {
|
|
return y.item1!.compareTo(x.item1!);
|
|
}
|
|
}
|
|
})
|
|
.map((e) => e.item2)
|
|
.toList();
|
|
}
|
|
|
|
static const _type = "time";
|
|
}
|