Skip to content

Commit 7840f76

Browse files
Add a terminal size guard
1 parent 4d1c00a commit 7840f76

File tree

3 files changed

+89
-3
lines changed

3 files changed

+89
-3
lines changed

internal/ui/app.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ type App struct {
6363
systemScraper *system.Scraper
6464
userStats *userstats.Reader
6565
currentScreen Component
66+
sizeGuard TerminalSizeGuard
6667
lastSize tea.WindowSizeMsg
6768
eventChan <-chan struct{}
6869
watchCtx context.Context
@@ -117,6 +118,7 @@ func NewApp(ns *docker.Namespace, installImageRef string) *App {
117118
systemScraper: systemScraper,
118119
userStats: userStats,
119120
currentScreen: screen,
121+
sizeGuard: NewTerminalSizeGuard(80, 24),
120122
eventChan: eventChan,
121123
watchCtx: ctx,
122124
watchCancel: cancel,
@@ -139,6 +141,7 @@ func (m *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
139141
switch msg := msg.(type) {
140142
case tea.WindowSizeMsg:
141143
m.lastSize = msg
144+
m.sizeGuard = m.sizeGuard.Update(msg)
142145

143146
case tea.MouseClickMsg:
144147
ms := msg.Mouse()
@@ -247,10 +250,14 @@ func (m *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
247250
}
248251

249252
func (m *App) View() tea.View {
250-
content := m.currentScreen.View()
251-
cleaned := mouse.Sweep(content)
253+
var content string
254+
if m.sizeGuard.LargeEnough() {
255+
content = mouse.Sweep(m.currentScreen.View())
256+
} else {
257+
content = m.sizeGuard.View()
258+
}
252259

253-
v := tea.NewView(cleaned)
260+
v := tea.NewView(content)
254261
v.AltScreen = true
255262
v.MouseMode = tea.MouseModeAllMotion
256263
return v

internal/ui/terminal_size_guard.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package ui
2+
3+
import (
4+
"fmt"
5+
6+
tea "charm.land/bubbletea/v2"
7+
"charm.land/lipgloss/v2"
8+
)
9+
10+
type TerminalSizeGuard struct {
11+
minWidth, minHeight int
12+
width, height int
13+
}
14+
15+
func NewTerminalSizeGuard(minWidth, minHeight int) TerminalSizeGuard {
16+
return TerminalSizeGuard{minWidth: minWidth, minHeight: minHeight}
17+
}
18+
19+
func (g TerminalSizeGuard) Update(msg tea.WindowSizeMsg) TerminalSizeGuard {
20+
g.width = msg.Width
21+
g.height = msg.Height
22+
return g
23+
}
24+
25+
func (g TerminalSizeGuard) LargeEnough() bool {
26+
return g.width >= g.minWidth && g.height >= g.minHeight
27+
}
28+
29+
func (g TerminalSizeGuard) View() string {
30+
line1 := fmt.Sprintf("Terminal too small: %d×%d", g.width, g.height)
31+
line2 := fmt.Sprintf("Minimum size is %d×%d", g.minWidth, g.minHeight)
32+
33+
style := lipgloss.NewStyle().Foreground(Colors.Muted)
34+
msg := lipgloss.JoinVertical(lipgloss.Center, style.Render(line1), "", style.Render(line2))
35+
return lipgloss.Place(g.width, g.height, lipgloss.Center, lipgloss.Center, msg)
36+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package ui
2+
3+
import (
4+
"testing"
5+
6+
tea "charm.land/bubbletea/v2"
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestTerminalSizeGuard_InitiallyTooSmall(t *testing.T) {
11+
g := NewTerminalSizeGuard(80, 24)
12+
assert.False(t, g.LargeEnough())
13+
}
14+
15+
func TestTerminalSizeGuard_LargeEnough(t *testing.T) {
16+
g := NewTerminalSizeGuard(80, 24)
17+
g = g.Update(tea.WindowSizeMsg{Width: 80, Height: 24})
18+
assert.True(t, g.LargeEnough())
19+
20+
g = g.Update(tea.WindowSizeMsg{Width: 120, Height: 40})
21+
assert.True(t, g.LargeEnough())
22+
}
23+
24+
func TestTerminalSizeGuard_TooNarrow(t *testing.T) {
25+
g := NewTerminalSizeGuard(80, 24)
26+
g = g.Update(tea.WindowSizeMsg{Width: 79, Height: 24})
27+
assert.False(t, g.LargeEnough())
28+
}
29+
30+
func TestTerminalSizeGuard_TooShort(t *testing.T) {
31+
g := NewTerminalSizeGuard(80, 24)
32+
g = g.Update(tea.WindowSizeMsg{Width: 80, Height: 23})
33+
assert.False(t, g.LargeEnough())
34+
}
35+
36+
func TestTerminalSizeGuard_ViewShowsDimensions(t *testing.T) {
37+
g := NewTerminalSizeGuard(80, 24)
38+
g = g.Update(tea.WindowSizeMsg{Width: 60, Height: 20})
39+
40+
view := g.View()
41+
assert.Contains(t, view, "Terminal too small: 60×20")
42+
assert.Contains(t, view, "Minimum size is 80×24")
43+
}

0 commit comments

Comments
 (0)