This commit is contained in:
Leon Bösche
2025-12-16 22:26:05 +01:00
parent 18f41ba2b3
commit 8b5a5f9b7e
4 changed files with 110 additions and 34 deletions

View File

@@ -13,6 +13,7 @@ class FileBrowserBloc extends Bloc<FileBrowserEvent, FileBrowserState> {
int _currentPage = 1;
int _pageSize = 20;
String _sortBy = 'name';
bool _isAscending = true;
FileBrowserBloc(this._fileService) : super(DirectoryInitial()) {
on<LoadDirectory>(_onLoadDirectory);
@@ -36,7 +37,7 @@ class FileBrowserBloc extends Bloc<FileBrowserEvent, FileBrowserState> {
_currentPath = event.path;
try {
final files = await _fileService.getFiles(event.orgId, event.path);
_currentFiles = _sortFiles(files, _sortBy);
_currentFiles = _sortFiles(files, _sortBy, _isAscending);
_filteredFiles = _currentFiles;
_currentPage = 1;
if (files.isEmpty) {
@@ -66,7 +67,8 @@ class FileBrowserBloc extends Bloc<FileBrowserEvent, FileBrowserState> {
void _onApplySort(ApplySort event, Emitter<FileBrowserState> emit) {
_sortBy = event.sortBy;
_currentFiles = _sortFiles(_currentFiles, _sortBy);
_isAscending = event.isAscending;
_currentFiles = _sortFiles(_currentFiles, _sortBy, _isAscending);
_filteredFiles = _currentFiles
.where((f) => f.name.toLowerCase().contains(''))
.toList(); // Re-apply filter if any, but since filter is separate, perhaps need to track filter
@@ -111,6 +113,7 @@ class FileBrowserBloc extends Bloc<FileBrowserEvent, FileBrowserState> {
_currentPage = 1;
_pageSize = 20;
_sortBy = 'name';
_isAscending = true;
}
void _onLoadPage(LoadPage event, Emitter<FileBrowserState> emit) {
@@ -155,6 +158,7 @@ class FileBrowserBloc extends Bloc<FileBrowserEvent, FileBrowserState> {
pageSize: _pageSize,
totalPages: totalPages,
sortBy: _sortBy,
isAscending: _isAscending,
),
);
}
@@ -165,24 +169,40 @@ class FileBrowserBloc extends Bloc<FileBrowserEvent, FileBrowserState> {
return _filteredFiles.sublist(start, end.clamp(0, _filteredFiles.length));
}
List<FileItem> _sortFiles(List<FileItem> files, String sortBy) {
List<FileItem> _sortFiles(
List<FileItem> files,
String sortBy,
bool isAscending,
) {
final sorted = List<FileItem>.from(files);
sorted.sort((a, b) {
switch (sortBy) {
case 'name':
return a.name.compareTo(b.name);
return isAscending
? a.name.compareTo(b.name)
: b.name.compareTo(a.name);
case 'date':
return b.lastModified.compareTo(a.lastModified);
return isAscending
? a.lastModified.compareTo(b.lastModified)
: b.lastModified.compareTo(a.lastModified);
case 'size':
return b.size.compareTo(a.size);
return isAscending
? a.size.compareTo(b.size)
: b.size.compareTo(a.size);
case 'type':
// Folders before files
if (a.type == FileType.folder && b.type == FileType.file) return -1;
if (a.type == FileType.file && b.type == FileType.folder) return 1;
// Folders before files if ascending, else files before folders
int typeCompare = isAscending
? a.type.index.compareTo(b.type.index)
: b.type.index.compareTo(a.type.index);
if (typeCompare != 0) return typeCompare;
// Within same type, sort by name
return a.name.compareTo(b.name);
return isAscending
? a.name.compareTo(b.name)
: b.name.compareTo(a.name);
default:
return a.name.compareTo(b.name);
return isAscending
? a.name.compareTo(b.name)
: b.name.compareTo(a.name);
}
});
return sorted;

View File

@@ -30,11 +30,12 @@ class RefreshDirectory extends FileBrowserEvent {}
class ApplySort extends FileBrowserEvent {
final String sortBy; // name, date, size, type
final bool isAscending;
const ApplySort(this.sortBy);
const ApplySort(this.sortBy, {this.isAscending = true});
@override
List<Object> get props => [sortBy];
List<Object> get props => [sortBy, isAscending];
}
class ApplyFilter extends FileBrowserEvent {

View File

@@ -32,6 +32,7 @@ class DirectoryLoaded extends FileBrowserState {
final int pageSize;
final int totalPages;
final String sortBy;
final bool isAscending;
const DirectoryLoaded({
required this.files,
@@ -43,6 +44,7 @@ class DirectoryLoaded extends FileBrowserState {
required this.pageSize,
required this.totalPages,
required this.sortBy,
required this.isAscending,
});
@override
@@ -56,6 +58,7 @@ class DirectoryLoaded extends FileBrowserState {
pageSize,
totalPages,
sortBy,
isAscending,
];
}

View File

@@ -213,36 +213,88 @@ class _FileExplorerState extends State<FileExplorer> {
}
},
),
const SizedBox(width: 860),
const SizedBox(width: 800),
BlocBuilder<FileBrowserBloc, FileBrowserState>(
builder: (context, state) {
String currentSort = 'name';
bool isAscending = true;
if (state is DirectoryLoaded) {
currentSort = state.sortBy;
isAscending = state.isAscending;
}
return DropdownButton<String>(
value: currentSort,
dropdownColor: AppTheme.accentColor.withAlpha(160),
return Row(
children: [
PopupMenuButton<String>(
color: AppTheme.accentColor.withAlpha(200),
position: PopupMenuPosition.under,
offset: const Offset(48, 8),
itemBuilder: (BuildContext context) => [
const PopupMenuItem(
value: 'name',
child: Text('Name'),
),
const PopupMenuItem(
value: 'date',
child: Text('Date'),
),
const PopupMenuItem(
value: 'size',
child: Text('Size'),
),
const PopupMenuItem(
value: 'type',
child: Text('Type'),
),
],
onSelected: (value) {
context.read<FileBrowserBloc>().add(
ApplySort(value, isAscending: isAscending),
);
},
child: Row(
children: [
Icon(
Icons.arrow_drop_down,
color: AppTheme.primaryText,
),
const SizedBox(width: 4),
Text(
currentSort == 'name'
? 'Name'
: currentSort == 'date'
? 'Date'
: currentSort == 'size'
? 'Size'
: 'Type',
style: const TextStyle(
color: AppTheme.primaryText,
fontSize: 14,
),
underline: Container(), // Remove underline
items: const [
DropdownMenuItem(value: 'name', child: Text('Name')),
DropdownMenuItem(value: 'date', child: Text('Date')),
DropdownMenuItem(value: 'size', child: Text('Size')),
DropdownMenuItem(value: 'type', child: Text('Type')),
),
],
onChanged: (value) {
if (value != null) {
),
),
const SizedBox(width: 8),
IconButton(
icon: Icon(
isAscending
? Icons.arrow_upward
: Icons.arrow_downward,
color: AppTheme.accentColor,
),
onPressed: () {
context.read<FileBrowserBloc>().add(
ApplySort(value),
ApplySort(
currentSort,
isAscending: !isAscending,
),
);
}
},
),
],
);
},
),