feat(ios): W4 app wiring — DI graph, event fan-out, lifecycle, privacy shade
T-iOS-15: AppEnvironment production DI (real Keychain/probe/transports), EventFanOut (engine.events → TerminalVM + GateVM + activity bridge), scenePhase lifecycle (.background→close, suspend→rebuild+reopen reclaims size), privacy shade on != .active, spike screen deleted, cold-start routing Walkthrough proxies: hosted live-server smoke over the production DI graph (probe→store→ attach→echo→close) + real-Keychain kSecAttrAccessible assertion (closes T-iOS-7 deferral) Deviation closed: TerminalViewModel.lastSentDims (valid-only) + alive-engine .active → notifyForegrounded(dims:) (orchestrator fix on behalf of T-iOS-11 owner) Env finding: repo under ~/Documents → TCC blocks sim-spawned node; SimServerHarness dual-mode (self-bootstrap / WEBTERM_SERVER_URL via simctl launchctl setenv) Verified: 214 pkg + 76 app + 10 integration tests green; verify agent 8/8 PASS
This commit is contained in:
@@ -1,89 +0,0 @@
|
||||
//
|
||||
// SpikeTerminalScreen.swift — T-iOS-2 Day-1 spike ②【临时文件,W4/T-iOS-15 删除】
|
||||
//
|
||||
// 目的:SwiftTerm TerminalView 的真机键盘/IME smoke 载体(plan §7 T-iOS-2):
|
||||
// - 键盘弹出 / first-responder 行为
|
||||
// - 中文 IME 组合输入(不自加 keydown 监听,组合事件全交系统栈)
|
||||
// - inputAccessoryView 上 Esc/Ctrl-C 可发 —— SwiftTerm iOS 端自带
|
||||
// TerminalAccessory(含 esc/ctrl/tab 键,iOSAccessoryView.swift),
|
||||
// spike 直接用它验证;正式 key-bar(逐字节复刻 public/keybar.ts)归 T-iOS-11
|
||||
// - 文本选择不崩(SwiftTerm 自绘选择是历史坑点)
|
||||
//
|
||||
// 接线为【纯本地回显】(无服务器依赖):typed bytes → send() → feed() 原样喂回,
|
||||
// CR 扩成 CRLF。真实 SessionEngine 接线是 W2/W3 的事。
|
||||
//
|
||||
// 2026-07-04:无可用真机 —— 真机清单各项记 DEFERRED(真机不可用)(见 PROGRESS_LOG
|
||||
// 条目)。本文件当下的验收是:作为 App target 源码在模拟器 xcodebuild 构建通过。
|
||||
|
||||
import SwiftTerm
|
||||
import SwiftUI
|
||||
|
||||
/// Day-1 spike 的最小 SwiftUI 壳。不接入 WebTermApp 导航(WebTermApp.swift 归
|
||||
/// T-iOS-1/T-iOS-15 所有);存在本身即证明 App target 在 Swift 6 strict
|
||||
/// concurrency 下能链接并承载 SwiftTerm 的 TerminalView。
|
||||
struct SpikeTerminalScreen: View {
|
||||
var body: some View {
|
||||
LocalEchoTerminal()
|
||||
.ignoresSafeArea(.container, edges: .bottom)
|
||||
.navigationTitle("SwiftTerm spike")
|
||||
}
|
||||
}
|
||||
|
||||
/// 承载 SwiftTerm UIKit `TerminalView` 的 UIViewRepresentable,接本地回显。
|
||||
/// 形状即 T-iOS-11 正式 TerminalScreen 的雏形(去掉 SessionEngine)。
|
||||
private struct LocalEchoTerminal: UIViewRepresentable {
|
||||
func makeCoordinator() -> LocalEchoCoordinator {
|
||||
LocalEchoCoordinator()
|
||||
}
|
||||
|
||||
func makeUIView(context: Context) -> TerminalView {
|
||||
let view = TerminalView(frame: .zero)
|
||||
view.terminalDelegate = context.coordinator
|
||||
view.feed(text: SpikeGreeting.text)
|
||||
return view
|
||||
}
|
||||
|
||||
func updateUIView(_ uiView: TerminalView, context: Context) {
|
||||
// 本地回显无外部状态可同步。
|
||||
}
|
||||
}
|
||||
|
||||
private enum SpikeGreeting {
|
||||
/// 行尾用 CRLF:PTY 语义下裸 LF 只下移一行不回车。
|
||||
static let text = "SwiftTerm local-echo spike (T-iOS-2)\r\n"
|
||||
+ "Typed bytes are echoed locally; CR -> CRLF.\r\n"
|
||||
+ "真机清单: 键盘弹出 / 中文 IME / accessory esc·ctrl / 文本选择\r\n\r\n> "
|
||||
}
|
||||
|
||||
/// 本地回显 delegate:SwiftTerm 要"发给宿主"的每个字节原样喂回终端。
|
||||
/// Enter 产生的 CR(0x0D)补一个 LF,光标才会回行首并换行。
|
||||
@MainActor
|
||||
private final class LocalEchoCoordinator: NSObject, @preconcurrency TerminalViewDelegate {
|
||||
private static let carriageReturn: UInt8 = 0x0D
|
||||
private static let lineFeed: UInt8 = 0x0A
|
||||
|
||||
func send(source: TerminalView, data: ArraySlice<UInt8>) {
|
||||
var echoed: [UInt8] = []
|
||||
echoed.reserveCapacity(data.count + 1)
|
||||
for byte in data {
|
||||
echoed.append(byte)
|
||||
if byte == Self.carriageReturn {
|
||||
echoed.append(Self.lineFeed)
|
||||
}
|
||||
}
|
||||
source.feed(byteArray: echoed[...])
|
||||
}
|
||||
|
||||
func sizeChanged(source: TerminalView, newCols: Int, newRows: Int) {}
|
||||
func setTerminalTitle(source: TerminalView, title: String) {}
|
||||
func hostCurrentDirectoryUpdate(source: TerminalView, directory: String?) {}
|
||||
func scrolled(source: TerminalView, position: Double) {}
|
||||
func requestOpenLink(source: TerminalView, link: String, params: [String: String]) {}
|
||||
func clipboardCopy(source: TerminalView, content: Data) {}
|
||||
func rangeChanged(source: TerminalView, startY: Int, endY: Int) {}
|
||||
// bell / iTermContent 用 SwiftTerm 的默认实现。
|
||||
}
|
||||
|
||||
#Preview {
|
||||
SpikeTerminalScreen()
|
||||
}
|
||||
Reference in New Issue
Block a user