goncdu/tui/tui.go
ZZY 051fa629df refactor(tui): 重构 UI 设计
- 将 UI 组件分解为更小的模块,提高可维护性
- 优化了列表渲染和路径输入逻辑
- 改进了帮助界面的显示方式
- 调整了 UI 样式,去除了冗余代码
2025-02-12 18:01:45 +08:00

124 lines
2.2 KiB
Go

// go get github.com/rivo/tview@master
package tui
import (
"errors"
node "git.zzyxyz.com/zzy/goncdu/node"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)
type UI struct {
app *tview.Application
msg string
err string
main *ListFrame
list tview.Primitive
input tview.Primitive
modal tview.Primitive
}
func NewUI(n *node.NodeManager) *UI {
ui := &UI{
app: tview.NewApplication(),
msg: "",
err: "",
main: &ListFrame{node: n},
}
return ui
}
func (ui *UI) MakeAllUI() {
ui.list = ui.main.MakeListFrameUI(func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
case tcell.KeyRight:
idx := ui.main.list.GetCurrentItem()
if len(ui.main.nodes) == 0 {
ui.err = errors.New("no children nodes").Error()
break
}
name := ui.main.nodes[idx].GetPath()
if err := ui.main.node.GoIn(name); err != nil {
ui.err = err.Error()
break
}
case tcell.KeyLeft:
if err := ui.main.node.GoOut(); err != nil {
ui.err = err.Error()
}
case tcell.KeyRune:
switch event.Rune() {
case 'q':
ui.app.Stop()
case '?':
// show help
ui.app.SetRoot(ui.modal, false)
case 'R':
ui.app.SetRoot(ui.input, true)
case 'S':
if err := ui.main.node.SaveToFile(); err != nil {
ui.err = err.Error()
}
case 'L':
if err := ui.main.node.LoadFromFile(); err != nil {
ui.err = err.Error()
}
default:
return event
}
default:
return event
}
// END:
ui.main.RenderList()
return nil
})
ui.modal = MakeHelpUI(func() {
ui.app.SetRoot(ui.list, true)
})
ui.input = MakeInputUI(func(path string) error {
valid := ui.main.node.SetRootPath(path)
if valid {
ui.app.SetRoot(ui.list, true)
ui.scanPath()
return nil
} else {
return errors.New("invalid path")
}
})
}
func (ui *UI) run() {
if err := ui.app.Run(); err != nil {
panic(err)
}
}
func (ui *UI) scanPath() {
err := ui.main.node.Scan()
if err != nil {
ui.err = err.Error()
}
ui.main.RenderList()
}
func ShowMain(entry *node.NodeManager) {
ui := NewUI(entry)
ui.MakeAllUI()
// need input path
if entry.VaildRoot() {
ui.app.SetRoot(ui.list, true)
ui.scanPath()
} else {
ui.app.SetRoot(ui.input, true)
}
ui.run()
}