import SwiftUI import UIKit /// T-iOS-34 · 终端画布配色 —— **跟随主题**的那一半。 /// /// 此前终端是"固定暖深色,不随外观变"(对齐桌面)。浅色主题落地后这条不成立: /// 用户选了浅色,却有一整块纯黑画布占满屏,是最刺眼的破绽。所以画布按有效外观 /// 取两套值: /// - 深色 = `#100F0D` / `#ECE9E3`(桌面 web `--bg` / `--text`,**逐字节不变**); /// - 浅色 = `#F6F7F9` / `#1A1D24`(镜像 web `public/settings.ts` 的 /// `THEMES.light`,iOS 与桌面浅色档观感一致)。 /// /// caret / selection 用**该档**的 accent 解析值(深色金 `#E3A64A` / 浅色深金 /// `#C9892F`),不写死深色档的金。 /// /// 说明(重要):`SwiftTerm.TerminalView` 在 `nativeBackgroundColor` 的 setter 里 /// 就把 UIColor 压成了内部 `terminal.backgroundColor`(`iOSTerminalView.swift:1207`), /// 且没有 `traitCollectionDidChange` 重取 —— 因此**动态 UIColor 只能保证"构建时 /// 取对档"**,主题在会话进行中切换必须由视图侧重新 `apply` 一次。本文件提供两种 /// 形态供调用点选择:`colors(for:)`(已解析,重套用)与 `dynamic*`(动态 UIColor, /// 构建时取当前 trait)。 enum TerminalPalette { /// 一档终端画布的四个颜色。全部是**已解析**的具体色(不是动态色), /// 便于直接交给 SwiftTerm,也便于测试逐字节断言。 struct Colors: Equatable { let background: UIColor let foreground: UIColor let caret: UIColor let selection: UIColor } /// 深色档(桌面对齐,历史值)。 private enum Dark { static let background: UInt32 = 0x100F_0D static let foreground: UInt32 = 0xECE9_E3 } /// 浅色档(镜像 web `THEMES.light`)。 private enum Light { static let background: UInt32 = 0xF6F7_F9 static let foreground: UInt32 = 0x1A1D_24 } static func colors(for scheme: ColorScheme) -> Colors { let style = scheme.userInterfaceStyle let accent = DS.Palette.accentUIColor() .resolvedColor(with: UITraitCollection(userInterfaceStyle: style)) let isDark = style == .dark return Colors( background: UIColor(hex: isDark ? Dark.background : Light.background), foreground: UIColor(hex: isDark ? Dark.foreground : Light.foreground), caret: accent, selection: accent ) } /// 动态背景色 —— 取值时机决定档位(SwiftUI/UIKit 的 trait 解析)。 static func dynamicBackground() -> UIColor { UIColor { trait in colors(for: trait.colorScheme).background } } /// 动态前景色。 static func dynamicForeground() -> UIColor { UIColor { trait in colors(for: trait.colorScheme).foreground } } } // MARK: - 外观桥(ColorScheme ↔ UIUserInterfaceStyle) extension ColorScheme { /// SwiftUI → UIKit。`ColorScheme` 只有 light/dark 两个 case,故是全函数。 var userInterfaceStyle: UIUserInterfaceStyle { self == .dark ? .dark : .light } } extension UITraitCollection { /// UIKit → SwiftUI。`.unspecified` 按 iOS 的默认外观算作浅色。 var colorScheme: ColorScheme { userInterfaceStyle == .dark ? .dark : .light } } // MARK: - Hex extension UIColor { /// 从 `0xRRGGBB` 构建不透明 sRGB 色。设计 token 的十六进制值在文档/CSS 里 /// 就是这个写法,直接用它可以逐字节对照,不必手算 0–1 分量。 convenience init(hex: UInt32, alpha: CGFloat = 1) { self.init( red: CGFloat((hex >> 16) & 0xFF) / 255, green: CGFloat((hex >> 8) & 0xFF) / 255, blue: CGFloat(hex & 0xFF) / 255, alpha: alpha ) } }