feat: 修复 3 个渲染/tmux 显示 bug + UI 产品化第一波(对标 Moshi)

渲染/tmux 修复(e2e 复现+回归,模拟器 idb 点击+截图取证):
- 终端底部残影:ghostty iOS 释放 surface 不摘 IOSurfaceLayer(上游缺陷),
  platformSetup 清现存子层 + TerminalSurfaceCoordinator.onSurfaceFreed 钩子摘孤儿层
- tmux 切 tab 切回旧 tab 内容消失:改所有窗口常驻挂载(ZStack+opacity+hitTesting),
  surface 不释放、内容保留、后台窗口持续收 %output
- tmux pane 内容钉底/顶部残行:pane grid 由容器几何定(tab 条吃高度),75 行快照喂 73 行
  溢出上滚;几何测量上移 TmuxTabbedView + attach kickoff 双条件(attachAcked∧containerKnown)
  + capture-pane 铺快照前剔尾空行

UI 产品化(对标 Moshi getmoshi.app:深蓝黑 + 终端绿 + Catppuccin):
- 设计系统 Theme.swift:TXPalette(色角色 struct)+TXThemeManager(环境注入),颜色封装供主题系统
- 统一主题:抽离 4 套 Catppuccin(Mocha/Macchiato/Frappé/Latte),一套同时驱动 app+终端配色,
  设置里选主题 app 与终端一起变色 + UserDefaults 持久化
- 主屏/主机管理页 HomeView:HostCard 主机卡 + FAB 加主机(AddHostSheet) + 设置(主题选择器),
  HostStore 本地 JSON 持久化(密码暂存/TODO Keychain),点卡片 connect(to:)
- 终端外壳 chrome TerminalTopBar:圆形返回钮 + 会话标题 + SSH/mosh 传输徽章 + 状态提示,
  tmux tab 绿 pill 化,底部工具栏深色自适应,终端默认 Catppuccin Mocha

iPad mini(A17 Pro) live 端到端验证:加主机→连接→终端→切 tab→分屏点焦点→主题切换同步。
详见 docs/HANDOFF.md §10。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
kid
2026-07-24 22:43:00 +08:00
parent d4ab55db48
commit 6dd23275ff
10 changed files with 754 additions and 96 deletions

View File

