feat: Add complete keyboard navigation system
Implemented a full keyboard navigation system with directional commands (C-h/j/k/l) for moving between views, vim-style navigation (j/k for rows, h/l for columns), and TAB cycling. Added table header navigation mode where users can move between columns and change sort order with keyboard shortcuts. The navigation follows visual position: left sidebar, table, and filter bar can all be reached with directional keys. Created a keymap system with context-aware bindings that resolve commands based on current focus (Table, TableHeaders, FilterBar, Sidebar). Commands are dispatched through a centralized handler that manages focus transitions and view state. Added helper methods to cycle through column headers with proper wrapping. Auto-select first task on load when tasks exist, and set initial window focus so keyboard shortcuts work immediately without requiring a mouse click.
This commit is contained in:
@@ -206,6 +206,21 @@ impl FilterState {
|
||||
self.due_filter = DueFilter::default();
|
||||
}
|
||||
|
||||
pub fn clear_project(&mut self) {
|
||||
self.selected_project = None;
|
||||
}
|
||||
|
||||
pub fn clear_tags(&mut self) {
|
||||
self.active_tags.clear();
|
||||
}
|
||||
|
||||
pub fn clear_search_and_dropdowns(&mut self) {
|
||||
self.search_text.clear();
|
||||
self.status_filter = StatusFilter::default();
|
||||
self.priority_filter = PriorityFilter::default();
|
||||
self.due_filter = DueFilter::default();
|
||||
}
|
||||
|
||||
pub fn has_active_filters(&self) -> bool {
|
||||
self.selected_project.is_some()
|
||||
|| !self.active_tags.is_empty()
|
||||
|
||||
@@ -152,6 +152,21 @@ impl ProjectTree {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_expanded_paths(&self) -> HashMap<String, bool> {
|
||||
self.expanded_paths.clone()
|
||||
}
|
||||
|
||||
pub fn restore_expanded_paths(&mut self, paths: HashMap<String, bool>) {
|
||||
for (path, is_expanded) in &paths {
|
||||
if *is_expanded {
|
||||
if let Some(&idx) = self.path_to_index.get(path) {
|
||||
self.nodes[idx].is_expanded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.expanded_paths = paths;
|
||||
}
|
||||
|
||||
pub fn expand_path(&mut self, full_path: &str) {
|
||||
let segments: Vec<&str> = full_path.split('.').collect();
|
||||
let mut current_path = String::new();
|
||||
|
||||
Reference in New Issue
Block a user