import 'dart:math'; import 'package:equatable/equatable.dart'; import 'package:logging/logging.dart'; import 'package:nc_photos/entity/file.dart'; import 'package:nc_photos/list_extension.dart'; List makeDistinctAlbumItems(List items) => items.distinctIf( (a, b) => a is AlbumFileItem && b is AlbumFileItem && a.file.path == b.file.path, (a) { if (a is AlbumFileItem) { return a.file.path.hashCode; } else { return Random().nextInt(0xFFFFFFFF); } }); abstract class AlbumItem { AlbumItem(); factory AlbumItem.fromJson(Map json) { final type = json["type"]; final content = json["content"]; switch (type) { case AlbumFileItem._type: return AlbumFileItem.fromJson(content.cast()); default: _log.shout("[fromJson] Unknown type: $type"); throw ArgumentError.value(type, "type"); } } Map toJson() { String getType() { if (this is AlbumFileItem) { return AlbumFileItem._type; } else { throw StateError("Unknwon subtype"); } } return { "type": getType(), "content": toContentJson(), }; } Map toContentJson(); static final _log = Logger("entity.album.AlbumItem"); } class AlbumFileItem extends AlbumItem with EquatableMixin { AlbumFileItem({this.file}); @override // ignore: hash_and_equals bool operator ==(Object other) => equals(other, isDeep: true); bool equals(Object other, {bool isDeep = false}) { if (other is AlbumFileItem) { return super == other && (file == null) == (other.file == null) && (file?.equals(other.file, isDeep: isDeep) ?? true); } else { return false; } } factory AlbumFileItem.fromJson(Map json) { return AlbumFileItem( file: File.fromJson(json["file"].cast()), ); } @override toString() { return "$runtimeType {" "file: $file" "}"; } @override toContentJson() { return { "file": file.toJson(), }; } @override get props => [ // file is handled separately, see [equals] ]; final File file; static const _type = "file"; }