Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
extension Scene {
/// Modifies the scene's environment.
///
/// - Parameters:
/// - keyPath: The key path to the environment value to update.
/// - newValue: The new value.
public func environment<T>(
_ keyPath: WritableKeyPath<EnvironmentValues, T>,
_ newValue: T
) -> some Scene {
SceneEnvironmentModifier(self) { environment in
environment.with(keyPath, newValue)
}
}

/// Modifies the scene's environment.
///
/// - Parameters:
/// - keyPath: The key path to the environment value to update.
/// - transform: A closure that transforms the environment at `keyPath`.
public func transformEnvironment<T>(
_ keyPath: WritableKeyPath<EnvironmentValues, T>,
transform: @escaping (inout T) -> Void
) -> some Scene {
SceneEnvironmentModifier(self) { environment in
var value = environment[keyPath: keyPath]
transform(&value)
return environment.with(keyPath, value)
}
}
}

struct SceneEnvironmentModifier<Content: Scene>: Scene {
typealias Node = SceneEnvironmentModifierNode<Content>

var content: Content
var modification: (EnvironmentValues) -> EnvironmentValues

var commands: Commands { content.commands }

init(
_ content: Content,
modification: @escaping (EnvironmentValues) -> EnvironmentValues
) {
self.content = content
self.modification = modification
}
}

final class SceneEnvironmentModifierNode<Content: Scene>: SceneGraphNode {
typealias NodeScene = SceneEnvironmentModifier<Content>

var modification: (EnvironmentValues) -> EnvironmentValues
var contentNode: Content.Node

init<Backend: AppBackend>(
from scene: NodeScene,
backend: Backend,
environment: EnvironmentValues
) {
self.modification = scene.modification
contentNode = Content.Node(
from: scene.content,
backend: backend,
environment: modification(environment)
)
}

func update<Backend: AppBackend>(
_ newScene: NodeScene?,
backend: Backend,
environment: EnvironmentValues
) {
if let newScene {
self.modification = newScene.modification
}

contentNode.update(
newScene?.content,
backend: backend,
environment: modification(environment)
)
}
}
Loading