Skip to content

Commit 8c75e88

Browse files
authored
Merge pull request #127 from babarot/babarot/fix-restore-tui-small-window
fix: keep restore TUI within terminal bounds (closes #125)
2 parents 4f189da + c8e386b commit 8c75e88

2 files changed

Lines changed: 97 additions & 1 deletion

File tree

internal/ui/update.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,20 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
2828
}
2929

3030
case tea.WindowSizeMsg:
31-
m.list.SetWidth(msg.Width)
31+
// view.go appends a help block wrapped in lipgloss Margin(1, 2)
32+
// below the list: 1 row top margin + 1 row content + 1 row bottom
33+
// margin = 3 rows tall, and 2 cols on each side = 4 cols total.
34+
const (
35+
helpReservedRows = 3
36+
helpReservedCols = 4
37+
)
38+
if msg.Width > 0 {
39+
m.list.SetWidth(msg.Width)
40+
m.help.Width = max(msg.Width-helpReservedCols, 0)
41+
}
42+
if msg.Height > 0 {
43+
m.list.SetHeight(max(msg.Height-helpReservedRows, 1))
44+
}
3245
return m, tea.Batch(cmds...)
3346

3447
case FileListUpdatedMsg:

internal/ui/update_test.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/charmbracelet/bubbles/list"
99
"github.com/charmbracelet/bubbles/viewport"
1010
tea "github.com/charmbracelet/bubbletea"
11+
"github.com/charmbracelet/lipgloss"
1112

1213
"github.com/babarot/gomi/internal/config"
1314
"github.com/babarot/gomi/internal/trash"
@@ -60,6 +61,88 @@ func TestUpdate_WindowSizeMsg(t *testing.T) {
6061
}
6162
}
6263

64+
func TestUpdate_WindowSizeMsg_ShrinksListHeight(t *testing.T) {
65+
m := newTestModel()
66+
67+
const termHeight = 20
68+
msg := tea.WindowSizeMsg{Width: 80, Height: termHeight}
69+
updated, _ := m.Update(msg)
70+
model := asModel(t, updated)
71+
72+
if model.list.Height() > termHeight {
73+
t.Errorf("list height = %d, want <= %d (terminal height); "+
74+
"list is not following the terminal height and will push items off-screen",
75+
model.list.Height(), termHeight)
76+
}
77+
}
78+
79+
func TestUpdate_WindowSizeMsg_SetsHelpWidth(t *testing.T) {
80+
m := newTestModel()
81+
82+
const termWidth = 70
83+
msg := tea.WindowSizeMsg{Width: termWidth, Height: 20}
84+
updated, _ := m.Update(msg)
85+
model := asModel(t, updated)
86+
87+
if model.help.Width == 0 {
88+
t.Fatal("help.Width = 0; the help model was not informed of the " +
89+
"terminal width, so its View() will not truncate and may overflow")
90+
}
91+
if model.help.Width > termWidth {
92+
t.Errorf("help.Width = %d, want <= %d (terminal width)",
93+
model.help.Width, termWidth)
94+
}
95+
}
96+
97+
func TestView_FitsSmallTerminal(t *testing.T) {
98+
m := newTestModel()
99+
m.help = newHelpModel()
100+
m.state.SetView(ListView)
101+
102+
const (
103+
termWidth = 70
104+
termHeight = 20
105+
)
106+
msg := tea.WindowSizeMsg{Width: termWidth, Height: termHeight}
107+
updated, _ := m.Update(msg)
108+
model := asModel(t, updated)
109+
110+
view := model.View()
111+
112+
if h := lipgloss.Height(view); h > termHeight {
113+
t.Errorf("View height = %d lines, want <= %d; "+
114+
"output is taller than the terminal so the top rows scroll off",
115+
h, termHeight)
116+
}
117+
if w := lipgloss.Width(view); w > termWidth {
118+
t.Errorf("View width = %d cols, want <= %d; "+
119+
"output is wider than the terminal so the right edge is clipped/wrapped",
120+
w, termWidth)
121+
}
122+
}
123+
124+
// TestUpdate_WindowSizeMsg_HeightZero verifies that a synthetic
125+
// WindowSizeMsg with only Width set (sent by confirm-view cancel
126+
// paths in update.go) does not collapse the list height.
127+
func TestUpdate_WindowSizeMsg_HeightZero(t *testing.T) {
128+
m := newTestModel()
129+
130+
// First, set a real terminal size.
131+
updated, _ := m.Update(tea.WindowSizeMsg{Width: 120, Height: 40})
132+
m = asModel(t, updated)
133+
prevHeight := m.list.Height()
134+
135+
// Then send a width-only message (Height == 0).
136+
updated, _ = m.Update(tea.WindowSizeMsg{Width: m.list.Width()})
137+
model := asModel(t, updated)
138+
139+
if model.list.Height() != prevHeight {
140+
t.Errorf("list height = %d, want %d; "+
141+
"width-only WindowSizeMsg must not change list height",
142+
model.list.Height(), prevHeight)
143+
}
144+
}
145+
63146
func TestUpdate_ErrorMsg(t *testing.T) {
64147
m := newTestModel()
65148

0 commit comments

Comments
 (0)