AT Protocol Terminal Interface Explorer

add global footer

+32 -25
+30 -12
ui/app.go
··· 9 9 "github.com/bluesky-social/indigo/atproto/syntax" 10 10 "github.com/charmbracelet/bubbles/spinner" 11 11 tea "github.com/charmbracelet/bubbletea" 12 + "github.com/charmbracelet/lipgloss" 12 13 "github.com/treethought/attie/at" 13 14 ) 14 15 ··· 92 93 return a.active.Init() 93 94 } 94 95 96 + const footerHeight = 1 97 + 95 98 func (a *App) resizeChildren() tea.Cmd { 96 99 cmds := []tea.Cmd{} 97 - a.search.SetSize(a.w, a.h) 98 - a.repoView.SetSize(a.w, a.h) 99 - a.rlist.SetSize(a.w, a.h) 100 - a.recordView.SetSize(a.w, a.h) 101 - a.jetstream.SetSize(a.w, a.h) 102 - a.jetEventView.SetSize(a.w, a.h) 100 + h := a.h - footerHeight 101 + a.search.SetSize(a.w, h) 102 + a.repoView.SetSize(a.w, h) 103 + a.rlist.SetSize(a.w, h) 104 + a.recordView.SetSize(a.w, h) 105 + a.jetstream.SetSize(a.w, h) 106 + a.jetEventView.SetSize(a.w, h) 103 107 return tea.Batch(cmds...) 104 108 } 105 109 ··· 225 229 a.actx.collection = "" 226 230 a.actx.record = nil 227 231 cmd := a.repoView.SetRepo(msg.repo) 228 - a.repoView.SetSize(a.w, a.h) // Set size before switching view 232 + a.repoView.SetSize(a.w, a.h-footerHeight) // Set size before switching view 229 233 a.active = a.repoView 230 234 a.search.loading = false 231 235 return a, cmd ··· 241 245 a.actx.collection = msg.records.Collection() 242 246 a.actx.record = nil 243 247 cmd := a.rlist.SetRecords(msg.records.Records) 244 - a.rlist.SetSize(a.w, a.h) // Set size before switching view 248 + a.rlist.SetSize(a.w, a.h-footerHeight) // Set size before switching view 245 249 a.active = a.rlist 246 250 a.search.loading = false 247 251 return a, cmd ··· 252 256 a.actx.collection = msg.record.Record.Collection() 253 257 a.actx.record = msg.record.Record 254 258 a.recordView.SetRecord(msg.record.Record) 255 - a.recordView.SetSize(a.w, a.h) // Set size before switching view 259 + a.recordView.SetSize(a.w, a.h-footerHeight) // Set size before switching view 256 260 a.active = a.recordView 257 261 return a, nil 258 262 259 263 case jetEventSelectedMsg: 260 264 a.jetEventView.SetEvent(msg.evt) 261 - a.jetEventView.SetSize(a.w, a.h) 265 + a.jetEventView.SetSize(a.w, a.h-footerHeight) 262 266 a.active = a.jetEventView 263 267 a.jetSreamActive = false 264 268 return a, nil ··· 326 330 } 327 331 } 328 332 333 + func (a *App) footer() string { 334 + key := func(k string) string { 335 + return lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("205")).Render(k) 336 + } 337 + sep := dimStyle.Render(" · ") 338 + content := key("esc") + dimStyle.Render(" back") + 339 + sep + key("ctrl+k") + dimStyle.Render(" search") + 340 + sep + key("ctrl+j") + dimStyle.Render(" jetstream") 341 + return lipgloss.NewStyle().Width(a.w).Align(lipgloss.Right).Render(content) 342 + } 343 + 329 344 func (a *App) View() string { 330 345 if a.loading { 331 346 return "Loading... " + a.spinner.View() 332 347 } 348 + var body string 333 349 if a.jetSreamActive { 334 - return a.jetstream.View() 350 + body = a.jetstream.View() 351 + } else { 352 + body = a.active.View() 335 353 } 336 - return a.active.View() 354 + return lipgloss.JoinVertical(lipgloss.Left, body, a.footer()) 337 355 } 338 356 339 357 // Message types
+2 -13
ui/repo.go
··· 173 173 return 174 174 } 175 175 headerHeight := lipgloss.Height(r.header) 176 - footerHeight := 2 // "\n" + help text line 177 176 178 177 // List gets all remaining space 179 - listHeight := r.height - headerHeight - footerHeight 178 + listHeight := r.height - headerHeight 180 179 if listHeight < 5 { 181 180 listHeight = 5 182 181 } ··· 188 187 if r.repo == nil { 189 188 return "No repository loaded" 190 189 } 191 - 192 - // Footer help text 193 - footer := dimStyle.Render("Press Esc to go back • ↑/↓ or j/k to navigate • Ctrl+C to quit") 194 - 195 - // Join header (fixed), list (scrollable), and footer 196 - return lipgloss.JoinVertical( 197 - lipgloss.Left, 198 - r.header, 199 - r.clist.View(), 200 - "\n"+footer, 201 - ) 190 + return lipgloss.JoinVertical(lipgloss.Left, r.header, r.clist.View()) 202 191 }