From 215911cf29dea715dc39569826fbd3d0fda00484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= Date: Sun, 17 May 2026 00:27:17 +0200 Subject: [PATCH] refactored room and file sorting to use direct comparators instead of temporary sort strings, removed obsolete 'sort' properties from API models, and improved file list sorting with case-insensitive name comparisons and null-safe date handling --- .../talk/room/get_room_response.dart | 23 +++---- .../talk/room/get_room_response.g.dart | 3 +- .../queries/list_files/cacheable_file.dart | 1 - .../queries/list_files/cacheable_file.g.dart | 3 +- .../list_files/list_files_response.dart | 64 ++++--------------- lib/view/pages/files/data/sort_options.dart | 8 ++- .../pages/share_intent/share_chat_picker.dart | 1 - lib/view/pages/talk/chat_list.dart | 1 - 8 files changed, 27 insertions(+), 77 deletions(-) diff --git a/lib/api/marianumcloud/talk/room/get_room_response.dart b/lib/api/marianumcloud/talk/room/get_room_response.dart index c18e668..b720c65 100644 --- a/lib/api/marianumcloud/talk/room/get_room_response.dart +++ b/lib/api/marianumcloud/talk/room/get_room_response.dart @@ -16,26 +16,20 @@ class GetRoomResponse extends ApiResponse { Map toJson() => _$GetRoomResponseToJson(this); List sortBy({ - bool lastActivity = true, required bool favoritesToTop, required bool unreadToTop, }) { - for (var chat in data) { - final buffer = StringBuffer(); - - if (favoritesToTop) { - buffer.write(chat.isFavorite ? 'b' : 'a'); + return data.toList()..sort((a, b) { + if (favoritesToTop && a.isFavorite != b.isFavorite) { + return a.isFavorite ? -1 : 1; } if (unreadToTop) { - buffer.write(chat.unreadMessages > 0 ? 'b' : 'a'); + final aUnread = a.unreadMessages > 0; + final bUnread = b.unreadMessages > 0; + if (aUnread != bUnread) return aUnread ? -1 : 1; } - - buffer.write(chat.lastActivity); - - chat.sort = buffer.toString(); - } - - return data.toList()..sort((a, b) => b.sort!.compareTo(a.sort!)); + return b.lastActivity.compareTo(a.lastActivity); + }); } } @@ -71,7 +65,6 @@ class GetRoomResponseObject { String? status; String? statusIcon; String? statusMessage; - String? sort; GetRoomResponseObject( this.id, diff --git a/lib/api/marianumcloud/talk/room/get_room_response.g.dart b/lib/api/marianumcloud/talk/room/get_room_response.g.dart index 49362cc..edda039 100644 --- a/lib/api/marianumcloud/talk/room/get_room_response.g.dart +++ b/lib/api/marianumcloud/talk/room/get_room_response.g.dart @@ -60,7 +60,7 @@ GetRoomResponseObject _$GetRoomResponseObjectFromJson( json['status'] as String?, json['statusIcon'] as String?, json['statusMessage'] as String?, -)..sort = json['sort'] as String?; +); Map _$GetRoomResponseObjectToJson( GetRoomResponseObject instance, @@ -97,7 +97,6 @@ Map _$GetRoomResponseObjectToJson( 'status': instance.status, 'statusIcon': instance.statusIcon, 'statusMessage': instance.statusMessage, - 'sort': instance.sort, }; const _$GetRoomResponseObjectConversationTypeEnumMap = { diff --git a/lib/api/marianumcloud/webdav/queries/list_files/cacheable_file.dart b/lib/api/marianumcloud/webdav/queries/list_files/cacheable_file.dart index e8c1130..e96b6a0 100644 --- a/lib/api/marianumcloud/webdav/queries/list_files/cacheable_file.dart +++ b/lib/api/marianumcloud/webdav/queries/list_files/cacheable_file.dart @@ -13,7 +13,6 @@ class CacheableFile { String? eTag; DateTime? createdAt; DateTime? modifiedAt; - String? sort; /// Nextcloud's instance-local file id (`oc:fileid`). Used to address the /// preview API by id, which is more reliable than the path-based variant diff --git a/lib/api/marianumcloud/webdav/queries/list_files/cacheable_file.g.dart b/lib/api/marianumcloud/webdav/queries/list_files/cacheable_file.g.dart index 63bc94f..b1e7c44 100644 --- a/lib/api/marianumcloud/webdav/queries/list_files/cacheable_file.g.dart +++ b/lib/api/marianumcloud/webdav/queries/list_files/cacheable_file.g.dart @@ -22,7 +22,7 @@ CacheableFile _$CacheableFileFromJson(Map json) => : DateTime.parse(json['modifiedAt'] as String), fileId: (json['fileId'] as num?)?.toInt(), hasPreview: json['hasPreview'] as bool?, - )..sort = json['sort'] as String?; + ); Map _$CacheableFileToJson(CacheableFile instance) => { @@ -34,7 +34,6 @@ Map _$CacheableFileToJson(CacheableFile instance) => 'eTag': instance.eTag, 'createdAt': instance.createdAt?.toIso8601String(), 'modifiedAt': instance.modifiedAt?.toIso8601String(), - 'sort': instance.sort, 'fileId': instance.fileId, 'hasPreview': instance.hasPreview, }; diff --git a/lib/api/marianumcloud/webdav/queries/list_files/list_files_response.dart b/lib/api/marianumcloud/webdav/queries/list_files/list_files_response.dart index 3c73cd8..05bb271 100644 --- a/lib/api/marianumcloud/webdav/queries/list_files/list_files_response.dart +++ b/lib/api/marianumcloud/webdav/queries/list_files/list_files_response.dart @@ -1,4 +1,3 @@ -import 'package:jiffy/jiffy.dart'; import 'package:json_annotation/json_annotation.dart'; import '../../../../../view/pages/files/data/sort_options.dart'; @@ -22,60 +21,19 @@ class ListFilesResponse extends ApiResponse { SortOption sortOption = SortOption.name, bool reversed = false, }) { - var list = List.empty(growable: true); + final ascending = SortOptions.getOption(sortOption).compare; + // `reversed=true` means user picked "Aufsteigend" (a→z, oldest→newest, + // smallest→largest); default is descending. + final compare = reversed + ? ascending + : (CacheableFile a, CacheableFile b) => ascending(b, a); - if (foldersToTop) { - list.addAll( - _sort( - files.where((element) => element.isDirectory).toSet(), - reversed: reversed, - sortOption: sortOption, - ), - ); - list.addAll( - _sort( - files.where((element) => !element.isDirectory).toSet(), - reversed: reversed, - sortOption: sortOption, - ), - ); - } else { - list.addAll(_sort(files, reversed: reversed, sortOption: sortOption)); + if (!foldersToTop) { + return files.toList()..sort(compare); } - return list; - } - - List _sort( - Set files, { - SortOption sortOption = SortOption.name, - bool reversed = false, - }) { - for (var file in files) { - final buffer = StringBuffer(); - - switch (sortOption) { - case SortOption.date: - buffer.write( - Jiffy.parseFromMillisecondsSinceEpoch( - file.modifiedAt?.millisecondsSinceEpoch ?? 0, - ).format(pattern: 'yyyyMMddhhmmss'), - ); - break; - - case SortOption.name: - buffer.write(file.name.toLowerCase()); - break; - - case SortOption.size: - buffer.write(file.size); - break; - } - - file.sort = buffer.toString(); - } - - var list = files.toList()..sort((a, b) => b.sort!.compareTo(a.sort!)); - return reversed ? list.reversed.toList() : list; + final folders = files.where((f) => f.isDirectory).toList()..sort(compare); + final regular = files.where((f) => !f.isDirectory).toList()..sort(compare); + return [...folders, ...regular]; } } diff --git a/lib/view/pages/files/data/sort_options.dart b/lib/view/pages/files/data/sort_options.dart index ab78fdf..3532560 100644 --- a/lib/view/pages/files/data/sort_options.dart +++ b/lib/view/pages/files/data/sort_options.dart @@ -21,12 +21,16 @@ class SortOptions { SortOption.name: BetterSortOption( displayName: 'Name', icon: Icons.sort_by_alpha_outlined, - compare: (a, b) => a.name.compareTo(b.name), + compare: (a, b) => a.name.toLowerCase().compareTo(b.name.toLowerCase()), ), SortOption.date: BetterSortOption( displayName: 'Datum', icon: Icons.history_outlined, - compare: (a, b) => a.modifiedAt!.compareTo(b.modifiedAt!), + compare: (a, b) { + final aMs = a.modifiedAt?.millisecondsSinceEpoch ?? 0; + final bMs = b.modifiedAt?.millisecondsSinceEpoch ?? 0; + return aMs.compareTo(bMs); + }, ), SortOption.size: BetterSortOption( displayName: 'Größe', diff --git a/lib/view/pages/share_intent/share_chat_picker.dart b/lib/view/pages/share_intent/share_chat_picker.dart index d61e620..48b84eb 100644 --- a/lib/view/pages/share_intent/share_chat_picker.dart +++ b/lib/view/pages/share_intent/share_chat_picker.dart @@ -100,7 +100,6 @@ class ShareChatPicker extends StatelessWidget { if (rooms == null) return const SizedBox.shrink(); final sorted = rooms .sortBy( - lastActivity: true, favoritesToTop: talkSettings.sortFavoritesToTop, unreadToTop: talkSettings.sortUnreadToTop, ) diff --git a/lib/view/pages/talk/chat_list.dart b/lib/view/pages/talk/chat_list.dart index d249b64..223960f 100644 --- a/lib/view/pages/talk/chat_list.dart +++ b/lib/view/pages/talk/chat_list.dart @@ -162,7 +162,6 @@ class _ChatListViewState extends State<_ChatListView> { .val() .talkSettings; final sorted = rooms.sortBy( - lastActivity: true, favoritesToTop: talkSettings.sortFavoritesToTop, unreadToTop: talkSettings.sortUnreadToTop, );