1
0
mirror of https://github.com/immich-app/immich.git synced 2025-01-12 15:32:36 +02:00

feat(mobile): offer the same album sorting options on mobile as on web (#3804)

* Add translations for new album sort options

* Support additional album sort options like on web

* Update generated code

* Fix lint

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
Alexander Groß 2023-10-12 20:18:54 +02:00 committed by GitHub
parent f3b17d8f73
commit e57c926676
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 59 additions and 1 deletions

View File

@ -173,6 +173,8 @@
"library_page_sharing": "Sharing",
"library_page_sort_created": "Most recently created",
"library_page_sort_title": "Album title",
"library_page_sort_most_recent_photo": "Most recent photo",
"library_page_sort_last_modified": "Last modified",
"login_disabled": "Login has been disabled",
"login_form_api_exception": "API exception. Please check the server URL and try again.",
"login_form_handshake_exception": "There was an Handshake Exception with the server. Enable self-signed certificate support in the settings if you are using a self-signed certificate.",

View File

@ -47,6 +47,7 @@ class LibraryPage extends HookConsumerWidget {
useState(settings.getSetting(AppSettingsEnum.selectedAlbumSortOrder));
List<Album> sortedAlbums() {
// Created.
if (selectedAlbumSortOrder.value == 0) {
return albums
.where((a) => a.isRemote)
@ -54,6 +55,34 @@ class LibraryPage extends HookConsumerWidget {
.reversed
.toList();
}
// Album title.
if (selectedAlbumSortOrder.value == 1) {
return albums.where((a) => a.isRemote).sortedBy((album) => album.name);
}
// Most recent photo, if unset (e.g. empty album, use modifiedAt / updatedAt).
if (selectedAlbumSortOrder.value == 2) {
return albums
.where((a) => a.isRemote)
.sorted(
(a, b) => a.lastModifiedAssetTimestamp != null &&
b.lastModifiedAssetTimestamp != null
? a.lastModifiedAssetTimestamp!
.compareTo(b.lastModifiedAssetTimestamp!)
: a.modifiedAt.compareTo(b.modifiedAt),
)
.reversed
.toList();
}
// Last modified.
if (selectedAlbumSortOrder.value == 3) {
return albums
.where((a) => a.isRemote)
.sortedBy((album) => album.modifiedAt)
.reversed
.toList();
}
// Fallback: Album title.
return albums.where((a) => a.isRemote).sortedBy((album) => album.name);
}
@ -61,6 +90,8 @@ class LibraryPage extends HookConsumerWidget {
final options = [
"library_page_sort_created".tr(),
"library_page_sort_title".tr(),
"library_page_sort_most_recent_photo".tr(),
"library_page_sort_last_modified".tr(),
];
return PopupMenuButton(

View File

@ -18,6 +18,7 @@ class Album {
required this.name,
required this.createdAt,
required this.modifiedAt,
this.lastModifiedAssetTimestamp,
required this.shared,
});
@ -29,6 +30,7 @@ class Album {
String name;
DateTime createdAt;
DateTime modifiedAt;
DateTime? lastModifiedAssetTimestamp;
bool shared;
final IsarLink<User> owner = IsarLink<User>();
final IsarLink<Asset> thumbnail = IsarLink<Asset>();
@ -83,12 +85,21 @@ class Album {
@override
bool operator ==(other) {
if (other is! Album) return false;
final lastModifiedAssetTimestampIsSetAndEqual =
lastModifiedAssetTimestamp != null &&
other.lastModifiedAssetTimestamp != null
? lastModifiedAssetTimestamp!
.isAtSameMomentAs(other.lastModifiedAssetTimestamp!)
: true;
return id == other.id &&
remoteId == other.remoteId &&
localId == other.localId &&
name == other.name &&
createdAt.isAtSameMomentAs(other.createdAt) &&
modifiedAt.isAtSameMomentAs(other.modifiedAt) &&
lastModifiedAssetTimestampIsSetAndEqual &&
shared == other.shared &&
owner.value == other.owner.value &&
thumbnail.value == other.thumbnail.value &&
@ -105,6 +116,7 @@ class Album {
name.hashCode ^
createdAt.hashCode ^
modifiedAt.hashCode ^
lastModifiedAssetTimestamp.hashCode ^
shared.hashCode ^
owner.value.hashCode ^
thumbnail.value.hashCode ^
@ -130,6 +142,7 @@ class Album {
name: dto.albumName,
createdAt: dto.createdAt,
modifiedAt: dto.updatedAt,
lastModifiedAssetTimestamp: dto.lastModifiedAssetTimestamp,
shared: dto.shared,
);
a.owner.value = await db.users.getById(dto.ownerId);

View File

@ -282,6 +282,9 @@ class SyncService {
if (!_hasAlbumResponseDtoChanged(dto, album)) {
return false;
}
// loadDetails (/api/album/:id) will not include lastModifiedAssetTimestamp,
// i.e. it will always be null. Save it here.
final originalDto = dto;
dto = await loadDetails(dto);
if (dto.assetCount != dto.assets.length) {
return false;
@ -321,6 +324,7 @@ class SyncService {
album.name = dto.albumName;
album.shared = dto.shared;
album.modifiedAt = dto.updatedAt;
album.lastModifiedAssetTimestamp = originalDto.lastModifiedAssetTimestamp;
if (album.thumbnail.value?.remoteId != dto.albumThumbnailAssetId) {
album.thumbnail.value = await _db.assets
.where()
@ -808,5 +812,13 @@ bool _hasAlbumResponseDtoChanged(AlbumResponseDto dto, Album a) {
dto.albumThumbnailAssetId != a.thumbnail.value?.remoteId ||
dto.shared != a.shared ||
dto.sharedUsers.length != a.sharedUsers.length ||
!dto.updatedAt.isAtSameMomentAs(a.modifiedAt);
!dto.updatedAt.isAtSameMomentAs(a.modifiedAt) ||
(dto.lastModifiedAssetTimestamp == null &&
a.lastModifiedAssetTimestamp != null) ||
(dto.lastModifiedAssetTimestamp != null &&
a.lastModifiedAssetTimestamp == null) ||
(dto.lastModifiedAssetTimestamp != null &&
a.lastModifiedAssetTimestamp != null &&
!dto.lastModifiedAssetTimestamp!
.isAtSameMomentAs(a.lastModifiedAssetTimestamp!));
}