fourth commit

This commit is contained in:
Leon Bösche
2025-12-16 22:11:15 +01:00
parent 6207a99718
commit 18f41ba2b3
6 changed files with 270 additions and 48 deletions

View File

@@ -154,6 +154,7 @@ class FileBrowserBloc extends Bloc<FileBrowserEvent, FileBrowserState> {
currentPage: _currentPage,
pageSize: _pageSize,
totalPages: totalPages,
sortBy: _sortBy,
),
);
}
@@ -174,6 +175,12 @@ class FileBrowserBloc extends Bloc<FileBrowserEvent, FileBrowserState> {
return b.lastModified.compareTo(a.lastModified);
case 'size':
return 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;
// Within same type, sort by name
return a.name.compareTo(b.name);
default:
return a.name.compareTo(b.name);
}

View File

@@ -29,7 +29,7 @@ class NavigateToFolder extends FileBrowserEvent {
class RefreshDirectory extends FileBrowserEvent {}
class ApplySort extends FileBrowserEvent {
final String sortBy; // name, date, size
final String sortBy; // name, date, size, type
const ApplySort(this.sortBy);

View File

@@ -31,6 +31,7 @@ class DirectoryLoaded extends FileBrowserState {
final int currentPage;
final int pageSize;
final int totalPages;
final String sortBy;
const DirectoryLoaded({
required this.files,
@@ -41,6 +42,7 @@ class DirectoryLoaded extends FileBrowserState {
required this.currentPage,
required this.pageSize,
required this.totalPages,
required this.sortBy,
});
@override
@@ -53,6 +55,7 @@ class DirectoryLoaded extends FileBrowserState {
currentPage,
pageSize,
totalPages,
sortBy,
];
}

View File

@@ -120,7 +120,12 @@ class _FileExplorerState extends State<FileExplorer> {
},
child: const Text(
'Create',
style: TextStyle(color: AppTheme.accentColor),
style: TextStyle(
color: AppTheme.accentColor,
decoration: TextDecoration.underline,
decorationColor: AppTheme.accentColor,
decorationThickness: 1.5,
),
),
),
],
@@ -180,31 +185,68 @@ class _FileExplorerState extends State<FileExplorer> {
curve: Curves.easeInOut,
child: Padding(
padding: const EdgeInsets.only(top: 2),
child: IconButton(
icon: Icon(
_isSearching ? Icons.close : Icons.search,
color: AppTheme.accentColor,
),
onPressed: () {
if (_isSearching) {
setState(() {
_showField = false;
_isSearching = false;
_searchController.clear();
_searchQuery = '';
context.read<FileBrowserBloc>().add(ApplyFilter(''));
});
} else {
setState(() {
_isSearching = true;
});
Future.delayed(const Duration(milliseconds: 150), () {
setState(() {
_showField = true;
});
});
}
},
child: Row(
children: [
IconButton(
icon: Icon(
_isSearching ? Icons.close : Icons.search,
color: AppTheme.accentColor,
),
onPressed: () {
if (_isSearching) {
setState(() {
_showField = false;
_isSearching = false;
_searchController.clear();
_searchQuery = '';
context.read<FileBrowserBloc>().add(ApplyFilter(''));
});
} else {
setState(() {
_isSearching = true;
});
Future.delayed(const Duration(milliseconds: 150), () {
setState(() {
_showField = true;
});
});
}
},
),
const SizedBox(width: 860),
BlocBuilder<FileBrowserBloc, FileBrowserState>(
builder: (context, state) {
String currentSort = 'name';
if (state is DirectoryLoaded) {
currentSort = state.sortBy;
}
return DropdownButton<String>(
value: currentSort,
dropdownColor: AppTheme.accentColor.withAlpha(160),
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) {
context.read<FileBrowserBloc>().add(
ApplySort(value),
);
}
},
);
},
),
],
),
),
),
@@ -259,7 +301,9 @@ class _FileExplorerState extends State<FileExplorer> {
return BlocBuilder<FileBrowserBloc, FileBrowserState>(
builder: (context, state) {
if (state is DirectoryLoading) {
return const Center(child: CircularProgressIndicator());
return Center(
child: CircularProgressIndicator(color: AppTheme.accentColor),
);
}
if (state is DirectoryError) {
return Center(
@@ -517,9 +561,9 @@ class _FileExplorerState extends State<FileExplorer> {
const SizedBox(height: 16),
Expanded(
child: ListView.builder(
itemCount: state.filteredFiles.length,
itemCount: state.paginatedFiles.length,
itemBuilder: (context, index) {
final file = state.filteredFiles[index];
final file = state.paginatedFiles[index];
final isSelected = _selectedFilePath == file.path;
return GestureDetector(
onTap: () {
@@ -611,6 +655,48 @@ class _FileExplorerState extends State<FileExplorer> {
},
),
),
// Pagination controls
if (state.totalPages > 1) ...[
const SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
icon: const Icon(
Icons.chevron_left,
color: AppTheme.primaryText,
),
onPressed: state.currentPage > 1
? () {
context.read<FileBrowserBloc>().add(
LoadPage(state.currentPage - 1),
);
}
: null,
),
Text(
'${state.currentPage} / ${state.totalPages}',
style: const TextStyle(
color: AppTheme.primaryText,
fontSize: 16,
),
),
IconButton(
icon: const Icon(
Icons.chevron_right,
color: AppTheme.primaryText,
),
onPressed: state.currentPage < state.totalPages
? () {
context.read<FileBrowserBloc>().add(
LoadPage(state.currentPage + 1),
);
}
: null,
),
],
),
],
],
),
);

View File

@@ -29,6 +29,143 @@ class MockFileRepository implements FileRepository {
size: 512,
lastModified: DateTime.now(),
),
// Add more files for pagination testing
FileItem(
name: 'presentation.pptx',
path: '/presentation.pptx',
type: FileType.file,
size: 2048,
lastModified: DateTime.now(),
),
FileItem(
name: 'data.xlsx',
path: '/data.xlsx',
type: FileType.file,
size: 1024,
lastModified: DateTime.now(),
),
FileItem(
name: 'video.mp4',
path: '/video.mp4',
type: FileType.file,
size: 102400,
lastModified: DateTime.now(),
),
FileItem(
name: 'archive.zip',
path: '/archive.zip',
type: FileType.file,
size: 5120,
lastModified: DateTime.now(),
),
FileItem(
name: 'notes.txt',
path: '/notes.txt',
type: FileType.file,
size: 256,
lastModified: DateTime.now(),
),
FileItem(
name: 'config.json',
path: '/config.json',
type: FileType.file,
size: 128,
lastModified: DateTime.now(),
),
FileItem(
name: 'script.js',
path: '/script.js',
type: FileType.file,
size: 256,
lastModified: DateTime.now(),
),
FileItem(
name: 'styles.css',
path: '/styles.css',
type: FileType.file,
size: 512,
lastModified: DateTime.now(),
),
FileItem(
name: 'index.html',
path: '/index.html',
type: FileType.file,
size: 1024,
lastModified: DateTime.now(),
),
FileItem(
name: 'database.db',
path: '/database.db',
type: FileType.file,
size: 20480,
lastModified: DateTime.now(),
),
FileItem(
name: 'logs',
path: '/logs',
type: FileType.folder,
lastModified: DateTime.now(),
),
FileItem(
name: 'temp',
path: '/temp',
type: FileType.folder,
lastModified: DateTime.now(),
),
FileItem(
name: 'backup',
path: '/backup',
type: FileType.folder,
lastModified: DateTime.now(),
),
FileItem(
name: 'Music',
path: '/Music',
type: FileType.folder,
lastModified: DateTime.now(),
),
FileItem(
name: 'Videos',
path: '/Videos',
type: FileType.folder,
lastModified: DateTime.now(),
),
FileItem(
name: 'Projects',
path: '/Projects',
type: FileType.folder,
lastModified: DateTime.now(),
),
FileItem(
name: 'Downloads',
path: '/Downloads',
type: FileType.folder,
lastModified: DateTime.now(),
),
FileItem(
name: 'Pictures',
path: '/Pictures',
type: FileType.folder,
lastModified: DateTime.now(),
),
FileItem(
name: 'Documents2',
path: '/Documents2',
type: FileType.folder,
lastModified: DateTime.now(),
),
FileItem(
name: 'Archive',
path: '/Archive',
type: FileType.folder,
lastModified: DateTime.now(),
),
FileItem(
name: 'OldFiles',
path: '/OldFiles',
type: FileType.folder,
lastModified: DateTime.now(),
),
];
@override

View File

@@ -105,24 +105,13 @@ class _ModernGlassButtonState extends State<ModernGlassButton>
),
),
child: Center(
child: widget.isLoading
? SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(
AppTheme.primaryText,
),
strokeWidth: 2,
),
)
: DefaultTextStyle(
style: const TextStyle(
color: AppTheme.primaryText,
fontWeight: FontWeight.w600,
),
child: widget.child,
),
child: DefaultTextStyle(
style: const TextStyle(
color: AppTheme.primaryText,
fontWeight: FontWeight.w600,
),
child: widget.child,
),
),
),
),