mirror of
https://github.com/teest114514/chatlog_alpha.git
synced 2026-04-06 20:38:45 +08:00
Refactor UI: replace dashboard and sidebar with infobar
Removed dashboard, sidebar, layout, and logs components, consolidating status and account information into a new infobar component. Updated app structure to use tabbed pages and the infobar for displaying key information. Simplified menu and settings handling, and removed legacy UI code for a more streamlined interface.
This commit is contained in:
@@ -1,59 +0,0 @@
|
||||
package dashboard
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
"github.com/sjzar/chatlog/internal/ui/style"
|
||||
)
|
||||
|
||||
type Dashboard struct {
|
||||
*tview.Table
|
||||
}
|
||||
|
||||
func New() *Dashboard {
|
||||
d := &Dashboard{
|
||||
Table: tview.NewTable(),
|
||||
}
|
||||
|
||||
d.SetBorders(false)
|
||||
d.SetBorder(true)
|
||||
d.SetTitle(" 状态概览 ")
|
||||
d.SetBorderColor(style.BorderColor)
|
||||
d.SetBackgroundColor(style.BgColor)
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *Dashboard) Update(data map[string]string) {
|
||||
d.Clear()
|
||||
|
||||
row := 0
|
||||
headerColor := style.InfoBarItemFgColor
|
||||
|
||||
keys := []string{
|
||||
"Account", "PID", "Status", "ExePath",
|
||||
"Platform", "Version", "Session", "Data Key",
|
||||
"Image Key", "Data Usage", "Data Dir",
|
||||
"Work Usage", "Work Dir", "HTTP Server", "Auto Decrypt",
|
||||
}
|
||||
|
||||
for _, key := range keys {
|
||||
val, ok := data[key]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
d.SetCell(row, 0, tview.NewTableCell(fmt.Sprintf(" [%s::b]%s", headerColor, key)).
|
||||
SetAlign(tview.AlignRight).
|
||||
SetExpansion(1).
|
||||
SetTextColor(style.FgColor))
|
||||
|
||||
d.SetCell(row, 1, tview.NewTableCell(fmt.Sprintf(" %s", val)).
|
||||
SetAlign(tview.AlignLeft).
|
||||
SetExpansion(3).
|
||||
SetTextColor(style.FgColor))
|
||||
|
||||
row++
|
||||
}
|
||||
}
|
||||
230
internal/ui/infobar/infobar.go
Normal file
230
internal/ui/infobar/infobar.go
Normal file
@@ -0,0 +1,230 @@
|
||||
package infobar
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/sjzar/chatlog/internal/ui/style"
|
||||
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/rivo/tview"
|
||||
)
|
||||
|
||||
const (
|
||||
Title = "infobar"
|
||||
)
|
||||
|
||||
// InfoBarViewHeight info bar height.
|
||||
const (
|
||||
InfoBarViewHeight = 8
|
||||
accountRow = 0
|
||||
statusRow = 1
|
||||
platformRow = 2
|
||||
sessionRow = 3
|
||||
dataUsageRow = 4
|
||||
workUsageRow = 5
|
||||
httpServerRow = 6
|
||||
autoDecryptRow = 7
|
||||
|
||||
// 列索引
|
||||
labelCol1 = 0 // 第一列标签
|
||||
valueCol1 = 1 // 第一列值
|
||||
labelCol2 = 2 // 第二列标签
|
||||
valueCol2 = 3 // 第二列值
|
||||
totalCols = 4
|
||||
)
|
||||
|
||||
// InfoBar implements the info bar primitive.
|
||||
type InfoBar struct {
|
||||
*tview.Box
|
||||
title string
|
||||
table *tview.Table
|
||||
}
|
||||
|
||||
// NewInfoBar returns info bar view.
|
||||
func New() *InfoBar {
|
||||
table := tview.NewTable()
|
||||
headerColor := style.InfoBarItemFgColor
|
||||
|
||||
// Account 和 PID 行
|
||||
table.SetCell(
|
||||
accountRow,
|
||||
labelCol1,
|
||||
tview.NewTableCell(fmt.Sprintf(" [%s::]%s", headerColor, "Account:")),
|
||||
)
|
||||
table.SetCell(accountRow, valueCol1, tview.NewTableCell(""))
|
||||
|
||||
table.SetCell(
|
||||
accountRow,
|
||||
labelCol2,
|
||||
tview.NewTableCell(fmt.Sprintf(" [%s::]%s", headerColor, "PID:")),
|
||||
)
|
||||
table.SetCell(accountRow, valueCol2, tview.NewTableCell(""))
|
||||
|
||||
// Status 和 ExePath 行
|
||||
table.SetCell(
|
||||
statusRow,
|
||||
labelCol1,
|
||||
tview.NewTableCell(fmt.Sprintf(" [%s::]%s", headerColor, "Status:")),
|
||||
)
|
||||
table.SetCell(statusRow, valueCol1, tview.NewTableCell(""))
|
||||
|
||||
table.SetCell(
|
||||
statusRow,
|
||||
labelCol2,
|
||||
tview.NewTableCell(fmt.Sprintf(" [%s::]%s", headerColor, "ExePath:")),
|
||||
)
|
||||
table.SetCell(statusRow, valueCol2, tview.NewTableCell(""))
|
||||
|
||||
// Platform 和 Version 行
|
||||
table.SetCell(
|
||||
platformRow,
|
||||
labelCol1,
|
||||
tview.NewTableCell(fmt.Sprintf(" [%s::]%s", headerColor, "Platform:")),
|
||||
)
|
||||
table.SetCell(platformRow, valueCol1, tview.NewTableCell(""))
|
||||
|
||||
table.SetCell(
|
||||
platformRow,
|
||||
labelCol2,
|
||||
tview.NewTableCell(fmt.Sprintf(" [%s::]%s", headerColor, "Version:")),
|
||||
)
|
||||
table.SetCell(platformRow, valueCol2, tview.NewTableCell(""))
|
||||
|
||||
// Session 和 Data Key 行
|
||||
table.SetCell(
|
||||
sessionRow,
|
||||
labelCol1,
|
||||
tview.NewTableCell(fmt.Sprintf(" [%s::]%s", headerColor, "Session:")),
|
||||
)
|
||||
table.SetCell(sessionRow, valueCol1, tview.NewTableCell(""))
|
||||
|
||||
table.SetCell(
|
||||
sessionRow,
|
||||
labelCol2,
|
||||
tview.NewTableCell(fmt.Sprintf(" [%s::]%s", headerColor, "Data Key:")),
|
||||
)
|
||||
table.SetCell(sessionRow, valueCol2, tview.NewTableCell(""))
|
||||
|
||||
// Data Usage 和 Data Dir 行
|
||||
table.SetCell(
|
||||
dataUsageRow,
|
||||
labelCol1,
|
||||
tview.NewTableCell(fmt.Sprintf(" [%s::]%s", headerColor, "Data Usage:")),
|
||||
)
|
||||
table.SetCell(dataUsageRow, valueCol1, tview.NewTableCell(""))
|
||||
|
||||
table.SetCell(
|
||||
dataUsageRow,
|
||||
labelCol2,
|
||||
tview.NewTableCell(fmt.Sprintf(" [%s::]%s", headerColor, "Data Dir:")),
|
||||
)
|
||||
table.SetCell(dataUsageRow, valueCol2, tview.NewTableCell(""))
|
||||
|
||||
// Work Usage 和 Work Dir 行
|
||||
table.SetCell(
|
||||
workUsageRow,
|
||||
labelCol1,
|
||||
tview.NewTableCell(fmt.Sprintf(" [%s::]%s", headerColor, "Work Usage:")),
|
||||
)
|
||||
table.SetCell(workUsageRow, valueCol1, tview.NewTableCell(""))
|
||||
|
||||
table.SetCell(
|
||||
workUsageRow,
|
||||
labelCol2,
|
||||
tview.NewTableCell(fmt.Sprintf(" [%s::]%s", headerColor, "Work Dir:")),
|
||||
)
|
||||
table.SetCell(workUsageRow, valueCol2, tview.NewTableCell(""))
|
||||
|
||||
// HTTP Server 行
|
||||
table.SetCell(
|
||||
httpServerRow,
|
||||
labelCol1,
|
||||
tview.NewTableCell(fmt.Sprintf(" [%s::]%s", headerColor, "HTTP Server:")),
|
||||
)
|
||||
table.SetCell(httpServerRow, valueCol1, tview.NewTableCell(""))
|
||||
|
||||
table.SetCell(
|
||||
httpServerRow,
|
||||
labelCol2,
|
||||
tview.NewTableCell(fmt.Sprintf(" [%s::]%s", headerColor, "Image Key:")),
|
||||
)
|
||||
table.SetCell(httpServerRow, valueCol2, tview.NewTableCell(""))
|
||||
|
||||
table.SetCell(
|
||||
autoDecryptRow,
|
||||
labelCol1,
|
||||
tview.NewTableCell(fmt.Sprintf(" [%s::]%s", headerColor, "Auto Decrypt:")),
|
||||
)
|
||||
table.SetCell(autoDecryptRow, valueCol1, tview.NewTableCell(""))
|
||||
|
||||
// infobar
|
||||
infoBar := &InfoBar{
|
||||
Box: tview.NewBox(),
|
||||
title: Title,
|
||||
table: table,
|
||||
}
|
||||
|
||||
return infoBar
|
||||
}
|
||||
|
||||
func (info *InfoBar) UpdateAccount(account string) {
|
||||
info.table.GetCell(accountRow, valueCol1).SetText(account)
|
||||
}
|
||||
|
||||
func (info *InfoBar) UpdateBasicInfo(pid int, version string, exePath string) {
|
||||
info.table.GetCell(accountRow, valueCol2).SetText(fmt.Sprintf("%d", pid))
|
||||
info.table.GetCell(statusRow, valueCol2).SetText(exePath)
|
||||
info.table.GetCell(platformRow, valueCol2).SetText(version)
|
||||
}
|
||||
|
||||
func (info *InfoBar) UpdateStatus(status string) {
|
||||
info.table.GetCell(statusRow, valueCol1).SetText(status)
|
||||
}
|
||||
|
||||
func (info *InfoBar) UpdatePlatform(text string) {
|
||||
info.table.GetCell(platformRow, valueCol1).SetText(text)
|
||||
}
|
||||
|
||||
func (info *InfoBar) UpdateSession(text string) {
|
||||
info.table.GetCell(sessionRow, valueCol1).SetText(text)
|
||||
}
|
||||
|
||||
func (info *InfoBar) UpdateDataKey(key string) {
|
||||
info.table.GetCell(sessionRow, valueCol2).SetText(key)
|
||||
}
|
||||
|
||||
func (info *InfoBar) UpdateDataUsageDir(dataUsage string, dataDir string) {
|
||||
info.table.GetCell(dataUsageRow, valueCol1).SetText(dataUsage)
|
||||
info.table.GetCell(dataUsageRow, valueCol2).SetText(dataDir)
|
||||
}
|
||||
|
||||
func (info *InfoBar) UpdateWorkUsageDir(workUsage string, workDir string) {
|
||||
info.table.GetCell(workUsageRow, valueCol1).SetText(workUsage)
|
||||
info.table.GetCell(workUsageRow, valueCol2).SetText(workDir)
|
||||
}
|
||||
|
||||
// UpdateHTTPServer updates HTTP Server value.
|
||||
func (info *InfoBar) UpdateHTTPServer(server string) {
|
||||
info.table.GetCell(httpServerRow, valueCol1).SetText(server)
|
||||
}
|
||||
|
||||
func (info *InfoBar) UpdateImageKey(key string) {
|
||||
info.table.GetCell(httpServerRow, valueCol2).SetText(key)
|
||||
}
|
||||
|
||||
// UpdateAutoDecrypt updates Auto Decrypt value.
|
||||
func (info *InfoBar) UpdateAutoDecrypt(text string) {
|
||||
info.table.GetCell(autoDecryptRow, valueCol1).SetText(text)
|
||||
}
|
||||
|
||||
// Draw draws this primitive onto the screen.
|
||||
func (info *InfoBar) Draw(screen tcell.Screen) {
|
||||
info.Box.DrawForSubclass(screen, info)
|
||||
info.Box.SetBorder(false)
|
||||
|
||||
x, y, width, height := info.GetInnerRect()
|
||||
|
||||
info.table.SetRect(x, y, width, height)
|
||||
info.table.SetBorder(false)
|
||||
info.table.Draw(screen)
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package layout
|
||||
|
||||
import (
|
||||
"github.com/rivo/tview"
|
||||
"github.com/sjzar/chatlog/internal/ui/sidebar"
|
||||
)
|
||||
|
||||
type Layout struct {
|
||||
*tview.Flex
|
||||
Sidebar *sidebar.Sidebar
|
||||
Pages *tview.Pages
|
||||
}
|
||||
|
||||
func New(s *sidebar.Sidebar, pages *tview.Pages) *Layout {
|
||||
l := &Layout{
|
||||
Flex: tview.NewFlex(),
|
||||
Sidebar: s,
|
||||
Pages: pages,
|
||||
}
|
||||
|
||||
l.AddItem(s, 20, 0, true).
|
||||
AddItem(pages, 0, 1, false)
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *Layout) FocusSidebar() {
|
||||
l.AddItem(l.Sidebar, 20, 0, true)
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package logs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
"github.com/sjzar/chatlog/internal/ui/style"
|
||||
)
|
||||
|
||||
type Logs struct {
|
||||
*tview.TextView
|
||||
}
|
||||
|
||||
func New() *Logs {
|
||||
l := &Logs{
|
||||
TextView: tview.NewTextView(),
|
||||
}
|
||||
|
||||
l.SetDynamicColors(true)
|
||||
l.SetScrollable(true)
|
||||
l.SetWrap(true)
|
||||
l.SetBorder(true)
|
||||
l.SetTitle(" 日志 ")
|
||||
l.SetBorderColor(style.BorderColor)
|
||||
l.SetBackgroundColor(style.BgColor)
|
||||
l.SetTextColor(style.FgColor)
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *Logs) AddLog(msg string) {
|
||||
fmt.Fprintf(l, "[%s]%s[white] %s\n",
|
||||
time.Now().Format("15:04:05"),
|
||||
"",
|
||||
msg)
|
||||
l.ScrollToEnd()
|
||||
}
|
||||
|
||||
func (l *Logs) Write(p []byte) (n int, err error) {
|
||||
l.AddLog(string(p))
|
||||
return len(p), nil
|
||||
}
|
||||
@@ -159,4 +159,4 @@ func (l SortItems) Less(i, j int) bool {
|
||||
|
||||
func (l SortItems) Swap(i, j int) {
|
||||
l[i], l[j] = l[j], l[i]
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package sidebar
|
||||
|
||||
import (
|
||||
"github.com/rivo/tview"
|
||||
"github.com/sjzar/chatlog/internal/ui/style"
|
||||
)
|
||||
|
||||
type Sidebar struct {
|
||||
*tview.List
|
||||
}
|
||||
|
||||
func New(onSelected func(int, string, string, rune)) *Sidebar {
|
||||
s := &Sidebar{
|
||||
List: tview.NewList(),
|
||||
}
|
||||
|
||||
s.ShowSecondaryText(false)
|
||||
s.SetBackgroundColor(style.BgColor)
|
||||
s.SetMainTextColor(style.FgColor)
|
||||
s.SetSelectedBackgroundColor(style.MenuBgColor)
|
||||
s.SetSelectedTextColor(style.PageHeaderFgColor)
|
||||
s.SetBorder(true)
|
||||
s.SetTitle(" 导航 ")
|
||||
s.SetTitleAlign(tview.AlignLeft)
|
||||
s.SetBorderColor(style.BorderColor)
|
||||
|
||||
s.SetSelectedFunc(onSelected)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Sidebar) AddItem(text string, shortcut rune) {
|
||||
s.List.AddItem(text, "", shortcut, nil)
|
||||
}
|
||||
Reference in New Issue
Block a user