Files
web-terminal/ios/App/WebTerm/Screens/ProjectsLayout.swift
Yaojia Wang 823432b1c8 feat(ipad): W1-W3 — adaptive split-view layout + finding fixes
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/
2026-07-05 19:58:30 +02:00

74 lines
3.3 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import SwiftUI
import UIKit
/// T-iPad-4 · Projects **** / / sheet
/// detents 仿 `LayoutPolicy`
/// 100%
///
/// ** `UIUserInterfaceIdiom` `horizontalSizeClass`**
/// iPad Projects ** sheet**form sheet
/// `horizontalSizeClass` **compact** iPhone
/// size class iPhone iPhoneiPad
/// Projects sheet idiom Projects /
/// idiom+ stack/split `LayoutPolicy`
/// size-class
enum ProjectsGridLayout {
/// iPhone / iPad 退
static let singleColumn = 1
/// iPad 2 sheet ~440540pt
static let twoColumnMinWidth: CGFloat = 400
/// iPad 3 /
static let threeColumnMinWidth: CGFloat = 760
/// iPhone`.phone`/ `singleColumn` List
/// iPad`.pad` **** 13 `>= 1`
/// 0
static func columnCount(
availableWidth: CGFloat,
idiom: UIUserInterfaceIdiom
) -> Int {
guard idiom == .pad else { return singleColumn }
if availableWidth >= threeColumnMinWidth { return 3 }
if availableWidth >= twoColumnMinWidth { return 2 }
return singleColumn
}
/// iPad iPhone List
static func usesGrid(idiom: UIUserInterfaceIdiom) -> Bool {
idiom == .pad
}
}
/// T-iPad-4 · Projects sheet detents idiom
enum ProjectsSheetSizing {
/// iPhone `nil`** `.presentationDetents`** sheet
/// iPhone iPad `[.medium, .large]`
///
static func detents(idiom: UIUserInterfaceIdiom) -> Set<PresentationDetent>? {
idiom == .pad ? [.medium, .large] : nil
}
}
// MARK: - iPhone iPad detents modifier
/// `.presentationDetents` modifier nil `content`
/// iPhone sheet
private struct AdaptiveSheetDetents: ViewModifier {
let detents: Set<PresentationDetent>?
func body(content: Content) -> some View {
if let detents {
content.presentationDetents(detents)
} else {
content
}
}
}
extension View {
/// iPhone sheetiPad detents
func adaptiveProjectsSheetDetents(idiom: UIUserInterfaceIdiom) -> some View {
modifier(AdaptiveSheetDetents(detents: ProjectsSheetSizing.detents(idiom: idiom)))
}
}