Skip to content

Commit 12447c1

Browse files
committed
fix: a terminal resize reaches screens holding a text input
Non-key messages are forwarded to whichever text input a screen owns, and that branch returns, so the resize never reached the handler that records the new size. Every screen with a search field or a form — Run workflow, Run commands, the name inputs — kept drawing for the terminal it started in, while screens without one resized correctly. A resize belongs to no single sub-model, so it is now taken before any forwarding. The inputs are deliberately not told: their widths are fixed on purpose, so a wide terminal does not stretch a name field across the screen.
1 parent aae3511 commit 12447c1

2 files changed

Lines changed: 77 additions & 5 deletions

File tree

internal/tui/update.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ import (
99
type runReadyMsg struct{}
1010

1111
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
12+
// A resize is every screen's business, so it is handled before the
13+
// forwarding below — which returns early and would otherwise leave
14+
// the layout stale on any screen holding a text input.
15+
if ws, ok := msg.(tea.WindowSizeMsg); ok {
16+
m.width = ws.Width
17+
m.height = ws.Height
18+
m.updateStepsViewport()
19+
return m, nil
20+
}
21+
1222
// Always forward to spinner so TickMsg animates it.
1323
{
1424
s, c := m.spinner.Update(msg)
@@ -51,11 +61,6 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
5161
}
5262

5363
switch msg := msg.(type) {
54-
case tea.WindowSizeMsg:
55-
m.width = msg.Width
56-
m.height = msg.Height
57-
m.updateStepsViewport()
58-
return m, nil
5964
case runReadyMsg:
6065
if m.running != nil {
6166
m.running.starting = false

internal/tui/update_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package tui
2+
3+
import (
4+
"testing"
5+
6+
"github.com/charmbracelet/bubbles/spinner"
7+
"github.com/charmbracelet/bubbles/textinput"
8+
tea "github.com/charmbracelet/bubbletea"
9+
10+
mdl "github.com/Taka-S-dev/baton/internal/model"
11+
)
12+
13+
// TestUpdate_ResizeReachesEveryScreen guards the dispatch order: screens
14+
// holding a text input forward every non-key message to it and return,
15+
// so a resize arriving there used to be swallowed and the layout stayed
16+
// sized for the old terminal. Every screen must see it.
17+
func TestUpdate_ResizeReachesEveryScreen(t *testing.T) {
18+
screens := []Screen{
19+
ScreenMainMenu,
20+
ScreenRunWorkflow, // wfSearchTI
21+
ScreenRunCommands, // msSearchTI
22+
ScreenCreateWorkflow, // msSearchTI
23+
ScreenNameInput, // nameInput
24+
ScreenCommandForm, // nameInput
25+
ScreenVarForm, // nameInput
26+
ScreenSlotPick,
27+
ScreenConfirmRun,
28+
ScreenRunWorkflowSteps,
29+
}
30+
for _, sc := range screens {
31+
m := Model{screen: sc, width: 80, height: 24}
32+
m.spinner = spinner.New()
33+
m.nameInput = textinput.New()
34+
m.msSearchTI = textinput.New()
35+
m.wfSearchTI = textinput.New()
36+
m.workflows = []mdl.Workflow{{Name: "wf", Commands: []string{"a"}}}
37+
38+
nm, _ := m.Update(tea.WindowSizeMsg{Width: 120, Height: 40})
39+
got := nm.(Model)
40+
if got.width != 120 || got.height != 40 {
41+
t.Errorf("screen %v: size = %dx%d, want 120x40 — the resize was swallowed",
42+
sc, got.width, got.height)
43+
}
44+
}
45+
}
46+
47+
// TestUpdate_ResizeResizesStepsPreview checks the steps viewport is
48+
// rebuilt for the new size rather than keeping the dimensions it was
49+
// given at startup.
50+
func TestUpdate_ResizeResizesStepsPreview(t *testing.T) {
51+
m := Model{screen: ScreenRunWorkflow, width: 80, height: 24}
52+
m.spinner = spinner.New()
53+
m.wfSearchTI = textinput.New()
54+
m.config = mdl.Config{Base: []mdl.Command{{Name: "a", Cmd: "echo hi"}}}
55+
m.workflows = []mdl.Workflow{{Name: "wf", Commands: []string{"a"}}}
56+
m.updateStepsViewport()
57+
before := m.stepsVP.Width
58+
59+
nm, _ := m.Update(tea.WindowSizeMsg{Width: 140, Height: 50})
60+
got := nm.(Model)
61+
if got.stepsVP.Width == before {
62+
t.Fatalf("steps preview width stayed %d after a resize to 140", before)
63+
}
64+
if got.stepsVP.Width != 140-4 {
65+
t.Fatalf("steps preview width = %d, want the new terminal width less its frame", got.stepsVP.Width)
66+
}
67+
}

0 commit comments

Comments
 (0)