@@ -7,6 +7,7 @@
## 0. 一句话现状
一个**原生 iPad SSH 终端**已可用并真机验证libghostty 渲染 + 键盘输入 + SSH 直连 + **SSH-over-tsnet(Tailscale 用户态)** + **tmux -CC 原生 tab + 多 pane 分屏** + **mosh(LAN + over-tsnet 均已端到端验证)** + 断线自动重连 + **mosh 挂起→恢复<3s(M3)**。四大核心需求libghostty/tailscale/tmux/**mosh 均已验证**)。仅在 iOS 模拟器验证(未上真机/未签名)。
> **2026-07-24 本轮**:修复 3 个渲染/tmux 显示 bug + 完成 UI 产品化第一波(对标 Moshi。详见 **§10**。UI 已从 demo 态变为深色 Catppuccin 主题 + 主机管理页 + 终端 chrome + 统一主题切换。
> **mosh 状态2026-07-24 全部验证通过)**mosh(C++,blinksh/ios)+protobuf-lite 交叉编译成 `MoshCore.xcframework`CommonCrypto 后端,含 arm64 模拟器 slicetsnet 桥加 UDP relay(`StartMoshRelay`)`MoshSession`(pipe↔FILE*/pthread/SIGWINCH)+`MoshConnectScanner`(TXCore)+`SSHTerminalModel` 编排SSH 引导 mosh-server→解析 MOSH CONNECT→接管
> - **LAN 直连端到端验证**192.168.9.199mosh-server 存活 104s≫60s 无客户端超时+子 shell+心跳=真连。
> - **mosh over tsnet 端到端验证**vohive-vm 100.69.201.101app 日志 `parsed MOSH CONNECT port=60002`→`relay up localPort=63542`→`activateMosh started`;屏幕渲染远端 shell 且无 mosh 断连 overlay=relay UDP 双向流通。**R1(tsnet UDP 数据报语义) 证伪**。
@@ -96,4 +97,22 @@
- **绝不臆想工具结果**调用后等真实返回再推理绝不编造 BUILD/日志/截图曾因连续编造工具输出含假 BUILD SUCCEEDED错误归因 GhosttyKit而误诊——真相全靠老实 `Read` 完整 log此规则已写入全局 `~/.claude/CLAUDE.md`
- 每步用真实证据验证`swift test` 看真实计数`xcodebuild` 看真实 BUILD 结果模拟器 `screenshot` + `Read` 看真实画面
- 与用户用**简体中文**commit/push 只在明确要求时
## 10. UI 产品化 + 渲染修复2026-07-24 本轮)
### 10.1 修复的 3 个渲染/tmux 显示 buge2e 复现+修复+回归,均模拟器 idb 点击+截图取证)
1. **终端底部残影**旧帧钉屏底ghostty iOS `addSublayer:` IOSurfaceLayer `Metal.deinit` 从不 `removeFromSuperlayer`上游 iOS-only 缺陷SwiftUI attach 抖动导致同一 view 多次建 surface 时旧层泄漏冻结小尺寸首帧 CA `topLeft` gravity 钉在屏底vendor `UITerminalView.platformSetup` surface 前清现存子层 + `TerminalSurfaceCoordinator.onSurfaceFreed` 钩子`tearDownSurface` 后回调 `commonInit` 里摘子层。(诊断经 Fable 顾问在 ghostty 源码层锚定。)
2. **tmux 切 tab 切回旧 tab 内容消失**`TmuxTabbedView` 原只渲 activeWindow `.id(win.id)`切走销毁 pane 视图释放 surface内容丢失改成**所有窗口常驻挂载仅激活可见**`ZStack`+`opacity`+`allowsHitTesting`surface 不释放内容保留后台窗口持续收 %output
3. **tmux pane 内容钉底/顶部残行**pane ghostty grid 由容器像素几何决定tab 条吃高度73 attach raw 全屏 75 capture75 行快照喂 73 grid 溢出上滚(A) 容器几何测量上移到 `TmuxTabbedView` 内容槽破鸡生蛋死锁(B) `TmuxController` attach kickoff `attachAcked ∧ containerKnown` 双条件`kickoffIfReady`(C) `capture-pane` 铺快照前剔尾部空行
### 10.2 UI 产品化(对标 Moshi getmoshi.app深蓝黑底 + 终端绿 + 圆角卡片)
- **设计系统颜色封装为主题系统**`apps/TerminalX/iOS/Theme.swift``TXPalette`(所有色角色 struct)+`TXThemeManager:ObservableObject`(环境注入)结构量走 `enum TX`(圆角/间距/等宽字体)。
- **统一主题** GhosttyTheme 抽离 4 Catppuccin(Mocha/Macchiato/Frappé/Latte)每套同时定义 app 配色+终端配色(`ghosttyName``terminalTheme`)。设置里选主题 **app 与终端一起变色 + 持久化**(`UserDefaults(txThemeStorageKey)`)`ContentView` `.onChange(palette.id)→model.applyTerminalTheme()`新终端/pane `TerminalTheme.txDefault` 读持久化
- **主屏/主机管理页**(`ContentView.HomeView`)主机卡(`HostCard`)+FAB 加主机(`AddHostSheet`)+设置(`SettingsStubView` 含主题选择器)`HostStore`(Application Support/hosts.json 持久化密码暂存本地/TODO Keychain)点卡片 `SSHTerminalModel.connect(to:)`
- **终端外壳 chrome**(`ContentView.TerminalScreen`+`TerminalTopBar`)顶栏(圆形返回钮+会话标题`model.connectionTitle`+传输徽章`model.moshEngaged`?mosh青:SSH绿+连接态点+状态提示)`TmuxTabChip` 绿 pill 底部 GhosttyKit 工具栏深色自适应终端默认 Catppuccin Mocha
- **验证**iPad mini(A17 Pro) live 验证全流程加主机连接终端 tab分屏点焦点主题切换 app+终端同步)。
### 10.3 待续UI
- 会话缩略卡区Moshi 首屏实时终端预览横滑需会话管理设置页字体/工具栏配置导航壳打磨终端工具栏 accent tint`inputAccessoryStyle` SwiftUI 未暴露需桥接)。
- 无头 UI 测试`idb ui tap x y`Python3.14 需事件循环 shim `/tmp/idbrun.py`坐标=屏幕像素×0.5,注意设备朝向)。诊断埋点(GKDBG/txDbg*)已清理MOSHDBG/TMUXDBG/M4DBG 仍在( cleanup-todo)。
</content>