Skip to content

Decompose render: left sidebar as View<SidebarPanel> with SidebarSnapshot #204

Description

@MasonRhodesDev

Context

While auditing the render architecture in #203, the left sidebar was identified as the highest-payoff decomposition target.

Currently left_sidebar.rs is a collection of &self render helpers called inline from AnotherOneApp::render. Any state change anywhere in the app triggers a full re-render of the sidebar even when its specific state (project list, task list, expand state, context menus) didn't change.

What to do

Mirror the existing RightSidebarPanel pattern exactly:

  1. Define a SidebarSnapshot struct capturing everything the sidebar needs: projects, tasks, expanded repo IDs, UI state (pinned tasks, last active section), and the per-task menu/rename/delete-confirm state that currently lives on AnotherOneApp.
  2. Create struct SidebarPanel implementing Render, storing the snapshot plus local interaction state (sidebar_task_menu, sidebar_task_rename, sidebar_task_delete_confirm, sidebar_task_last_click).
  3. Store sidebar_panel: Entity<SidebarPanel> on AnotherOneApp.
  4. In the drain tick, compute a fresh SidebarSnapshot only when project/task state actually changed (gate behind a dirty flag like sidebar_changed), push it to SidebarPanel and call cx.notify() on it. Terminal-output ticks must not notify the sidebar.
  5. Remove the sidebar-only fields from AnotherOneApp (5–6 fields).

Why this is the right next step

  • RightSidebarPanel already proves the pattern works in this codebase.
  • The sidebar's state drivers (project/task mutations, daemon ProjectList pushes) are low-frequency (<1/sec) and already separated from terminal-output ticks by the drain loop.
  • Sidebar context-menu state (sidebar_task_menu, etc.) has zero cross-cutting dependencies — it can move directly into the new view.
  • project_store is the only broad dependency; a SidebarSnapshot severs it cleanly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions