Files
2024-07-15 21:08:32 -06:00

111 lines
2.7 KiB
Go

package viewer
import (
"time"
"github.com/charmbracelet/bubbles/spinner"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
type footerModel struct {
spinner spinner.Model
loading bool
dbName string
width int
flashRed bool
flashing bool
ErrMsg string
}
type FooterFlash string
func NewFooterModel(dbName string) footerModel {
s := spinner.New()
s.Spinner = spinner.Dot
s.Style = lipgloss.NewStyle().Foreground(red)
return footerModel{spinner: s, dbName: dbName}
}
func (m *footerModel) Init() tea.Cmd {
return m.spinner.Tick
}
func tickCmd(msg string) tea.Cmd {
ms := time.Millisecond * 100
if msg == "reset" {
ms = time.Millisecond * 700
}
return tea.Tick(ms, func(_ time.Time) tea.Msg {
return FooterFlash(msg)
})
}
func (m *footerModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case StillLoadingResults:
// don't allow the flashing routing to start again if it's already began
// it will look ugly if multiple flashes are running
if !m.flashing {
// immediately mark this as flashing
m.flashing = true
m.flashRed = true
// toggle to normal color after timeout
return m, tickCmd("normal")
}
return m, nil
case FooterFlash:
switch msg {
case "normal":
m.flashRed = false
// toggle to red after timeout
return m, tickCmd("red")
case "red":
m.flashRed = true
// toggle to normal color after timeout
return m, tickCmd("debounce")
case "debounce":
m.flashRed = false
// toggle the resetting of the flashing flag
// after a longer timeout so that the bar doesn't flash like crazy
// if the user keeps pressing next page
return m, tickCmd("reset")
case "reset":
m.flashing = false
}
return m, nil
case tea.KeyMsg:
return m, nil
default:
var cmd tea.Cmd
m.spinner, cmd = m.spinner.Update(msg)
return m, cmd
}
}
func (m *footerModel) View() string {
barColor := surface0
if m.ErrMsg != "" || m.flashRed {
barColor = pink
}
msg := "Loading results"
if m.ErrMsg != "" {
msg = m.ErrMsg
}
dbFooter := mainStyle.Margin(0, 0, 0, 0).Padding(0, 2).Background(lavender).Foreground(base).AlignVertical(lipgloss.Bottom).Bold(true).Render("Database")
spinnerWidth := m.width - 12 - 10 - 2 - len(m.dbName) - len(msg) - 1
middleBarStyle := mainStyle.Background(barColor).Foreground(defaultTextColor)
dbFooter += middleBarStyle.PaddingLeft(1).Render(m.dbName)
if m.loading {
dbFooter += middleBarStyle.Width(spinnerWidth).AlignHorizontal(lipgloss.Right).Render(m.spinner.View())
dbFooter += middleBarStyle.PaddingRight(1).Render(msg)
} else {
dbFooter += middleBarStyle.Width(spinnerWidth + len(msg) + 2).Render()
}
dbFooter += mainStyle.Background(overlay2).Padding(0, 2).Render("? help")
return dbFooter
}