diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-12 22:47:20 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-12 22:47:20 +0300 |
| commit | 35df301fceabfadc8b8a4ae221cc0c2391e233cd (patch) | |
| tree | 2d5da8031aacd588e31db1aad05c2956412f7566 /internal/tui/screenrouter.go | |
| parent | a2c067cc49b96968da81031275de9c44c4ba2ee9 (diff) | |
extract TUI Model god class into focused sub-controllers
Split the 1389-line tui.go Model into three focused sub-controllers
that each own a single concern:
- filterstack.go (filterStack): owns the filter chain, undo history,
and label stack; provides push/pop/rebindProcessFilters API so the
Model never manipulates filter slices directly.
- tracelifecycle.go (traceLifecycle): owns trace start/stop and the
active context.CancelFunc; provides beginCmd/stop API; also houses
the recorder helpers (recorderStart/Stop/Active/Status) and the
auto-reset cycle logic (nextAutoResetInterval, autoResetCycle).
- screenrouter.go (screenRouter): owns the picker-return bookmark
(pickerReturn) and the applyWindowSizeToPicker helper so screen
transition code in tui.go delegates to it.
The Model.Update switch is split into dispatchTypedMsg (framework
messages) and dispatchAppMsg (app messages) to keep each helper
under the 50-line limit. View is split into viewPickerScreen and
viewDashboardScreen for the same reason.
All functions are ≤50 lines. go test ./internal/tui/... passes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/tui/screenrouter.go')
| -rw-r--r-- | internal/tui/screenrouter.go | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/internal/tui/screenrouter.go b/internal/tui/screenrouter.go new file mode 100644 index 0000000..9a110c8 --- /dev/null +++ b/internal/tui/screenrouter.go @@ -0,0 +1,60 @@ +package tui + +import ( + "ior/internal/tui/pidpicker" + + tea "charm.land/bubbletea/v2" +) + +// screenRouter owns screen-transition state for the TUI. It tracks the picker +// return bookmark used when the user navigates from the dashboard to the PID or +// TID picker and may want to cancel back to the original dashboard view. +type screenRouter struct { + // pickerReturn is non-nil while the user has navigated from the dashboard + // back to the PID/TID picker. The stored values are used to restart the + // trace if the user presses Esc to cancel the picker navigation. + pickerReturn *pickerReturnState +} + +// newScreenRouter creates an empty screenRouter with no pending return state. +func newScreenRouter() screenRouter { + return screenRouter{} +} + +// savePendingReturn records the current pid/tid so Esc can restore the +// dashboard if the user decides not to select a new process. +func (r *screenRouter) savePendingReturn(pid, tid int) { + r.pickerReturn = &pickerReturnState{ + pidFilter: pid, + tidFilter: tid, + } +} + +// takePendingReturn consumes and returns the stored picker return state, +// clearing it in the process. Returns (zero, false) when no pending state exists. +func (r *screenRouter) takePendingReturn() (pickerReturnState, bool) { + if r.pickerReturn == nil { + return pickerReturnState{}, false + } + state := *r.pickerReturn + r.pickerReturn = nil + return state, true +} + +// hasPendingReturn reports whether the user navigated from the dashboard to +// the picker (meaning Esc should return to the dashboard instead of quitting). +func (r *screenRouter) hasPendingReturn() bool { + return r.pickerReturn != nil +} + +// applyWindowSizeToPicker sends the current window size to the pid picker when +// valid dimensions are available. Returns the updated picker and an optional +// size command. +func applyWindowSizeToPicker(picker pidpicker.Model, width, height int) (pidpicker.Model, tea.Cmd) { + if width <= 0 || height <= 0 { + return picker, nil + } + msg := tea.WindowSizeMsg{Width: width, Height: height} + next, cmd := picker.Update(msg) + return next.(pidpicker.Model), cmd +} |
