improved performance and battery usage on older devices
This commit is contained in:
@@ -104,32 +104,43 @@ class FilesSearchResults extends StatelessWidget {
|
||||
Widget _resultList(BuildContext context, List<CacheableFile> combined) {
|
||||
final groups = _groupByParent(combined);
|
||||
final orderedKeys = groups.keys.toList()..sort();
|
||||
final items = <Widget>[];
|
||||
for (final folder in orderedKeys) {
|
||||
final segments = _segmentsOf(folder);
|
||||
items.add(
|
||||
_FolderHeader(
|
||||
folder: folder,
|
||||
onOpen: () {
|
||||
onResultTap?.call();
|
||||
AppRoutes.openFolder(context, segments);
|
||||
},
|
||||
),
|
||||
);
|
||||
for (final file in groups[folder]!) {
|
||||
items.add(
|
||||
FileElement(
|
||||
file,
|
||||
segments,
|
||||
controller.retry,
|
||||
highlight: controller.query,
|
||||
),
|
||||
// Flat (folder header | file) rows built lazily: results can run into
|
||||
// the hundreds and arrive in several batches per query.
|
||||
final rows = <(String, CacheableFile?)>[
|
||||
for (final folder in orderedKeys) ...[
|
||||
(folder, null),
|
||||
for (final file in groups[folder]!) (folder, file),
|
||||
],
|
||||
];
|
||||
return ListView.builder(
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: rows.length,
|
||||
itemBuilder: (context, index) {
|
||||
final (folder, file) = rows[index];
|
||||
final segments = _segmentsOf(folder);
|
||||
if (file == null) {
|
||||
return _FolderHeader(
|
||||
key: ValueKey('folder:$folder'),
|
||||
folder: folder,
|
||||
onOpen: () {
|
||||
onResultTap?.call();
|
||||
AppRoutes.openFolder(context, segments);
|
||||
},
|
||||
);
|
||||
}
|
||||
return FileElement(
|
||||
file,
|
||||
segments,
|
||||
controller.retry,
|
||||
key: ValueKey('file:${file.path}'),
|
||||
highlight: controller.query,
|
||||
);
|
||||
}
|
||||
}
|
||||
return ListView(padding: EdgeInsets.zero, children: items);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
static final RegExp _edgeSlashes = RegExp(r'^/+|/+$');
|
||||
|
||||
Map<String, List<CacheableFile>> _groupByParent(List<CacheableFile> files) {
|
||||
final map = <String, List<CacheableFile>>{};
|
||||
for (final file in files) {
|
||||
@@ -139,7 +150,7 @@ class FilesSearchResults extends StatelessWidget {
|
||||
}
|
||||
|
||||
String _parentOf(CacheableFile file) {
|
||||
final stripped = file.path.replaceAll(RegExp(r'^/+|/+$'), '');
|
||||
final stripped = file.path.replaceAll(_edgeSlashes, '');
|
||||
final segments = stripped.split('/');
|
||||
if (segments.length <= 1) return '/';
|
||||
segments.removeLast();
|
||||
@@ -147,7 +158,7 @@ class FilesSearchResults extends StatelessWidget {
|
||||
}
|
||||
|
||||
List<String> _segmentsOf(String folder) {
|
||||
final stripped = folder.replaceAll(RegExp(r'^/+|/+$'), '');
|
||||
final stripped = folder.replaceAll(_edgeSlashes, '');
|
||||
if (stripped.isEmpty) return const [];
|
||||
return stripped.split('/');
|
||||
}
|
||||
@@ -156,7 +167,11 @@ class FilesSearchResults extends StatelessWidget {
|
||||
class _FolderHeader extends StatelessWidget {
|
||||
final String folder;
|
||||
final VoidCallback onOpen;
|
||||
const _FolderHeader({required this.folder, required this.onOpen});
|
||||
const _FolderHeader({
|
||||
required this.folder,
|
||||
required this.onOpen,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
Reference in New Issue
Block a user