diff --git a/lib/widgets/file_list_view.dart b/lib/widgets/file_list_view.dart index d6ddccec..b946af69 100644 --- a/lib/widgets/file_list_view.dart +++ b/lib/widgets/file_list_view.dart @@ -75,6 +75,7 @@ class FileListView extends HookConsumerWidget { final poolsAsync = ref.watch(poolsProvider); final isSelectionMode = useState(false); final selectedFileIds = useState>({}); + final currentVisibleItems = useState>([]); final query = useState(null); final order = useState('date'); final orderDesc = useState(true); @@ -140,6 +141,7 @@ class FileListView extends HookConsumerWidget { viewMode, isSelectionMode, selectedFileIds, + currentVisibleItems, ), ), _ => PagingHelperSliverView( @@ -162,6 +164,7 @@ class FileListView extends HookConsumerWidget { viewMode, isSelectionMode, selectedFileIds, + currentVisibleItems, ), ), }; @@ -455,6 +458,48 @@ class FileListView extends HookConsumerWidget { }, child: const Text('Cancel'), ), + const Gap(12), + OutlinedButton( + onPressed: () { + final allIds = + currentVisibleItems.value + .expand( + (item) => item.maybeMap( + file: (f) => [f.fileIndex.id], + unindexedFile: (u) => [u.file.id], + orElse: () => [], + ), + ) + .toSet(); + + if (allIds + .difference(selectedFileIds.value) + .isEmpty) { + // All items are selected, deselect all + selectedFileIds.value.clear(); + } else { + // Select all visible items + selectedFileIds.value = allIds; + } + }, + child: Text( + currentVisibleItems.value.isEmpty + ? 'Select All' + : currentVisibleItems.value + .expand( + (item) => item.maybeMap( + file: (f) => [f.fileIndex.id], + unindexedFile: (u) => [u.file.id], + orElse: () => [], + ), + ) + .toSet() + .difference(selectedFileIds.value) + .isEmpty + ? 'Deselect All' + : 'Select All', + ), + ), const Spacer(), Text('${selectedFileIds.value.length} selected'), const Spacer(), @@ -522,7 +567,9 @@ class FileListView extends HookConsumerWidget { ValueNotifier currentViewMode, ValueNotifier isSelectionMode, ValueNotifier> selectedFileIds, + ValueNotifier> currentVisibleItems, ) { + currentVisibleItems.value = items; return switch (currentViewMode.value) { // Waterfall mode FileListViewMode.waterfall => SliverMasonryGrid( @@ -965,7 +1012,9 @@ class FileListView extends HookConsumerWidget { ValueNotifier currentViewMode, ValueNotifier isSelectionMode, ValueNotifier> selectedFileIds, + ValueNotifier> currentVisibleItems, ) { + currentVisibleItems.value = items; return switch (currentViewMode.value) { // Waterfall mode FileListViewMode.waterfall => SliverMasonryGrid(