From 45d1036fa75f1a6cdea509eec6e3f3f700d72869 Mon Sep 17 00:00:00 2001 From: Ignacio Perez Date: Sat, 27 Dec 2025 13:05:21 -0300 Subject: [PATCH] feat: Add sidebar filtering and fix layout issues Connect sidebar project/tag clicks to filter the task table. App now observes FilterState changes and triggers task reload. Removed redundant observer from TaskTable since App handles it. Fix Panel component that was overwriting its own styles, breaking flex layouts. Sidebar sections now split space equally and scroll properly. --- src/app.rs | 20 ++++++++++++--- src/components/panel.rs | 12 +++------ src/view/sidebar.rs | 54 ++++++++++++----------------------------- src/view/task_table.rs | 18 +++----------- 4 files changed, 40 insertions(+), 64 deletions(-) diff --git a/src/app.rs b/src/app.rs index 6a1a0e6..1c01dd4 100644 --- a/src/app.rs +++ b/src/app.rs @@ -55,6 +55,13 @@ impl gpui::Render for App { } impl App { + fn reload_tasks(&mut self, cx: &mut gpui::Context) { + let task_service = &mut self.task_service; + self.task_table.update(cx, |table, cx| { + table.reload_tasks(task_service, cx); + }); + } + pub fn run() -> () { let app = gpui::Application::new(); @@ -102,13 +109,20 @@ impl App { table.reload_tasks(&mut task_service, cx); }); - App { + let app = App { sidebar, - filter_state, + filter_state: filter_state.clone(), status_bar, task_table, task_service, - } + }; + + cx.observe(&filter_state, |app, _, cx| { + app.reload_tasks(cx); + }) + .detach(); + + app }) }, ) diff --git a/src/components/panel.rs b/src/components/panel.rs index eb909de..e2f3b25 100644 --- a/src/components/panel.rs +++ b/src/components/panel.rs @@ -78,21 +78,15 @@ impl gpui::RenderOnce for Panel { let children: Vec = self.content.drain(..).collect(); - let mut div = gpui::div() + gpui::div() .size_full() .bg(theme.panel) .border(gpui::px(self.border)) .border_color(theme.border) .rounded_md() .p(gpui::px(self.padding)) - .flex() - .flex_col() - .h_full() + .overflow_hidden() .children(header) - .children(children); - - *div.style() = self.style; - - div + .children(children) } } diff --git a/src/view/sidebar.rs b/src/view/sidebar.rs index 18a8975..149829c 100644 --- a/src/view/sidebar.rs +++ b/src/view/sidebar.rs @@ -2,7 +2,6 @@ use crate::components::{label::Label, panel::Panel}; use crate::models::{FilterState, ProjectTree}; use crate::theme::ActiveTheme; use gpui::{Context, Div, Entity, IntoElement, Window, div, prelude::*, px}; -use std::sync::Arc; #[derive(Debug, Clone)] pub struct TagItem { @@ -14,7 +13,6 @@ pub struct Sidebar { project_tree: ProjectTree, tags: Vec, filter_state: Entity, - on_filter_change: Option) + 'static>>, } impl Sidebar { @@ -33,18 +31,9 @@ impl Sidebar { project_tree, tags, filter_state, - on_filter_change: None, } } - pub fn on_filter_change(mut self, callback: F) -> Self - where - F: Fn(FilterState, &mut Window, &mut Context) + 'static, - { - self.on_filter_change = Some(Arc::new(callback)); - self - } - pub fn update_projects(&mut self, project_tree: ProjectTree, cx: &mut Context) { self.project_tree = project_tree; cx.notify(); @@ -58,18 +47,14 @@ impl Sidebar { fn handle_project_click( &mut self, full_path: Option, - window: &mut Window, + _window: &mut Window, cx: &mut Context, ) { - self.filter_state.update(cx, |filter, _cx| { + self.filter_state.update(cx, |filter, cx| { filter.select_project(full_path); + cx.notify(); }); - if let Some(callback) = &self.on_filter_change { - let filter = self.filter_state.read(cx).clone(); - callback(filter, window, cx); - } - cx.notify(); } @@ -78,16 +63,11 @@ impl Sidebar { cx.notify(); } - fn handle_tag_click(&mut self, tag_name: String, window: &mut Window, cx: &mut Context) { - self.filter_state.update(cx, |filter, _cx| { + fn handle_tag_click(&mut self, tag_name: String, _window: &mut Window, cx: &mut Context) { + self.filter_state.update(cx, |filter, cx| { filter.toggle_tag(tag_name); + cx.notify(); }); - - if let Some(callback) = &self.on_filter_change { - let filter = self.filter_state.read(cx).clone(); - callback(filter, window, cx); - } - cx.notify(); } @@ -284,16 +264,18 @@ impl Render for Sidebar { div() .flex() .flex_col() - .h_full() + .size_full() .bg(theme.background) .child( div() .flex() .flex_col() - .h(gpui::relative(0.5)) + .flex_1() + .min_h_0() .overflow_hidden() .child( div() + .flex_shrink_0() .px_3() .py_2() .border_b_1() @@ -308,25 +290,24 @@ impl Render for Sidebar { .child( div() .id("sidebar-projects") - .flex() - .flex_col() .flex_1() .min_h_0() - .py_2() + .py_1() .overflow_y_scroll() - .scrollbar_width(gpui::px(6.0)) .children(projects), ), ) - .child(div().h_px().bg(theme.border)) + .child(div().flex_shrink_0().h_px().bg(theme.border)) .child( div() .flex() .flex_col() - .h(gpui::relative(0.5)) + .flex_1() + .min_h_0() .overflow_hidden() .child( div() + .flex_shrink_0() .px_3() .py_2() .border_b_1() @@ -341,13 +322,10 @@ impl Render for Sidebar { .child( div() .id("sidebar-tags") - .flex() - .flex_col() .flex_1() .min_h_0() - .py_2() + .py_1() .overflow_y_scroll() - .scrollbar_width(gpui::px(6.0)) .children(tags), ), ), diff --git a/src/view/task_table.rs b/src/view/task_table.rs index 8522aeb..8330bbe 100644 --- a/src/view/task_table.rs +++ b/src/view/task_table.rs @@ -222,14 +222,8 @@ impl TaskTable { pub fn new( id: impl Into, filter_state: gpui::Entity, - cx: &mut gpui::Context, + _cx: &mut gpui::Context, ) -> Self { - cx.observe(&filter_state, |table, _filter, cx| { - table.need_reload = true; - cx.notify(); - }) - .detach(); - Self { id: id.into(), filter_state, @@ -315,13 +309,9 @@ impl TaskTable { self.cached_tasks = filtered_tasks; self.apply_sort(); self.pagination.total_items(self.cached_tasks.len()); - - if let Some(idx) = self.selected_global_idx { - if idx >= self.cached_tasks.len() { - self.selected_global_idx = None; - self.selected_page_idx = None; - } - } + self.pagination.current_page(1); + self.selected_global_idx = None; + self.selected_page_idx = None; self.recalculate_rows();