Files
phranck 5ad97132b8 Feat: Add @Observable support with Observation framework
- 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
2026-02-15 23:49:34 +01:00

92 lines
2.8 KiB
Swift
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 🖥 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
}
}