feat: 升级到 lipgloss/bubbletea v2,实现翻译卡片组件
- 升级 charm.land/lipgloss/v2 v1.1.0 -> v2.0.2 - 升级 charm.land/bubbletea/v2 v1.3.10 -> v2.0.2 - 升级 charm.land/bubbles/v2 -> v2.1.0 - 新增翻译卡片组件:元信息行(Tokens/耗时/模型)、用户输入(碳黑背景)、翻译结果 - 卡片组件间距 5px - 重构 model.go 适配 v2 API - 更新 keys.go, messages.go, styles.go
This commit is contained in:
149
memory.md
149
memory.md
@@ -745,4 +745,153 @@ func matchCommand(input string) []command {
|
||||
|
||||
### Viewport组件
|
||||
用于长文本滚动显示,配合scrollbar展示滚动位置。
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## TUI输入框踩坑记录 (v0.8.0)
|
||||
|
||||
### 问题1:Ctrl+J换行后第一行被遮住
|
||||
|
||||
**现象**:
|
||||
- 按Ctrl+J换行后,第一行内容往上滚动被遮住
|
||||
- 光标在新行,但下方显示一个空行
|
||||
- 实际渲染了3行,但只显示2行
|
||||
|
||||
**尝试过的方案**:
|
||||
1. 移除 lipgloss Width() 限制 - 无效
|
||||
2. 设置 SetWidth() 后再 SetHeight() - 无效
|
||||
3. 动态计算行数后调用 SetHeight() - 无效
|
||||
4. 移除 updateInputHeight() 调用 - 无效
|
||||
|
||||
**根因分析**:
|
||||
- textarea 内部使用 viewport 组件管理滚动
|
||||
- 每次按键后动态调用 `m.input.SetHeight(lines)` 调整高度
|
||||
- 导致 textarea 内部 viewport 滚动位置与渲染不同步
|
||||
|
||||
**最终解决方案**:
|
||||
- 放弃动态调整高度的方案
|
||||
- 固定 textarea 高度为5行
|
||||
- 超过5行时,textarea 内部自动滚动,光标始终可见
|
||||
|
||||
**关键代码** (`internal/tui/model.go`):
|
||||
```go
|
||||
ta.SetWidth(60)
|
||||
ta.SetHeight(5) // 固定高度,不动态调整
|
||||
```
|
||||
|
||||
### 问题2:输入框背景颜色
|
||||
|
||||
**解决方案**:
|
||||
- 使用 `textarea.DefaultStyles()` 获取默认样式
|
||||
- 修改 Style.Base 设置背景色
|
||||
|
||||
**关键代码**:
|
||||
```go
|
||||
focusedStyle, blurredStyle := textarea.DefaultStyles()
|
||||
bgStyle := lipgloss.NewStyle().
|
||||
Background(lipgloss.Color("#1F2937")).
|
||||
Foreground(lipgloss.Color("#FAFAFA"))
|
||||
focusedStyle.Base = bgStyle
|
||||
blurredStyle.Base = bgStyle
|
||||
ta.FocusedStyle = focusedStyle
|
||||
ta.BlurredStyle = blurredStyle
|
||||
```
|
||||
|
||||
### 经验总结
|
||||
|
||||
1. **Bubble Tea的textarea组件**:内部包含viewport,不适合频繁动态调整高度
|
||||
2. **固定高度方案**:更稳定,让组件内部控制滚动
|
||||
3. **样式设置**:使用 FocusedStyle/BlurredStyle + Style.Base 而非直接设置 Style
|
||||
|
||||
---
|
||||
|
||||
## Bubble Tea/Lipgloss v2 升级经验 (v0.8.1)
|
||||
|
||||
### 模块路径变更
|
||||
|
||||
v2 版本全部迁移到 `charm.land` 域名:
|
||||
|
||||
| v1 | v2 |
|
||||
|----|-----|
|
||||
| `github.com/charmbracelet/lipgloss` | `charm.land/lipgloss/v2` |
|
||||
| `github.com/charmbracelet/bubbletea` | `charm.land/bubbletea/v2` |
|
||||
| `github.com/charmbracelet/bubbles` | `charm.land/bubbles/v2` |
|
||||
|
||||
### View() 方法变更
|
||||
|
||||
v1:
|
||||
```go
|
||||
func (m model) View() string {
|
||||
return "内容"
|
||||
}
|
||||
```
|
||||
|
||||
v2:
|
||||
```go
|
||||
func (m model) View() tea.View {
|
||||
v := tea.NewView("内容")
|
||||
v.AltScreen = true // 进入备用屏幕
|
||||
return v
|
||||
}
|
||||
```
|
||||
|
||||
### KeyMsg 变更
|
||||
|
||||
v1:
|
||||
```go
|
||||
case tea.KeyMsg:
|
||||
switch msg.Type {
|
||||
case tea.KeyCtrlC:
|
||||
return m, tea.Quit
|
||||
}
|
||||
```
|
||||
|
||||
v2:
|
||||
```go
|
||||
case tea.KeyPressMsg:
|
||||
switch msg.String() {
|
||||
case "ctrl+c":
|
||||
return m, tea.Quit
|
||||
case "space": // 注意:空格键改为"space"
|
||||
}
|
||||
```
|
||||
|
||||
### 快捷键对比
|
||||
|
||||
| 功能 | v1 | v2 |
|
||||
|-----|-----|-----|
|
||||
| Ctrl+C | `tea.KeyCtrlC` | `"ctrl+c"` |
|
||||
| Alt修饰键 | `msg.Alt` | `msg.Mod.Contains(tea.ModAlt)` |
|
||||
| 空格键 | `" "` | `"space"` |
|
||||
|
||||
### viewport API变更
|
||||
|
||||
| 功能 | v1 | v2 |
|
||||
|-----|-----|-----|
|
||||
| 滚动上 | `m.viewport.LineUp(n)` | `m.viewport.ScrollUp(n)` |
|
||||
| 滚动下 | `m.viewport.LineDown(n)` | `m.viewport.ScrollDown(n)` |
|
||||
| 宽度 | `m.viewport.Width` | `m.viewport.Width()` |
|
||||
| 高度 | `m.viewport.Height` | `m.viewport.Height()` |
|
||||
| 创建 | `viewport.New(w, h)` | `viewport.New(viewport.WithWidth(w), viewport.WithHeight(h))` |
|
||||
|
||||
### textarea API变更
|
||||
|
||||
| 功能 | v1 | v2 |
|
||||
|-----|-----|-----|
|
||||
| 默认样式 | `textarea.DefaultStyles()` | `textarea.DefaultStyles(isDark bool)` |
|
||||
| 重置内容 | `m.input.SetValue("")` | `m.input.Reset()` |
|
||||
|
||||
### Program启动
|
||||
|
||||
v1:
|
||||
```go
|
||||
p := tea.NewProgram(model{})
|
||||
p.Start()
|
||||
```
|
||||
|
||||
v2:
|
||||
```go
|
||||
p := tea.NewProgram(model{})
|
||||
p.Run()
|
||||
```
|
||||
Reference in New Issue
Block a user