mirror of
https://codeberg.org/shroff/phylum.git
synced 2026-05-07 04:39:25 -05:00
[client] Scroll folder list on keyboard nav
This commit is contained in:
@@ -151,7 +151,7 @@ class ExplorerController extends StateNotifier<ExplorerState> {
|
||||
return true;
|
||||
}
|
||||
|
||||
void updateSelection(int Function(int)? indexFn, SelectionMode mode, bool highlight) {
|
||||
int updateSelection(int Function(int)? indexFn, SelectionMode mode, bool highlight) {
|
||||
Set<String>? selectedIds;
|
||||
int index = indexFn?.call(state.focusIndex) ?? state.focusIndex;
|
||||
index = min(state.resources.length - 1, max(0, index));
|
||||
@@ -196,6 +196,7 @@ class ExplorerController extends StateNotifier<ExplorerState> {
|
||||
focusIndex: index,
|
||||
showFocus: highlight,
|
||||
);
|
||||
return index;
|
||||
}
|
||||
|
||||
Future refresh() {
|
||||
|
||||
@@ -16,51 +16,85 @@ class FolderListView extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _FolderListViewState extends State<FolderListView> {
|
||||
double? _rowHeight;
|
||||
double _viewportHeight = 0.0;
|
||||
final _scrollController = ScrollController(debugLabel: "FolderList");
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void ensureVisible(int index) {
|
||||
final currentOffset = _scrollController.offset;
|
||||
final itemStart = index * _rowHeight!;
|
||||
if (itemStart < currentOffset) {
|
||||
_scrollController.jumpTo(itemStart);
|
||||
} else if (currentOffset <= itemStart + _rowHeight! + -_viewportHeight) {
|
||||
_scrollController.jumpTo(itemStart - _viewportHeight + _rowHeight!);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final resources = context.select<ExplorerState, List<Resource>>((state) => state.resources);
|
||||
return Actions(
|
||||
actions: {
|
||||
FocusUpIntent: CallbackAction<FocusUpIntent>(onInvoke: (i) {
|
||||
context.read<ExplorerController>().updateSelection((i) => i - 1, i.mode, true);
|
||||
final index = context.read<ExplorerController>().updateSelection((i) => i - 1, i.mode, true);
|
||||
ensureVisible(index);
|
||||
return null;
|
||||
}),
|
||||
FocusDownIntent: CallbackAction<FocusDownIntent>(onInvoke: (i) {
|
||||
context.read<ExplorerController>().updateSelection((i) => i + 1, i.mode, true);
|
||||
final index = context.read<ExplorerController>().updateSelection((i) => i + 1, i.mode, true);
|
||||
ensureVisible(index);
|
||||
return null;
|
||||
}),
|
||||
FocusFirstIntent: CallbackAction<FocusFirstIntent>(onInvoke: (i) {
|
||||
context.read<ExplorerController>().updateSelection((i) => 0, i.mode, true);
|
||||
final index = context.read<ExplorerController>().updateSelection((i) => 0, i.mode, true);
|
||||
ensureVisible(index);
|
||||
return null;
|
||||
}),
|
||||
FocusLastIntent: CallbackAction<FocusLastIntent>(onInvoke: (i) {
|
||||
context.read<ExplorerController>().updateSelection((i) => 4294967296, i.mode, true);
|
||||
final index = context.read<ExplorerController>().updateSelection((i) => 4294967296, i.mode, true);
|
||||
ensureVisible(index);
|
||||
return null;
|
||||
}),
|
||||
},
|
||||
child: Focus(
|
||||
autofocus: true,
|
||||
descendantsAreFocusable: false,
|
||||
child: ListView.builder(
|
||||
itemCount: resources.length,
|
||||
itemExtent: calculateRowHeight(context),
|
||||
itemBuilder: (context, index) {
|
||||
final resource = resources[index];
|
||||
return (resource.dir)
|
||||
? ResourceDragTarget(
|
||||
resourceId: resource.id,
|
||||
buildItem: (context, dropTargetActive) => ResourceItemGestureHandler(
|
||||
child: LayoutBuilder(builder: (context, constraints) {
|
||||
_rowHeight ??= calculateRowHeight(context);
|
||||
_viewportHeight = constraints.maxHeight;
|
||||
return ListView.builder(
|
||||
itemCount: resources.length,
|
||||
itemExtent: _rowHeight,
|
||||
controller: _scrollController,
|
||||
itemBuilder: (context, index) {
|
||||
final resource = resources[index];
|
||||
return (resource.dir)
|
||||
? ResourceDragTarget(
|
||||
resourceId: resource.id,
|
||||
buildItem: (context, dropTargetActive) => ResourceItemGestureHandler(
|
||||
index: index,
|
||||
resource: resource,
|
||||
dropTargetActive: dropTargetActive,
|
||||
),
|
||||
)
|
||||
: ResourceItemGestureHandler(
|
||||
index: index,
|
||||
resource: resource,
|
||||
dropTargetActive: dropTargetActive,
|
||||
),
|
||||
)
|
||||
: ResourceItemGestureHandler(
|
||||
index: index,
|
||||
resource: resource,
|
||||
dropTargetActive: false,
|
||||
);
|
||||
}),
|
||||
dropTargetActive: false,
|
||||
);
|
||||
});
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user