summaryrefslogtreecommitdiff
path: root/internal/client/ui/loadscreen/loadscreen.go
diff options
context:
space:
mode:
authorKyren223 <Kyren223@proton.me>2024-11-09 21:36:11 +0200
committerKyren223 <Kyren223@proton.me>2024-11-09 21:36:11 +0200
commit1b2c19149631f0397d1532644e2a2ce3d6a44e11 (patch)
tree03e362bdcbb024c6ee08b2c86fbc29159e46980b /internal/client/ui/loadscreen/loadscreen.go
parent8d97e7000c6579180d37c977edf5d071e4ff1219 (diff)
feat: add WIP loading screen, messed around with custom spinners
Diffstat (limited to 'internal/client/ui/loadscreen/loadscreen.go')
-rw-r--r--internal/client/ui/loadscreen/loadscreen.go208
1 files changed, 208 insertions, 0 deletions
diff --git a/internal/client/ui/loadscreen/loadscreen.go b/internal/client/ui/loadscreen/loadscreen.go
new file mode 100644
index 0000000..6639f7d
--- /dev/null
+++ b/internal/client/ui/loadscreen/loadscreen.go
@@ -0,0 +1,208 @@
+package loadscreen
+
+import (
+ "log"
+ "time"
+
+ "github.com/charmbracelet/bubbles/spinner"
+ "github.com/charmbracelet/bubbles/viewport"
+ tea "github.com/charmbracelet/bubbletea"
+ "github.com/charmbracelet/lipgloss"
+
+ "github.com/kyren223/eko/internal/client/ui"
+ "github.com/kyren223/eko/pkg/assert"
+)
+
+var (
+ style = lipgloss.NewStyle().Border(lipgloss.ThickBorder()).Padding(1)
+ _ = spinner.Spinner{
+ Frames: []string{
+ "██▓▓▒▒\n ░░\n ",
+ "▓▓▒▒░░\n██ \n ",
+ "▒▒░░ \n▓▓ \n██ ",
+ "░░ \n▒▒ \n▓▓██ ",
+ " \n░░ \n▒▒▓▓██",
+ " \n ██\n░░▒▒▓▓",
+ " ██\n ▓▓\n ░░▒▒",
+ " ██▓▓\n ▒▒\n ░░",
+ },
+ FPS: time.Second / 8,
+ }
+
+ apple = lipgloss.NewStyle().Foreground(lipgloss.Color("#FF0000")).Render("██")
+ // loadingFrames = circleTrail(5, 5, 0, true, " ", "░░", "▒▒", "▓▓", "██")
+ // loadingFrames = circleTrail(5, 5, 0, true, " ", "░░", "▒▒", "▓▓", "██", " ", " ", " ", apple)
+ // loadingFrames = circleTrail(5, 5, 0, true, " ", "░░", "░░", "▒▒", "▒▒", "▓▓", "▓▓", "██", " ", " ", " ", apple)
+ loadingFrames = func() []string {
+ green := lipgloss.NewStyle().Foreground(lipgloss.Color("#00FF00"))
+ trail := []string{"░░", "░░", "▒▒", "▒▒", "▓▓", "██", " ", " "}
+ for i := range trail {
+ trail[i] = green.Render(trail[i])
+ }
+ trail = append(trail, apple)
+ return circleTrail(5, 5, 0, true, " ", trail...)
+ }()
+ loading = spinner.Spinner{
+ Frames: loadingFrames,
+ FPS: time.Second / time.Duration(len(loadingFrames)),
+ }
+)
+
+func circleTrail(width int, height int, offset int, clockwise bool, bg string, trail ...string) (states []string) {
+ slots := (width+height)*2 - 4
+ slotWidth := lipgloss.Width(bg)
+ slotHeight := lipgloss.Height(bg)
+
+ assert.Assert(slots-len(trail) >= 0, "not enough space to fit trail")
+ assert.AddData("slotWidth", slotWidth)
+ assert.AddData("slotHeight", slotHeight)
+ defer assert.RemoveData("slotWidth")
+ defer assert.RemoveData("slotHeight")
+ for _, elem := range trail {
+ w := lipgloss.Width(elem)
+ h := lipgloss.Height(elem)
+ assert.AddData("elemWidth", w)
+ assert.AddData("elemHeight", h)
+ assert.Assert(slotWidth == w, "bg and all trails must have the same height")
+ assert.Assert(slotHeight == h, "bg and all trails must have the same height")
+ assert.RemoveData("elemWidth")
+ assert.RemoveData("elemHeight")
+ }
+
+ matrix := make([][]string, height)
+ for i := range matrix {
+ matrix[i] = make([]string, width)
+ }
+
+ for i := 0; i < slots; i++ {
+ for y := range matrix {
+ for x := range matrix[y] {
+ matrix[y][x] = bg
+ }
+ }
+
+ x, y := 0, 0
+ for j := 0; j < i+offset; j++ {
+ if clockwise {
+ if y == 0 && x != width-1 {
+ x++
+ } else if x == width-1 && y != height-1 {
+ y++
+ } else if y == height-1 && x != 0 {
+ x--
+ } else if x == 0 && y != 0 {
+ y--
+ }
+ } else {
+ if x == 0 && y != height-1 {
+ y++
+ } else if y == height-1 && x != width-1 {
+ x++
+ } else if x == width-1 && y != 0 {
+ y--
+ } else if y == 0 && x != 0 {
+ x--
+ }
+ }
+ }
+
+ for _, trail := range trail {
+ matrix[y][x] = trail
+ if clockwise {
+ if y == 0 && x != width-1 {
+ x++
+ } else if x == width-1 && y != height-1 {
+ y++
+ } else if y == height-1 && x != 0 {
+ x--
+ } else if x == 0 && y != 0 {
+ y--
+ }
+ } else {
+ if x == 0 && y != height-1 {
+ y++
+ } else if y == height-1 && x != width-1 {
+ x++
+ } else if x == width-1 && y != 0 {
+ y--
+ } else if y == 0 && x != 0 {
+ x--
+ }
+ }
+ }
+
+ var rows []string
+ for _, row := range matrix {
+ rows = append(rows, lipgloss.JoinHorizontal(0, row...))
+ }
+ state := lipgloss.JoinVertical(0, rows...)
+ states = append(states, state)
+ }
+
+ return states
+}
+
+type Model struct {
+ sp spinner.Model
+ content string
+
+ Style lipgloss.Style
+
+ delta time.Time
+ index int
+}
+
+func New() Model {
+ return Model{
+ sp: spinner.New(spinner.WithSpinner(loading)),
+ content: "Update Failed - retrying in 3 sec...",
+ Style: style,
+ }
+}
+
+func (m Model) Init() tea.Cmd {
+ return m.sp.Tick
+}
+
+func (m Model) View() string {
+ vp := viewport.New(40, 5)
+ vp.Style = m.Style
+ vp.SetContent(m.content)
+
+ result := lipgloss.JoinVertical(lipgloss.Center, m.sp.View(), vp.View())
+
+ return lipgloss.Place(
+ ui.Width, ui.Height,
+ lipgloss.Center, lipgloss.Center,
+ result,
+ )
+}
+
+func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
+ switch msg := msg.(type) {
+
+ case tea.KeyMsg:
+ key := msg.Type
+ switch key {
+ case tea.KeyCtrlC:
+ return m, tea.Quit
+
+ case tea.KeyCtrlT:
+ return m, m.sp.Tick
+ }
+
+ case spinner.TickMsg:
+ if m.index == 0 {
+ m.delta = time.Now()
+ }
+ delta := time.Since(m.delta)
+ log.Printf("Frame %v Delta %v\n", m.index, delta)
+ m.index++
+ m.delta = time.Now()
+ var cmd tea.Cmd
+ m.sp, cmd = m.sp.Update(msg)
+ return m, cmd
+ }
+
+ return m, nil
+}