mirror of
https://github.com/phranck/TUIkit.git
synced 2026-06-20 09:54:37 +00:00
- Replace custom Observable protocol and @Published with Apple's @Observable macro - Add withObservationTracking in renderToBuffer for automatic per-property dependency tracking - Add type-based @Environment(Type.self) and .environment(object) for observable objects - Add ObjectEnvironmentModifier for injecting observable objects into the environment - Add needsCacheClear flag to AppState for thread-safe cache invalidation - Add cross-platform test script (scripts/test-linux.sh) for Docker-based Linux verification - Add DemoAppHeader with system info display (OS, version, architecture) - Consolidate Example App: extract ImageDemoHelpers, KeyboardHelpSection, ValueDisplayRow - Add pre-push verification rule to CLAUDE.md - Verified on both macOS and Linux (swift:6.0 container), 1155 tests passing
92 lines
2.8 KiB
Swift
92 lines
2.8 KiB
Swift
// 🖥️ TUIKit — Terminal UI Kit for Swift
|
|
// EnvironmentKey.swift
|
|
//
|
|
// Created by LAYERED.work
|
|
// License: MIT
|
|
|
|
import Observation
|
|
|
|
// MARK: - Environment Key Protocol
|
|
|
|
/// A key for accessing values in the environment.
|
|
///
|
|
/// Conform to this protocol to define custom environment values.
|
|
///
|
|
/// # Example
|
|
///
|
|
/// ```swift
|
|
/// struct MyCustomKey: EnvironmentKey {
|
|
/// static var defaultValue: String = "default"
|
|
/// }
|
|
///
|
|
/// extension EnvironmentValues {
|
|
/// var myCustomValue: String {
|
|
/// get { self[MyCustomKey.self] }
|
|
/// set { self[MyCustomKey.self] = newValue }
|
|
/// }
|
|
/// }
|
|
/// ```
|
|
public protocol EnvironmentKey {
|
|
/// The type of value stored by this key.
|
|
associatedtype Value
|
|
|
|
/// The default value for this key.
|
|
static var defaultValue: Value { get }
|
|
}
|
|
|
|
// MARK: - Environment Values
|
|
|
|
/// A collection of environment values propagated through the view hierarchy.
|
|
///
|
|
/// Environment values flow down from parent views to child views.
|
|
/// Each view can read environment values and optionally override them
|
|
/// for its children.
|
|
public struct EnvironmentValues: @unchecked Sendable {
|
|
/// Storage for environment values.
|
|
private var storage: [ObjectIdentifier: Any] = [:]
|
|
|
|
/// Creates an empty environment values container.
|
|
public init() {}
|
|
|
|
/// Accesses the environment value for the given key.
|
|
///
|
|
/// - Parameter key: The type of the environment key.
|
|
/// - Returns: The value for the key, or its default value if not set.
|
|
public subscript<K: EnvironmentKey>(key: K.Type) -> K.Value {
|
|
get {
|
|
if let value = storage[ObjectIdentifier(key)] as? K.Value {
|
|
return value
|
|
}
|
|
return K.defaultValue
|
|
}
|
|
set {
|
|
storage[ObjectIdentifier(key)] = newValue
|
|
}
|
|
}
|
|
|
|
/// Accesses an observable object stored by its type.
|
|
///
|
|
/// Objects stored via `.environment(model)` are keyed by
|
|
/// `ObjectIdentifier(type(of: object))`, enabling type-based lookup
|
|
/// via `@Environment(MyModel.self)`.
|
|
///
|
|
/// - Parameter type: The observable object's type.
|
|
/// - Returns: The stored object, or `nil` if not set.
|
|
public subscript<T: Observable>(observable type: T.Type) -> T? {
|
|
get { storage[ObjectIdentifier(type)] as? T }
|
|
set { storage[ObjectIdentifier(type)] = newValue }
|
|
}
|
|
|
|
/// Creates a copy of this environment with a modified value.
|
|
///
|
|
/// - Parameters:
|
|
/// - keyPath: The key path to the value to modify.
|
|
/// - value: The new value.
|
|
/// - Returns: A new EnvironmentValues with the modified value.
|
|
public func setting<V>(_ keyPath: WritableKeyPath<Self, V>, to value: V) -> Self {
|
|
var copy = self
|
|
copy[keyPath: keyPath] = value
|
|
return copy
|
|
}
|
|
}
|