Skip to content

Latest commit

 

History

History
65 lines (39 loc) · 6.61 KB

File metadata and controls

65 lines (39 loc) · 6.61 KB

Refactoring: pain points & roadmap (App.tsx)

This document records when a larger frontend refactor pays off, a lightweight map of apps/desktop/src/App.tsx, and three incremental extraction candidates. It implements the team decision from the refactor plan: prefer small PRs aligned with architecture.md (components/, features/).

1. When to refactor (pain points)

Treat refactoring as a tool, not a goal. Start or schedule work when at least one of these is true:

Signal What it means here
Reviews PRs touching App.tsx are hard to review because unrelated concerns (sidebar + settings + splits) change together.
Bugs Regressions recur in the same area (e.g. drag/drop, workspace restore, settings modal) because state and UI are tightly coupled in one file.
Feature tempo New UI takes disproportionate effort: finding the right useEffect / handler among thousands of lines, or fear of breaking unrelated flows.
Onboarding New contributors cannot form a mental model of “where host list lives” vs “where terminal layout lives” within a reasonable time.

If none of these apply and releases are stable, defer large splits; use the map below only when you pick up the next refactor PR.

Already in good shape: Rust modules in src-tauri, shared helpers under features/, and IPC in tauri-api.ts — no parallel backend refactor is required for frontend cleanup.

2. Mini-audit: App.tsx structure

Line ranges are approximate (~4048 lines in App.tsx after sidebar bridge + settings split). Use them as navigation hints, not rigid contracts.

Region (lines) Content
~1–~220 Imports; lazy LayoutCommandCenter; re-exports from features/ (split-tree, workspace snapshot, pane DnD, preferences, session model, bootstrap, …).
~220–~3610 export function App(): state, refs, effects (many persisted in hooks/ — workspace bootstrap/persist, ref sync, session-output trust listener), handlers (connect, backup, layout, DnD, …).
~3610–~3668 createSplitPaneRendererrenderSplitNode bridge; host list rows live in HostSidebar via HostListRow + hostListRowBridge.
~3669–end Root JSX: app-shell, HostSidebar, TerminalWorkspaceDock (workspace tabs + DnD, terminal grid / mobile pager, footer), context menus, settings, modals (AddHostModal, QuickConnectModal, TrustHostModal), mobile shell. Split panes use renderSplitNode from SplitWorkspace.tsx.

Pure logic (no React) now also lives in: split-tree.ts, workspace-snapshot.ts, pane-dnd.ts, app-preferences.ts, app-bootstrap.ts, session-model.ts, app-id.ts, tauri-runtime.ts (with Vitest where noted in repo).

Hooks: useAppRefSync, useSessionOutputTrustListener, useWorkspaceLocalStorage (useWorkspaceBootstrapFromStorage, useWorkspacePersistToStorage).

3. Three incremental extractions (order: low risk → larger)

Each step should be one PR, with npm test (and npm run build in apps/desktop) green before merge.

A) Pure view-profile / filter logic → features/

Target: apps/desktop/src/features/view-profile-filters.ts.

Status: Done — logic + ViewFilterHostRow live in that module; Vitest in view-profile-filters.test.ts; App.tsx wires evaluateGroup, createDefaultViewProfile, and createEmptyViewFilterRule.

B) App settings panel body → components/

Target: apps/desktop/src/components/AppSettingsPanel.tsx (shell + tab wiring) and apps/desktop/src/components/settings/ (app-settings-types, app-settings-panel-props, app-settings-constants, per-tab modules under settings/tabs/).

Status: Done — settings UI split by main tab; App still passes the full prop surface into AppSettingsPanel.

C) Sidebar host list + filters → components/

Target: apps/desktop/src/components/HostSidebar.tsx.

Status: Done — sidebar chrome, filters, and host list call back into App via props; rows render inside the sidebar via hostListRowBridge + HostListRow.

4. Optional next steps (not required)

  • Component smoke tests: shared bridge fixtures in host-list-row-fixtures.ts; HostListRow.test.tsx (row UI), HostSidebar.test.tsx (empty list, one row, settings click via minimalHostSidebarProps()).
  • useReducer / context for workspace or split state: defer until interaction bugs or review pain justify a single owner for that subgraph; current hooks + props remain easier to follow for most changes.
  • Further shrink App: HostSidebar renders HostListRow via a typed hostListRowBridge (no renderHostRow callback in App). Right-dock workspace UI lives in TerminalWorkspaceDock.

5. TypeScript output (noEmit)

Compiler output next to sources (duplicate .js files) is avoided by "noEmit": true in apps/desktop/tsconfig.json. npm run build remains tsc && vite build: typecheck only from tsc, bundling from Vite.