sort
This commit is contained in:
@@ -13,6 +13,7 @@ class FileBrowserBloc extends Bloc<FileBrowserEvent, FileBrowserState> {
|
|||||||
int _currentPage = 1;
|
int _currentPage = 1;
|
||||||
int _pageSize = 20;
|
int _pageSize = 20;
|
||||||
String _sortBy = 'name';
|
String _sortBy = 'name';
|
||||||
|
bool _isAscending = true;
|
||||||
|
|
||||||
FileBrowserBloc(this._fileService) : super(DirectoryInitial()) {
|
FileBrowserBloc(this._fileService) : super(DirectoryInitial()) {
|
||||||
on<LoadDirectory>(_onLoadDirectory);
|
on<LoadDirectory>(_onLoadDirectory);
|
||||||
@@ -36,7 +37,7 @@ class FileBrowserBloc extends Bloc<FileBrowserEvent, FileBrowserState> {
|
|||||||
_currentPath = event.path;
|
_currentPath = event.path;
|
||||||
try {
|
try {
|
||||||
final files = await _fileService.getFiles(event.orgId, event.path);
|
final files = await _fileService.getFiles(event.orgId, event.path);
|
||||||
_currentFiles = _sortFiles(files, _sortBy);
|
_currentFiles = _sortFiles(files, _sortBy, _isAscending);
|
||||||
_filteredFiles = _currentFiles;
|
_filteredFiles = _currentFiles;
|
||||||
_currentPage = 1;
|
_currentPage = 1;
|
||||||
if (files.isEmpty) {
|
if (files.isEmpty) {
|
||||||
@@ -66,7 +67,8 @@ class FileBrowserBloc extends Bloc<FileBrowserEvent, FileBrowserState> {
|
|||||||
|
|
||||||
void _onApplySort(ApplySort event, Emitter<FileBrowserState> emit) {
|
void _onApplySort(ApplySort event, Emitter<FileBrowserState> emit) {
|
||||||
_sortBy = event.sortBy;
|
_sortBy = event.sortBy;
|
||||||
_currentFiles = _sortFiles(_currentFiles, _sortBy);
|
_isAscending = event.isAscending;
|
||||||
|
_currentFiles = _sortFiles(_currentFiles, _sortBy, _isAscending);
|
||||||
_filteredFiles = _currentFiles
|
_filteredFiles = _currentFiles
|
||||||
.where((f) => f.name.toLowerCase().contains(''))
|
.where((f) => f.name.toLowerCase().contains(''))
|
||||||
.toList(); // Re-apply filter if any, but since filter is separate, perhaps need to track filter
|
.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;
|
_currentPage = 1;
|
||||||
_pageSize = 20;
|
_pageSize = 20;
|
||||||
_sortBy = 'name';
|
_sortBy = 'name';
|
||||||
|
_isAscending = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onLoadPage(LoadPage event, Emitter<FileBrowserState> emit) {
|
void _onLoadPage(LoadPage event, Emitter<FileBrowserState> emit) {
|
||||||
@@ -155,6 +158,7 @@ class FileBrowserBloc extends Bloc<FileBrowserEvent, FileBrowserState> {
|
|||||||
pageSize: _pageSize,
|
pageSize: _pageSize,
|
||||||
totalPages: totalPages,
|
totalPages: totalPages,
|
||||||
sortBy: _sortBy,
|
sortBy: _sortBy,
|
||||||
|
isAscending: _isAscending,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -165,24 +169,40 @@ class FileBrowserBloc extends Bloc<FileBrowserEvent, FileBrowserState> {
|
|||||||
return _filteredFiles.sublist(start, end.clamp(0, _filteredFiles.length));
|
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);
|
final sorted = List<FileItem>.from(files);
|
||||||
sorted.sort((a, b) {
|
sorted.sort((a, b) {
|
||||||
switch (sortBy) {
|
switch (sortBy) {
|
||||||
case 'name':
|
case 'name':
|
||||||
return a.name.compareTo(b.name);
|
return isAscending
|
||||||
|
? a.name.compareTo(b.name)
|
||||||
|
: b.name.compareTo(a.name);
|
||||||
case 'date':
|
case 'date':
|
||||||
return b.lastModified.compareTo(a.lastModified);
|
return isAscending
|
||||||
|
? a.lastModified.compareTo(b.lastModified)
|
||||||
|
: b.lastModified.compareTo(a.lastModified);
|
||||||
case 'size':
|
case 'size':
|
||||||
return b.size.compareTo(a.size);
|
return isAscending
|
||||||
|
? a.size.compareTo(b.size)
|
||||||
|
: b.size.compareTo(a.size);
|
||||||
case 'type':
|
case 'type':
|
||||||
// Folders before files
|
// Folders before files if ascending, else files before folders
|
||||||
if (a.type == FileType.folder && b.type == FileType.file) return -1;
|
int typeCompare = isAscending
|
||||||
if (a.type == FileType.file && b.type == FileType.folder) return 1;
|
? 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
|
// 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:
|
default:
|
||||||
return a.name.compareTo(b.name);
|
return isAscending
|
||||||
|
? a.name.compareTo(b.name)
|
||||||
|
: b.name.compareTo(a.name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return sorted;
|
return sorted;
|
||||||
|
|||||||
@@ -30,11 +30,12 @@ class RefreshDirectory extends FileBrowserEvent {}
|
|||||||
|
|
||||||
class ApplySort extends FileBrowserEvent {
|
class ApplySort extends FileBrowserEvent {
|
||||||
final String sortBy; // name, date, size, type
|
final String sortBy; // name, date, size, type
|
||||||
|
final bool isAscending;
|
||||||
|
|
||||||
const ApplySort(this.sortBy);
|
const ApplySort(this.sortBy, {this.isAscending = true});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [sortBy];
|
List<Object> get props => [sortBy, isAscending];
|
||||||
}
|
}
|
||||||
|
|
||||||
class ApplyFilter extends FileBrowserEvent {
|
class ApplyFilter extends FileBrowserEvent {
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class DirectoryLoaded extends FileBrowserState {
|
|||||||
final int pageSize;
|
final int pageSize;
|
||||||
final int totalPages;
|
final int totalPages;
|
||||||
final String sortBy;
|
final String sortBy;
|
||||||
|
final bool isAscending;
|
||||||
|
|
||||||
const DirectoryLoaded({
|
const DirectoryLoaded({
|
||||||
required this.files,
|
required this.files,
|
||||||
@@ -43,6 +44,7 @@ class DirectoryLoaded extends FileBrowserState {
|
|||||||
required this.pageSize,
|
required this.pageSize,
|
||||||
required this.totalPages,
|
required this.totalPages,
|
||||||
required this.sortBy,
|
required this.sortBy,
|
||||||
|
required this.isAscending,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -56,6 +58,7 @@ class DirectoryLoaded extends FileBrowserState {
|
|||||||
pageSize,
|
pageSize,
|
||||||
totalPages,
|
totalPages,
|
||||||
sortBy,
|
sortBy,
|
||||||
|
isAscending,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -213,36 +213,88 @@ class _FileExplorerState extends State<FileExplorer> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(width: 860),
|
const SizedBox(width: 800),
|
||||||
|
|
||||||
BlocBuilder<FileBrowserBloc, FileBrowserState>(
|
BlocBuilder<FileBrowserBloc, FileBrowserState>(
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
String currentSort = 'name';
|
String currentSort = 'name';
|
||||||
|
bool isAscending = true;
|
||||||
if (state is DirectoryLoaded) {
|
if (state is DirectoryLoaded) {
|
||||||
currentSort = state.sortBy;
|
currentSort = state.sortBy;
|
||||||
|
isAscending = state.isAscending;
|
||||||
}
|
}
|
||||||
return DropdownButton<String>(
|
return Row(
|
||||||
value: currentSort,
|
children: [
|
||||||
dropdownColor: AppTheme.accentColor.withAlpha(160),
|
PopupMenuButton<String>(
|
||||||
|
color: AppTheme.accentColor.withAlpha(200),
|
||||||
|
|
||||||
style: const TextStyle(
|
position: PopupMenuPosition.under,
|
||||||
color: AppTheme.primaryText,
|
offset: const Offset(48, 8),
|
||||||
fontSize: 14,
|
itemBuilder: (BuildContext context) => [
|
||||||
),
|
const PopupMenuItem(
|
||||||
underline: Container(), // Remove underline
|
value: 'name',
|
||||||
items: const [
|
|
||||||
DropdownMenuItem(value: 'name', child: Text('Name')),
|
child: Text('Name'),
|
||||||
DropdownMenuItem(value: 'date', child: Text('Date')),
|
),
|
||||||
DropdownMenuItem(value: 'size', child: Text('Size')),
|
const PopupMenuItem(
|
||||||
DropdownMenuItem(value: 'type', child: Text('Type')),
|
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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
isAscending
|
||||||
|
? Icons.arrow_upward
|
||||||
|
: Icons.arrow_downward,
|
||||||
|
color: AppTheme.accentColor,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
context.read<FileBrowserBloc>().add(
|
||||||
|
ApplySort(
|
||||||
|
currentSort,
|
||||||
|
isAscending: !isAscending,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
onChanged: (value) {
|
|
||||||
if (value != null) {
|
|
||||||
context.read<FileBrowserBloc>().add(
|
|
||||||
ApplySort(value),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user