import SwiftUI /// 全局字体放大档位。面向视力不佳 / 老年用户:放大整个 App 的字号。 /// 倍率作用于所有走 `Font.tjScaled` / `Font.tjTitle` 等的字体(即全 App 固定字号)。 enum FontScale: String, CaseIterable, Identifiable { case standard, large, extraLarge, huge var id: String { rawValue } /// 字号倍率。超大档位有限,避免密集布局严重溢出。 var multiplier: CGFloat { switch self { case .standard: return 1.0 case .large: return 1.2 case .extraLarge: return 1.4 case .huge: return 1.6 } } var label: String { switch self { case .standard: return String(appLoc: "标准") case .large: return String(appLoc: "大") case .extraLarge: return String(appLoc: "特大") case .huge: return String(appLoc: "超大") } } var detail: String { switch self { case .standard: return String(appLoc: "默认字号") case .large: return String(appLoc: "字号放大 20%") case .extraLarge: return String(appLoc: "字号放大 40%") case .huge: return String(appLoc: "字号放大 60%") } } } /// 全 App 单例。持久化字体档位;切换后由根视图 `.id` 触发整树重建即时生效(同语言切换机制)。 @Observable final class FontScaleManager { static let shared = FontScaleManager() private let storageKey = "appFontScale" private(set) var scale: FontScale private init() { let saved = UserDefaults.standard.string(forKey: storageKey) scale = FontScale(rawValue: saved ?? "") ?? .standard appFontScale = scale.multiplier } func set(_ newScale: FontScale) { guard newScale != scale else { return } scale = newScale UserDefaults.standard.set(newScale.rawValue, forKey: storageKey) appFontScale = newScale.multiplier } } /// nonisolated 快照:`Font.tjScaled` 是 static func,在任意上下文按值读取倍率。 /// 只由 `FontScaleManager`(MainActor)写入;读为快照,无竞态影响(同 Localization 的 appLocBundle 模式)。 nonisolated(unsafe) var appFontScale: CGFloat = 1.0