package tui import ( "github.com/charmbracelet/bubbles/textinput" "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "github.com/titor/fanyi/internal/config" "github.com/titor/fanyi/internal/translator" ) type model struct { config *config.Config translator *translator.Translator textInput textinput.Model result string targetLang string langIndex int } var ( headerStyle = lipgloss.NewStyle(). Foreground(lipgloss.Color("#00D9FF")). Bold(true) dividerStyle = lipgloss.NewStyle(). Foreground(lipgloss.Color("#00D9FF")) inputStyle = lipgloss.NewStyle(). Foreground(lipgloss.Color("#FAFAFA")). Background(lipgloss.Color("#1A1A2E")) resultStyle = lipgloss.NewStyle(). Foreground(lipgloss.Color("#98FB98")). Background(lipgloss.Color("#0D1B2A")) helpStyle = lipgloss.NewStyle(). Foreground(lipgloss.Color("#888888")) statusBarStyle = lipgloss.NewStyle(). Foreground(lipgloss.Color("#FFFFFF")). Background(lipgloss.Color("#1F2937")). Width(60) langStyle = lipgloss.NewStyle(). Foreground(lipgloss.Color("#FBBF24")). Bold(true) keyStyle = lipgloss.NewStyle(). Foreground(lipgloss.Color("#60A5FA")) ) var supportedLangs = []string{"zh-CN", "en-US", "ja", "ko", "zh-TW", "es", "fr", "de"} func NewApp(cfg *config.Config, t *translator.Translator) *tea.Program { targetLang := "zh-CN" if cfg != nil && cfg.DefaultTargetLang != "" { targetLang = cfg.DefaultTargetLang } ti := textinput.New() ti.Placeholder = "输入要翻译的文本..." ti.Focus() ti.Prompt = "> " ti.TextStyle = inputStyle return tea.NewProgram(model{ config: cfg, translator: t, textInput: ti, targetLang: targetLang, }) } func (m model) Init() tea.Cmd { return nil } func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmd tea.Cmd switch msg := msg.(type) { case tea.KeyMsg: switch msg.Type { case tea.KeyEnter: // 回车键处理,后续模块会添加翻译逻辑 case tea.KeyCtrlC: return m, tea.Quit case tea.KeyCtrlL: // Ctrl+L: 清空输入和结果 m.textInput.SetValue("") m.result = "" return m, nil case tea.KeyCtrlT: // Ctrl+T: 切换语言 m.langIndex = (m.langIndex + 1) % len(supportedLangs) m.targetLang = supportedLangs[m.langIndex] return m, nil case tea.KeyEsc: return m, tea.Quit } } m.textInput, cmd = m.textInput.Update(msg) return m, cmd } func (m model) View() string { resultBox := m.renderResult() helpText := helpStyle.Render("\n " + keyStyle.Render("Ctrl+L") + " 清空 " + keyStyle.Render("Ctrl+T") + " 切换语言 " + keyStyle.Render("Enter") + " 翻译 " + keyStyle.Render("Ctrl+C") + " 退出") return "\n" + " " + headerStyle.Render("YOYO翻译") + "\n" + " " + dividerStyle.Render("─────────────────────") + "\n\n" + " " + m.textInput.View() + "\n\n" + resultBox + helpText + "\n" + m.renderStatusBar() } func (m model) renderResult() string { if m.result == "" { return " " + helpStyle.Render("翻译结果将显示在这里...") + "\n" } return " " + resultStyle.Render(m.result) + "\n" } func (m model) renderStatusBar() string { divider := dividerStyle.Render("─") langInfo := langStyle.Render("目标: " + m.targetLang) return "\n " + divider + "\n" + " " + statusBarStyle.Render(" "+langInfo+" ") }