73 lines
1.3 KiB
Go
73 lines
1.3 KiB
Go
|
package tui
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"fmt"
|
||
|
"sync/atomic"
|
||
|
"time"
|
||
|
|
||
|
"github.com/gdamore/tcell/v2"
|
||
|
"github.com/rivo/tview"
|
||
|
)
|
||
|
|
||
|
type LoadingBar struct {
|
||
|
*tview.Box
|
||
|
view *tview.TextView
|
||
|
secondsElapsed atomic.Int64
|
||
|
needDrawFunc func()
|
||
|
reset func()
|
||
|
}
|
||
|
|
||
|
func NewLoadingBar(needDrawFunc func()) *LoadingBar {
|
||
|
b := &LoadingBar{
|
||
|
Box: tview.NewBox(),
|
||
|
view: tview.NewTextView(),
|
||
|
needDrawFunc: needDrawFunc,
|
||
|
}
|
||
|
b.view.SetBackgroundColor(tview.Styles.PrimaryTextColor)
|
||
|
b.view.SetTextColor(b.GetBackgroundColor())
|
||
|
|
||
|
return b
|
||
|
}
|
||
|
|
||
|
func (b *LoadingBar) Start(ctx context.Context) {
|
||
|
ctx, b.reset = context.WithCancel(ctx)
|
||
|
|
||
|
go func() {
|
||
|
ticker := time.NewTicker(1 * time.Second)
|
||
|
defer ticker.Stop()
|
||
|
|
||
|
b.secondsElapsed.Store(0)
|
||
|
for {
|
||
|
select {
|
||
|
case <-ctx.Done():
|
||
|
return
|
||
|
case <-ticker.C:
|
||
|
b.secondsElapsed.Add(1)
|
||
|
b.needDrawFunc()
|
||
|
}
|
||
|
}
|
||
|
}()
|
||
|
}
|
||
|
|
||
|
func (b *LoadingBar) Stop() {
|
||
|
b.reset()
|
||
|
}
|
||
|
|
||
|
func (b *LoadingBar) Draw(screen tcell.Screen) {
|
||
|
seconds := b.secondsElapsed.Load()
|
||
|
|
||
|
var time string
|
||
|
switch {
|
||
|
case seconds < 60:
|
||
|
time = fmt.Sprintf("%ds", seconds)
|
||
|
default:
|
||
|
time = fmt.Sprintf("%dm%ds", seconds/60, seconds%60)
|
||
|
}
|
||
|
b.view.SetText(fmt.Sprintf(" Loading... %s (press Escape to cancel) ", time))
|
||
|
|
||
|
x, y, width, _ := b.GetInnerRect()
|
||
|
b.view.SetRect(x, y, width, 1)
|
||
|
b.view.Draw(screen)
|
||
|
}
|