Fix TUI bugs: folder selection, filter stability, UI consistency

- Mail: Fix folder/account selector not triggering reload (use direct
  fetch instead of reactive reload_needed flag)
- Tasks: Store all_projects/all_tags on mount so filters don't change
  when filtering; add OR search for multiple tags
- Sync: Use rounded borders and border_title for sidebar/activity log
- Calendar: Remove padding from mini-calendar, add rounded border and
  border_title to invites panel
This commit is contained in:
Bendt
2025-12-19 11:24:15 -05:00
parent 25385c6482
commit be2f67bb7b
5 changed files with 71 additions and 37 deletions

View File

@@ -197,6 +197,8 @@ class TasksApp(App):
self.tasks = []
self.projects = []
self.tags = []
self.all_projects = [] # Stable list of all projects (not filtered)
self.all_tags = [] # Stable list of all tags (not filtered)
self.current_project_filter = None
self.current_tag_filters = []
self.current_sort_column = "priority"
@@ -261,7 +263,10 @@ class TasksApp(App):
height = max(10, min(90, height))
notes_pane.styles.height = f"{height}%"
# Load tasks (this will also update the sidebar)
# Load ALL projects and tags once for stable sidebar
self._load_all_filters()
# Load tasks (filtered by current filters)
self.load_tasks()
def _setup_columns(self, table: DataTable, columns: list[str]) -> None:
@@ -375,32 +380,58 @@ class TasksApp(App):
if not self.backend:
return
# Get tasks with current filters
self.tasks = self.backend.get_tasks(
project=self.current_project_filter,
tags=self.current_tag_filters if self.current_tag_filters else None,
)
# Get ALL tasks first (unfiltered)
all_tasks = self.backend.get_tasks()
# Apply client-side filtering for OR logic
self.tasks = self._filter_tasks(all_tasks)
# Sort tasks
self._sort_tasks()
# Also load projects and tags for filtering
self.projects = self.backend.get_projects()
self.tags = self.backend.get_tags()
# Update sidebar with available filters
self._update_sidebar()
# Update table
self._update_table()
def _load_all_filters(self) -> None:
"""Load all projects and tags once for stable sidebar."""
if not self.backend:
return
self.all_projects = self.backend.get_projects()
self.all_tags = self.backend.get_tags()
# Update sidebar with stable filter options
self._update_sidebar()
def _filter_tasks(self, tasks: list[Task]) -> list[Task]:
"""Filter tasks by current project and tag filters using OR logic.
- If project filter is set, only show tasks from that project
- If tag filters are set, show tasks that have ANY of the selected tags (OR)
"""
filtered = tasks
# Filter by project (single project filter is AND)
if self.current_project_filter:
filtered = [t for t in filtered if t.project == self.current_project_filter]
# Filter by tags using OR logic - show tasks with ANY of the selected tags
if self.current_tag_filters:
filtered = [
t
for t in filtered
if any(tag in t.tags for tag in self.current_tag_filters)
]
return filtered
def _update_sidebar(self) -> None:
"""Update the filter sidebar with current projects and tags."""
"""Update the filter sidebar with all available projects and tags."""
try:
sidebar = self.query_one("#sidebar", FilterSidebar)
# Convert projects to (name, count) tuples
project_data = [(p.name, p.task_count) for p in self.projects if p.name]
sidebar.update_filters(projects=project_data, tags=self.tags)
# Use stable all_projects/all_tags, not filtered ones
project_data = [(p.name, p.task_count) for p in self.all_projects if p.name]
sidebar.update_filters(projects=project_data, tags=self.all_tags)
except Exception:
pass # Sidebar may not be mounted yet