diff --git a/CHANGELOG.md b/CHANGELOG.md index 184731c0e..4d82bc55a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ### Added - Viewer: display more items in tag/copy/move quick action choosers +- Collection: sort by duration ### Changed diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index f7dbac54c..bc217fb55 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -723,6 +723,7 @@ "sortBySize": "By size", "sortByAlbumFileName": "By album & file name", "sortByRating": "By rating", + "sortByDuration": "By duration", "sortOrderNewestFirst": "Newest first", "sortOrderOldestFirst": "Oldest first", @@ -732,6 +733,8 @@ "sortOrderLowestFirst": "Lowest first", "sortOrderLargestFirst": "Largest first", "sortOrderSmallestFirst": "Smallest first", + "sortOrderShortestFirst": "Shortest first", + "sortOrderLongestFirst": "Longest first", "albumGroupTier": "By tier", "albumGroupType": "By type", diff --git a/lib/model/entry/sort.dart b/lib/model/entry/sort.dart index f15521bc0..5cf6aa267 100644 --- a/lib/model/entry/sort.dart +++ b/lib/model/entry/sort.dart @@ -35,4 +35,12 @@ class AvesEntrySort { final c = (b.sizeBytes ?? 0).compareTo(a.sizeBytes ?? 0); return c != 0 ? c : compareByDate(a, b); } + + // compare by: + // 1) duration descending + // 2) date descending + static int compareByDuration(AvesEntry a, AvesEntry b) { + final c = (b.durationMillis ?? 0).compareTo(a.durationMillis ?? 0); + return c != 0 ? c : compareByDate(a, b); + } } diff --git a/lib/model/source/collection_lens.dart b/lib/model/source/collection_lens.dart index e6329dbd7..d0f8d88f0 100644 --- a/lib/model/source/collection_lens.dart +++ b/lib/model/source/collection_lens.dart @@ -161,6 +161,7 @@ class CollectionLens with ChangeNotifier { case EntrySortFactor.rating: return !filters.any((f) => f is RatingFilter); case EntrySortFactor.size: + case EntrySortFactor.duration: return false; } } @@ -261,6 +262,8 @@ class CollectionLens with ChangeNotifier { _filteredSortedEntries.sort(AvesEntrySort.compareByRating); case EntrySortFactor.size: _filteredSortedEntries.sort(AvesEntrySort.compareBySize); + case EntrySortFactor.duration: + _filteredSortedEntries.sort(AvesEntrySort.compareByDuration); } if (sortReverse) { _filteredSortedEntries = _filteredSortedEntries.reversed.toList(); @@ -294,6 +297,7 @@ class CollectionLens with ChangeNotifier { case EntrySortFactor.rating: sections = groupBy(_filteredSortedEntries, (entry) => EntryRatingSectionKey(entry.rating)); case EntrySortFactor.size: + case EntrySortFactor.duration: sections = Map.fromEntries([ MapEntry(const SectionKey(), _filteredSortedEntries), ]); diff --git a/lib/theme/icons.dart b/lib/theme/icons.dart index 8397cf412..485ffa8e2 100644 --- a/lib/theme/icons.dart +++ b/lib/theme/icons.dart @@ -28,6 +28,7 @@ class AIcons { static const descriptionUntitled = Icons.comments_disabled_outlined; static const disc = Icons.fiber_manual_record; static const display = Icons.light_mode_outlined; + static const duration = Icons.timelapse_outlined; static const error = Icons.error_outline; static const explorer = Icons.account_tree_outlined; static const folder = Icons.folder_outlined; diff --git a/lib/view/src/source/sort.dart b/lib/view/src/source/sort.dart index 56188edd2..800cde2a3 100644 --- a/lib/view/src/source/sort.dart +++ b/lib/view/src/source/sort.dart @@ -11,6 +11,7 @@ extension ExtraEntrySortFactorView on EntrySortFactor { EntrySortFactor.name => l10n.sortByAlbumFileName, EntrySortFactor.rating => l10n.sortByRating, EntrySortFactor.size => l10n.sortBySize, + EntrySortFactor.duration => l10n.sortByDuration, }; } @@ -20,6 +21,7 @@ extension ExtraEntrySortFactorView on EntrySortFactor { EntrySortFactor.name => AIcons.name, EntrySortFactor.rating => AIcons.rating, EntrySortFactor.size => AIcons.size, + EntrySortFactor.duration => AIcons.duration, }; } @@ -30,6 +32,7 @@ extension ExtraEntrySortFactorView on EntrySortFactor { EntrySortFactor.name => reverse ? l10n.sortOrderZtoA : l10n.sortOrderAtoZ, EntrySortFactor.rating => reverse ? l10n.sortOrderLowestFirst : l10n.sortOrderHighestFirst, EntrySortFactor.size => reverse ? l10n.sortOrderSmallestFirst : l10n.sortOrderLargestFirst, + EntrySortFactor.duration => reverse ? l10n.sortOrderShortestFirst : l10n.sortOrderLongestFirst, }; } } diff --git a/lib/widgets/collection/app_bar.dart b/lib/widgets/collection/app_bar.dart index d6b019281..55a1f56ec 100644 --- a/lib/widgets/collection/app_bar.dart +++ b/lib/widgets/collection/app_bar.dart @@ -79,6 +79,7 @@ class _CollectionAppBarState extends State with SingleTickerPr EntrySortFactor.size, EntrySortFactor.name, EntrySortFactor.rating, + EntrySortFactor.duration, ]; static const _groupOptions = [ diff --git a/lib/widgets/collection/collection_grid.dart b/lib/widgets/collection/collection_grid.dart index d4d54012f..e7f2ecfd3 100644 --- a/lib/widgets/collection/collection_grid.dart +++ b/lib/widgets/collection/collection_grid.dart @@ -697,6 +697,7 @@ class _CollectionScrollViewState extends State<_CollectionScrollView> with Widge addAlbums(collection, sectionLayouts, crumbs); case EntrySortFactor.rating: case EntrySortFactor.size: + case EntrySortFactor.duration: break; } return crumbs; diff --git a/lib/widgets/collection/draggable_thumb_label.dart b/lib/widgets/collection/draggable_thumb_label.dart index a48a6dadb..548dad5bd 100644 --- a/lib/widgets/collection/draggable_thumb_label.dart +++ b/lib/widgets/collection/draggable_thumb_label.dart @@ -57,6 +57,10 @@ class CollectionDraggableThumbLabel extends StatelessWidget { return [ if (entry.sizeBytes != null) formatFileSize(context.locale, entry.sizeBytes!, round: 0), ]; + case EntrySortFactor.duration: + return [ + if (entry.durationMillis != null) entry.durationText, + ]; } }, ); diff --git a/lib/widgets/collection/grid/headers/any.dart b/lib/widgets/collection/grid/headers/any.dart index f2f423829..213b7acf8 100644 --- a/lib/widgets/collection/grid/headers/any.dart +++ b/lib/widgets/collection/grid/headers/any.dart @@ -66,6 +66,7 @@ class CollectionSectionHeader extends StatelessWidget { selectable: selectable, ); case EntrySortFactor.size: + case EntrySortFactor.duration: break; } return null; diff --git a/plugins/aves_model/lib/src/source/enums.dart b/plugins/aves_model/lib/src/source/enums.dart index de1b1faef..9f9d65e4d 100644 --- a/plugins/aves_model/lib/src/source/enums.dart +++ b/plugins/aves_model/lib/src/source/enums.dart @@ -4,7 +4,7 @@ enum ChipSortFactor { date, name, count, size } enum AlbumChipGroupFactor { none, importance, mimeType, volume } -enum EntrySortFactor { date, name, rating, size } +enum EntrySortFactor { date, name, rating, size, duration } enum EntryGroupFactor { none, album, month, day }