feat: TUI帮助功能与样式改进
Some checks failed
Release / build (push) Failing after 37s

- 添加帮助信息栏 (bubbles help组件, Ctrl+H切换)
- 翻译卡片样式优化 (Padding空隙、上方内边距)
- 扩展build.sh支持跨平台编译
- release.yaml使用build.sh构建
This commit is contained in:
2026-04-08 02:08:34 +08:00
parent a9b7a69224
commit 0a40258d9a
6 changed files with 211 additions and 11 deletions

View File

@@ -12,6 +12,7 @@ type KeyMap struct {
ScrollDown key.Binding
ScrollTop key.Binding
ScrollBottom key.Binding
Help key.Binding
}
func NewKeyMap() KeyMap {
@@ -44,5 +45,21 @@ func NewKeyMap() KeyMap {
key.WithKeys("end"),
key.WithHelp("End", "底部"),
),
Help: key.NewBinding(
key.WithKeys("ctrl+h"),
key.WithHelp("Ctrl+H", "帮助"),
),
}
}
func (k KeyMap) ShortHelp() []key.Binding {
return []key.Binding{k.Help, k.Quit}
}
func (k KeyMap) FullHelp() [][]key.Binding {
return [][]key.Binding{
{k.Quit, k.Clear, k.SwitchLang},
{k.ScrollUp, k.ScrollDown, k.ScrollTop, k.ScrollBottom},
{k.Help},
}
}

View File

@@ -7,6 +7,8 @@ import (
"strings"
"time"
"charm.land/bubbles/v2/help"
"charm.land/bubbles/v2/key"
"charm.land/bubbles/v2/spinner"
"charm.land/bubbles/v2/textarea"
"charm.land/bubbles/v2/viewport"
@@ -33,6 +35,7 @@ type model struct {
input textarea.Model
viewport viewport.Model
spinner spinner.Model
help help.Model
keys KeyMap
targetLang string
@@ -67,16 +70,22 @@ func NewApp(cfg *config.Config, t *translator.Translator) *tea.Program {
sp.Spinner = spinner.MiniDot
sp.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("#8B5CF6"))
return tea.NewProgram(model{
hp := help.New()
m := model{
config: cfg,
translator: t,
messages: make([]ChatMessage, 0),
input: ta,
viewport: vp,
spinner: sp,
help: hp,
keys: keys,
targetLang: getDefaultLang(cfg),
})
}
p := tea.NewProgram(m)
return p
}
func getDefaultLang(cfg *config.Config) string {
@@ -100,6 +109,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case tea.WindowSizeMsg:
m.width = msg.Width
m.height = msg.Height
m.help.SetWidth(msg.Width)
m.updateLayout()
case translateMsg:
@@ -137,6 +147,9 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case "end":
m.viewport.GotoBottom()
}
if key.Matches(msg, m.keys.Help) {
m.help.ShowAll = !m.help.ShowAll
}
}
m.input, cmd = m.input.Update(msg)
@@ -206,7 +219,12 @@ func (m *model) updateLayout() {
m.input.SetWidth(contentWidth)
m.viewport.SetWidth(contentWidth)
m.viewport.SetHeight(m.height - 12)
helpLines := 2
if m.help.ShowAll {
helpLines = 4
}
m.viewport.SetHeight(m.height - 12 - helpLines)
if m.viewport.Height() < 5 {
m.viewport.SetHeight(10)
}
@@ -217,6 +235,10 @@ func (m *model) updateLayout() {
func (m *model) updateViewportContent() {
var b strings.Builder
if len(m.messages) > 0 {
b.WriteString("\n")
}
for _, msg := range m.messages {
b.WriteString(m.renderTranslationCard(msg))
}
@@ -252,7 +274,7 @@ func (m *model) renderTranslationCard(msg ChatMessage) string {
Render(msg.Error)
outputBlock = lipgloss.NewStyle().
Foreground(lipgloss.Color("#F87171")).
Padding(0, 3, 1, 3).
Padding(1, 3, 1, 3).
Width(m.viewport.Width()).
Render(outputContent)
} else {
@@ -260,7 +282,7 @@ func (m *model) renderTranslationCard(msg ChatMessage) string {
Width(m.viewport.Width() - 2).
Render(msg.Output)
outputBlock = lipgloss.NewStyle().
Padding(0, 3, 1, 3).
Padding(1, 3, 1, 3).
Width(m.viewport.Width()).
Render(outputContent)
}
@@ -299,9 +321,9 @@ func (m model) View() tea.View {
messages := m.viewport.View()
inputArea := m.renderInputArea()
infoBar := m.renderInfoBar()
spinnerView := m.renderSpinner()
helpView := m.help.View(m.keys)
content := header + "\n" + messages + inputArea + infoBar + spinnerView
content := header + "\n" + messages + inputArea + infoBar + helpView
v := tea.NewView(content)
v.AltScreen = true
return v