182 lines
4.1 KiB
Go
182 lines
4.1 KiB
Go
package ui
|
|
|
|
import (
|
|
"fmt"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"git.bullercodeworks.com/brian/boltbrowser/models"
|
|
"git.bullercodeworks.com/brian/wandle"
|
|
"git.bullercodeworks.com/brian/widdles"
|
|
"github.com/nsf/termbox-go"
|
|
"github.com/spf13/viper"
|
|
bolt "go.etcd.io/bbolt"
|
|
)
|
|
|
|
const (
|
|
BS_CmdRefresh = BrowseId | iota
|
|
BS_CmdDBTimeout
|
|
)
|
|
|
|
type BrowseMsg struct {
|
|
source int
|
|
data interface{}
|
|
err error
|
|
}
|
|
|
|
type browseScreen struct {
|
|
ui *Ui
|
|
dbPath string
|
|
db *models.BoltDB
|
|
|
|
status *widdles.Text
|
|
|
|
treePane *BoltTreePane
|
|
rightPane ViewPort
|
|
}
|
|
|
|
func NewBrowseScreen(u *Ui) *browseScreen { return &browseScreen{ui: u} }
|
|
|
|
func (s *browseScreen) Init() wandle.Cmd {
|
|
w, h := termbox.Size()
|
|
dbs := viper.GetStringSlice("dbs")
|
|
dbidx := viper.GetInt("dbidx")
|
|
if len(dbs) <= dbidx {
|
|
return wandle.Quit
|
|
}
|
|
s.dbPath = dbs[dbidx]
|
|
s.treePane = NewBoltTreePane(0, 3, w/2, h-2)
|
|
|
|
s.status = widdles.NewText("Press '?' for help", 0, (h - 1), w, 1)
|
|
|
|
return func() wandle.Msg {
|
|
timeout, err := time.ParseDuration(viper.GetString("version"))
|
|
if err != nil {
|
|
timeout = time.Second
|
|
}
|
|
db, err := bolt.Open(s.dbPath, 0600, &bolt.Options{Timeout: timeout})
|
|
if err == bolt.ErrTimeout {
|
|
return func() wandle.Msg { return BrowseMsg{source: BS_CmdDBTimeout} }
|
|
}
|
|
s.db = models.NewBoltDB(db)
|
|
if viper.GetBool("readonly") {
|
|
db.Close()
|
|
}
|
|
s.treePane.SetDB(s.db)
|
|
s.resizeWindow(w, h)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func (s *browseScreen) Update(msg wandle.Msg) wandle.Cmd {
|
|
switch msg := msg.(type) {
|
|
case BrowseMsg:
|
|
return s.handleBrowseMsg(msg)
|
|
case termbox.Event:
|
|
return s.handleTermboxEvent(msg)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *browseScreen) handleBrowseMsg(msg BrowseMsg) wandle.Cmd {
|
|
switch msg.source {
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *browseScreen) handleTermboxEvent(msg termbox.Event) wandle.Cmd {
|
|
switch msg.Type {
|
|
case termbox.EventKey:
|
|
if cmd := s.treePane.Update(msg); cmd != nil {
|
|
return cmd
|
|
}
|
|
if msg.Ch == '?' {
|
|
return wandle.SwitchScreenCmd(NewAboutScreen(s.ui))
|
|
} else if msg.Ch == 'q' || msg.Key == termbox.KeyCtrlC {
|
|
return wandle.Quit
|
|
} else if msg.Key == termbox.KeyCtrlN {
|
|
// Next File
|
|
idx := viper.GetInt("dbidx") + 1
|
|
if idx >= len(viper.GetStringSlice("dbs")) {
|
|
s.setStatus("Already at last file", time.Second)
|
|
} else {
|
|
viper.Set("dbidx", idx)
|
|
return wandle.SwitchScreenCmd(NewBrowseScreen(s.ui))
|
|
}
|
|
} else if msg.Key == termbox.KeyCtrlP {
|
|
// Previous File
|
|
idx := viper.GetInt("dbidx") - 1
|
|
if idx < 0 {
|
|
s.setStatus("Already at first file", time.Second)
|
|
} else {
|
|
viper.Set("dbidx", idx)
|
|
return wandle.SwitchScreenCmd(NewBrowseScreen(s.ui))
|
|
}
|
|
}
|
|
case termbox.EventResize:
|
|
s.resizeWindow(msg.Width, msg.Height)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *browseScreen) resizeWindow(w, h int) {
|
|
lw := w
|
|
if lw > 80 {
|
|
lw = lw / 2
|
|
}
|
|
// Re-build Tree pane
|
|
s.treePane.SetWidth(lw)
|
|
// Re-build Right Pane buffer
|
|
s.rightPane = ViewPort{
|
|
x: lw + 1,
|
|
width: w - lw,
|
|
height: h - 2,
|
|
}
|
|
}
|
|
|
|
func (s *browseScreen) View(style wandle.Style) {
|
|
w, h := termbox.Size()
|
|
s.drawHeader(style)
|
|
s.treePane.View(style)
|
|
if w > 80 {
|
|
x := s.rightPane.GetX() - 1
|
|
termbox.SetCell(x, 1, '╦', style.Foreground, style.Background)
|
|
wandle.Fill('║', x, 2, x, h-1, style)
|
|
s.rightPane.View(style)
|
|
}
|
|
s.status.View(style)
|
|
}
|
|
|
|
func (s *browseScreen) drawHeader(style wandle.Style) {
|
|
width, _ := termbox.Size()
|
|
headerStringLen := func(fileName string) int {
|
|
return len("boltbrowser") + len(fileName) + 1
|
|
}
|
|
headerFileName := s.dbPath
|
|
if headerStringLen(headerFileName) > width {
|
|
headerFileName = filepath.Base(headerFileName)
|
|
}
|
|
headerString := "boltbrowser" + ": " + headerFileName
|
|
count := ((width - len(headerString)) / 2) + 1
|
|
if count < 0 {
|
|
count = 0
|
|
}
|
|
spaces := strings.Repeat(" ", count)
|
|
wandle.Print(0, 0, style, fmt.Sprintf("%s%s%s", spaces, headerString, spaces))
|
|
wandle.Fill('═', 0, 1, width, 1, style)
|
|
}
|
|
|
|
func (s *browseScreen) setStatus(status string, timeout time.Duration) {
|
|
s.status.SetText(status)
|
|
if timeout > 0 {
|
|
go func() {
|
|
time.Sleep(timeout)
|
|
if s.status.GetText() == status {
|
|
s.status.SetText("Press '?' for help")
|
|
s.ui.wandle.Send(BS_CmdRefresh)
|
|
}
|
|
}()
|
|
}
|
|
}
|