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:
@@ -112,6 +112,15 @@
|
||||
}
|
||||
core.platformSetup = { [weak self] config in
|
||||
guard let self else { return }
|
||||
// ghostty 在 `ghostty_surface_new`(本闭包返回后)里把新的 IOSurfaceLayer 追加为
|
||||
// 本 view.layer 的子层,但旧 surface 被 free 时并不移除其子层。detach/reattach 抖动或
|
||||
// 配置变更导致的多次 rebuild 会遗留孤儿子层(冻结在旧的小尺寸首帧,因纹理小被底部锚定,
|
||||
// 表现为屏幕底部一段永不更新的残影)。此刻旧 surface 已 free、新层尚未创建 —— 清掉现存
|
||||
// 全部子层即只保留 ghostty 即将新建的那一个。本 view 的子层仅由 ghostty 管理,清理安全。
|
||||
if let stale = self.layer.sublayers, !stale.isEmpty {
|
||||
TerminalDebugLog.log(.lifecycle, "removing stale sublayers count=\(stale.count)")
|
||||
for sub in stale { sub.removeFromSuperlayer() }
|
||||
}
|
||||
config.platform_tag = GHOSTTY_PLATFORM_IOS
|
||||
config.platform = ghostty_platform_u(
|
||||
ios: ghostty_platform_ios_s(
|
||||
@@ -128,6 +137,13 @@
|
||||
core.onPostRender = { [weak self] in
|
||||
self?.enforceSublayerScale()
|
||||
}
|
||||
core.onSurfaceFreed = { [weak self] in
|
||||
// ghostty(iOS) 释放 surface 不摘子层,泄漏的死层冻结在屏底。teardown 后清空遗留子层,
|
||||
// 后续 createSurface 会重挂新层;纯 teardown(断开/卸载)则清掉残影。本 view 子层仅 ghostty 管理。
|
||||
guard let sublayers = self?.layer.sublayers, !sublayers.isEmpty else { return }
|
||||
TerminalDebugLog.log(.lifecycle, "onSurfaceFreed removing sublayers count=\(sublayers.count)")
|
||||
for sub in sublayers { sub.removeFromSuperlayer() }
|
||||
}
|
||||
|
||||
setupApplicationLifecycleObservers()
|
||||
syncApplicationActiveState()
|
||||
|
||||
Reference in New Issue
Block a user