T-iPad-2: AdaptiveRootView/LayoutPolicy (sole size-class decision), SplitRootView (NavigationSplitView sidebar+detail), StackRootView (iPhone path verbatim, zero regression); privacy shade hoisted to shared ZStack top for both branches T-iPad-3: KeyBarVisibility predicate (hide when hardware keyboard present), pointer context menu (copy/new-in-cwd/kill, all via existing channels) T-iPad-4: Projects multi-column grid on iPad (idiom-gated), adaptive sheet detents T-iPad-5 findings (4/4 fixed): kill onKillSession thread-through + AppCoordinator.killCurrentSession; split route-gated to .sessions (iPad first-run pairing); continue-last banner in split sidebar; iPad XCUITest deferred (covered by SidebarSelectionTests) Verified: iPhone 16 277 + iPad Pro 11 278 tests green; packages 261 + integration 10; zero changes under ios/Packages, src/, public/
23 lines
1008 B
Swift
23 lines
1008 B
Swift
import SwiftUI
|
||
|
||
/// T-iPad-2 · 自适应根视图的布局模式。
|
||
public enum LayoutMode: Equatable {
|
||
/// 现有 iPhone 路径:`NavigationStack`(列表 → push 终端)。
|
||
case stack
|
||
/// iPad 分栏:`NavigationSplitView`(sidebar 会话列表 + detail 终端)。
|
||
case split
|
||
}
|
||
|
||
/// T-iPad-2 · **唯一** size-class 决策点(仿 `PrivacyShadePolicy` 的纯谓词
|
||
/// 先例)。视图内严禁散落 `if sizeClass == …`(PLAN_IOS_IPAD §4)—— 所有
|
||
/// 分支只从这里读一次,故可 100% 单测。
|
||
///
|
||
/// regular 宽度(iPad 全屏 / 大分屏 / Stage Manager 大窗)→ `.split`;
|
||
/// compact 或 nil(iPhone / iPad Slide Over / 小分屏 / size class 未定)→
|
||
/// `.stack`。nil 走最保守回退:退到现有已测的 iPhone 路径,绝不误判成分栏。
|
||
public enum LayoutPolicy {
|
||
public static func mode(horizontalSizeClass: UserInterfaceSizeClass?) -> LayoutMode {
|
||
horizontalSizeClass == .regular ? .split : .stack
|
||
}
|
||
}
|