tangled
alpha
login
or
join now
treethought.xyz
/
attie
5
fork
atom
AT Protocol Terminal Interface Explorer
5
fork
atom
overview
issues
pulls
pipelines
add global footer
Cam Sweeney
3 weeks ago
26f2cfba
b35a01e2
+32
-25
2 changed files
expand all
collapse all
unified
split
ui
app.go
repo.go
+30
-12
ui/app.go
···
9
"github.com/bluesky-social/indigo/atproto/syntax"
10
"github.com/charmbracelet/bubbles/spinner"
11
tea "github.com/charmbracelet/bubbletea"
0
12
"github.com/treethought/attie/at"
13
)
14
···
92
return a.active.Init()
93
}
94
0
0
95
func (a *App) resizeChildren() tea.Cmd {
96
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)
0
103
return tea.Batch(cmds...)
104
}
105
···
225
a.actx.collection = ""
226
a.actx.record = nil
227
cmd := a.repoView.SetRepo(msg.repo)
228
-
a.repoView.SetSize(a.w, a.h) // Set size before switching view
229
a.active = a.repoView
230
a.search.loading = false
231
return a, cmd
···
241
a.actx.collection = msg.records.Collection()
242
a.actx.record = nil
243
cmd := a.rlist.SetRecords(msg.records.Records)
244
-
a.rlist.SetSize(a.w, a.h) // Set size before switching view
245
a.active = a.rlist
246
a.search.loading = false
247
return a, cmd
···
252
a.actx.collection = msg.record.Record.Collection()
253
a.actx.record = msg.record.Record
254
a.recordView.SetRecord(msg.record.Record)
255
-
a.recordView.SetSize(a.w, a.h) // Set size before switching view
256
a.active = a.recordView
257
return a, nil
258
259
case jetEventSelectedMsg:
260
a.jetEventView.SetEvent(msg.evt)
261
-
a.jetEventView.SetSize(a.w, a.h)
262
a.active = a.jetEventView
263
a.jetSreamActive = false
264
return a, nil
···
326
}
327
}
328
0
0
0
0
0
0
0
0
0
0
0
329
func (a *App) View() string {
330
if a.loading {
331
return "Loading... " + a.spinner.View()
332
}
0
333
if a.jetSreamActive {
334
-
return a.jetstream.View()
0
0
335
}
336
-
return a.active.View()
337
}
338
339
// Message types
···
9
"github.com/bluesky-social/indigo/atproto/syntax"
10
"github.com/charmbracelet/bubbles/spinner"
11
tea "github.com/charmbracelet/bubbletea"
12
+
"github.com/charmbracelet/lipgloss"
13
"github.com/treethought/attie/at"
14
)
15
···
93
return a.active.Init()
94
}
95
96
+
const footerHeight = 1
97
+
98
func (a *App) resizeChildren() tea.Cmd {
99
cmds := []tea.Cmd{}
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)
107
return tea.Batch(cmds...)
108
}
109
···
229
a.actx.collection = ""
230
a.actx.record = nil
231
cmd := a.repoView.SetRepo(msg.repo)
232
+
a.repoView.SetSize(a.w, a.h-footerHeight) // Set size before switching view
233
a.active = a.repoView
234
a.search.loading = false
235
return a, cmd
···
245
a.actx.collection = msg.records.Collection()
246
a.actx.record = nil
247
cmd := a.rlist.SetRecords(msg.records.Records)
248
+
a.rlist.SetSize(a.w, a.h-footerHeight) // Set size before switching view
249
a.active = a.rlist
250
a.search.loading = false
251
return a, cmd
···
256
a.actx.collection = msg.record.Record.Collection()
257
a.actx.record = msg.record.Record
258
a.recordView.SetRecord(msg.record.Record)
259
+
a.recordView.SetSize(a.w, a.h-footerHeight) // Set size before switching view
260
a.active = a.recordView
261
return a, nil
262
263
case jetEventSelectedMsg:
264
a.jetEventView.SetEvent(msg.evt)
265
+
a.jetEventView.SetSize(a.w, a.h-footerHeight)
266
a.active = a.jetEventView
267
a.jetSreamActive = false
268
return a, nil
···
330
}
331
}
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
+
344
func (a *App) View() string {
345
if a.loading {
346
return "Loading... " + a.spinner.View()
347
}
348
+
var body string
349
if a.jetSreamActive {
350
+
body = a.jetstream.View()
351
+
} else {
352
+
body = a.active.View()
353
}
354
+
return lipgloss.JoinVertical(lipgloss.Left, body, a.footer())
355
}
356
357
// Message types
+2
-13
ui/repo.go
···
173
return
174
}
175
headerHeight := lipgloss.Height(r.header)
176
-
footerHeight := 2 // "\n" + help text line
177
178
// List gets all remaining space
179
-
listHeight := r.height - headerHeight - footerHeight
180
if listHeight < 5 {
181
listHeight = 5
182
}
···
188
if r.repo == nil {
189
return "No repository loaded"
190
}
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
-
)
202
}
···
173
return
174
}
175
headerHeight := lipgloss.Height(r.header)
0
176
177
// List gets all remaining space
178
+
listHeight := r.height - headerHeight
179
if listHeight < 5 {
180
listHeight = 5
181
}
···
187
if r.repo == nil {
188
return "No repository loaded"
189
}
190
+
return lipgloss.JoinVertical(lipgloss.Left, r.header, r.clist.View())
0
0
0
0
0
0
0
0
0
0
191
}