feat: clear screen on SSH enter/exit, host list scrolling, 'e' edit key

- tea.Batch(tea.ClearScreen, sshConnectCmd) before SSH starts so TUI
  output doesn't bleed into SSH terminal
- tea.ClearScreen after SSH exits so SSH output doesn't ghost in TUI
- Host list now paginates: only (term_height - 8) / 5 cards shown,
  viewport follows selectedIndex with centered scrolling
- Shows 'N of M hosts' indicator when content is clipped
- Added 'e' key alias for editing host (Ctrl+E or E)
This commit is contained in:
swanadiva
2026-06-23 16:04:38 +07:00
parent 2442920616
commit c7568e0bf4
2 changed files with 29 additions and 5 deletions
+27 -3
View File
@@ -68,7 +68,7 @@ func (t *HostListTab) Update(msg tea.Msg) (Tab, tea.Cmd) {
return openHostFormMsg{} return openHostFormMsg{}
} }
case "ctrl+e": case "ctrl+e", "e":
if len(t.hosts) > 0 { if len(t.hosts) > 0 {
host := t.hosts[t.selectedIndex] host := t.hosts[t.selectedIndex]
return t, func() tea.Msg { return t, func() tea.Msg {
@@ -139,15 +139,39 @@ func (t *HostListTab) View() string {
b.WriteString(centerText(SubtitleStyle.Render("No hosts found. Add with Ctrl+N"), availW)) b.WriteString(centerText(SubtitleStyle.Render("No hosts found. Add with Ctrl+N"), availW))
b.WriteString("\n") b.WriteString("\n")
} else { } else {
for i, host := range t.hosts { // Scrolling: show only what fits on screen
cardH := 5 // 4 lines per card + 1 blank separator
maxCards := (t.height - 8) / cardH
if maxCards < 1 {
maxCards = 1
}
if maxCards > len(t.hosts) {
maxCards = len(t.hosts)
}
start := t.selectedIndex - maxCards/2
if start < 0 {
start = 0
}
if start+maxCards > len(t.hosts) {
start = len(t.hosts) - maxCards
}
for i := start; i < start+maxCards; i++ {
host := t.hosts[i]
entry := renderHostEntry(host, i == t.selectedIndex, cardW) entry := renderHostEntry(host, i == t.selectedIndex, cardW)
// Center the card (which produces 4 lines) horizontally
for _, line := range strings.Split(entry, "\n") { for _, line := range strings.Split(entry, "\n") {
b.WriteString(centerText(line, availW)) b.WriteString(centerText(line, availW))
b.WriteString("\n") b.WriteString("\n")
} }
b.WriteString("\n") b.WriteString("\n")
} }
if maxCards < len(t.hosts) {
b.WriteString(centerText(
SubtitleStyle.Render(fmt.Sprintf("%d of %d hosts", start+1, len(t.hosts))),
availW))
}
} }
return b.String() return b.String()
+2 -2
View File
@@ -62,13 +62,13 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, tea.Quit return m, tea.Quit
case sshConnectToMsg: case sshConnectToMsg:
return m, sshConnectCmd(msg.host, m.dataDir) return m, tea.Batch(tea.ClearScreen, sshConnectCmd(msg.host, m.dataDir))
case sshExitMsg: case sshExitMsg:
if msg.err != nil { if msg.err != nil {
m.Error = msg.err m.Error = msg.err
} }
return m, nil return m, tea.ClearScreen
case openHostFormMsg: case openHostFormMsg:
var tab Tab var tab Tab