💄 File list loading indicator

This commit is contained in:
2025-11-17 23:10:13 +08:00
parent 256024fb46
commit b233f9a410

View File

@@ -62,6 +62,14 @@ class FileListView extends HookConsumerWidget {
if (usage == null) return const SizedBox.shrink(); if (usage == null) return const SizedBox.shrink();
final isRefreshing = ref.watch(
mode.value == FileListMode.normal
? cloudFileListNotifierProvider.select((value) => value.isLoading)
: unindexedFileListNotifierProvider.select(
(value) => value.isLoading,
),
);
final bodyWidget = switch (mode.value) { final bodyWidget = switch (mode.value) {
FileListMode.unindexed => PagingHelperSliverView( FileListMode.unindexed => PagingHelperSliverView(
provider: unindexedFileListNotifierProvider, provider: unindexedFileListNotifierProvider,
@@ -141,10 +149,13 @@ class FileListView extends HookConsumerWidget {
child: DropdownButton2<SnFilePool>( child: DropdownButton2<SnFilePool>(
value: selectedPool.value, value: selectedPool.value,
items: unindexedItems, items: unindexedItems,
onChanged: (value) { onChanged:
selectedPool.value = value; isRefreshing
unindexedNotifier.setPool(value?.id); ? null
}, : (value) {
selectedPool.value = value;
unindexedNotifier.setPool(value?.id);
},
customButton: Container( customButton: Container(
height: 28, height: 28,
width: 160, width: 160,
@@ -284,116 +295,123 @@ class FileListView extends HookConsumerWidget {
child: Column( child: Column(
children: [ children: [
const Gap(8), const Gap(8),
SizedBox( Card(
height: 64, child: Padding(
child: Card( padding: const EdgeInsets.all(16),
child: Padding( child: Row(
padding: const EdgeInsets.all(16), children: [
child: Row( IconButton(
children: [ icon: Icon(
IconButton( mode.value == FileListMode.unindexed
icon: Icon( ? Symbols.inventory_2
mode.value == FileListMode.unindexed : currentPath.value != '/'
? Symbols.inventory_2 ? Symbols.arrow_back
: currentPath.value != '/' : Symbols.folder,
? Symbols.arrow_back
: Symbols.folder,
),
onPressed: () {
if (mode.value == FileListMode.unindexed) {
mode.value = FileListMode.normal;
currentPath.value = '/';
} else {
final pathParts =
currentPath.value
.split('/')
.where((part) => part.isNotEmpty)
.toList();
if (pathParts.isNotEmpty) {
pathParts.removeLast();
currentPath.value =
pathParts.isEmpty
? '/'
: '/${pathParts.join('/')}';
}
}
},
visualDensity: const VisualDensity(
horizontal: -4,
vertical: -4,
),
), ),
const Gap(8), onPressed:
Expanded(child: pathContent), isRefreshing
IconButton( ? null
icon: Icon( : () {
if (mode.value == FileListMode.unindexed) {
mode.value = FileListMode.normal;
currentPath.value = '/';
} else {
final pathParts =
currentPath.value
.split('/')
.where((part) => part.isNotEmpty)
.toList();
if (pathParts.isNotEmpty) {
pathParts.removeLast();
currentPath.value =
pathParts.isEmpty
? '/'
: '/${pathParts.join('/')}';
}
}
},
visualDensity: const VisualDensity(
horizontal: -4,
vertical: -4,
),
),
const Gap(8),
Expanded(
child: AbsorbPointer(
absorbing: isRefreshing,
child: pathContent,
),
),
IconButton(
icon: Icon(
viewMode.value == FileListViewMode.list
? Symbols.view_module
: Symbols.list,
),
onPressed:
() =>
viewMode.value =
viewMode.value == FileListViewMode.list
? FileListViewMode.waterfall
: FileListViewMode.list,
tooltip:
viewMode.value == FileListViewMode.list viewMode.value == FileListViewMode.list
? Symbols.view_module ? 'Switch to Waterfall View'
: Symbols.list, : 'Switch to List View',
), visualDensity: const VisualDensity(
horizontal: -4,
vertical: -4,
),
),
if (mode.value == FileListMode.normal)
IconButton(
icon: const Icon(Symbols.create_new_folder),
onPressed: onPressed:
() => () =>
viewMode.value = onShowCreateDirectory(ref.context, currentPath),
viewMode.value == FileListViewMode.list tooltip: 'Create Directory',
? FileListViewMode.waterfall
: FileListViewMode.list,
tooltip:
viewMode.value == FileListViewMode.list
? 'Switch to Waterfall View'
: 'Switch to List View',
visualDensity: const VisualDensity( visualDensity: const VisualDensity(
horizontal: -4, horizontal: -4,
vertical: -4, vertical: -4,
), ),
), ),
if (mode.value == FileListMode.normal) if (mode.value == FileListMode.unindexed)
IconButton(
icon: const Icon(Symbols.create_new_folder),
onPressed:
() => onShowCreateDirectory(
ref.context,
currentPath,
),
tooltip: 'Create Directory',
visualDensity: const VisualDensity(
horizontal: -4,
vertical: -4,
),
),
if (mode.value == FileListMode.unindexed)
IconButton(
icon: Icon(
recycled.value
? Symbols.delete_forever
: Symbols.restore_from_trash,
),
onPressed: () {
recycled.value = !recycled.value;
unindexedNotifier.setRecycled(recycled.value);
},
tooltip:
recycled.value
? 'Show Active Files'
: 'Show Recycle Bin',
visualDensity: const VisualDensity(
horizontal: -4,
vertical: -4,
),
),
IconButton( IconButton(
icon: const Icon(Symbols.upload_file), icon: Icon(
onPressed: onPickAndUpload, recycled.value
tooltip: 'Upload File', ? Symbols.delete_forever
: Symbols.restore_from_trash,
),
onPressed: () {
recycled.value = !recycled.value;
unindexedNotifier.setRecycled(recycled.value);
},
tooltip:
recycled.value
? 'Show Active Files'
: 'Show Recycle Bin',
visualDensity: const VisualDensity( visualDensity: const VisualDensity(
horizontal: -4, horizontal: -4,
vertical: -4, vertical: -4,
), ),
), ),
], IconButton(
), icon: const Icon(Symbols.upload_file),
onPressed: onPickAndUpload,
tooltip: 'Upload File',
visualDensity: const VisualDensity(
horizontal: -4,
vertical: -4,
),
),
],
), ),
).padding(horizontal: 8), ),
), ).padding(horizontal: 8),
if (isRefreshing)
const LinearProgressIndicator(
minHeight: 4,
).padding(horizontal: 16, top: 6, bottom: 4),
const Gap(8), const Gap(8),
if (mode.value == FileListMode.normal && currentPath.value == '/') if (mode.value == FileListMode.normal && currentPath.value == '/')
_buildUnindexedFilesEntry(ref).padding(bottom: 12), _buildUnindexedFilesEntry(ref).padding(bottom: 12),