From c93907af619ddb22d9e150ba9bbdb818eafc1099 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 1 Feb 2026 18:21:23 +0800 Subject: [PATCH 1/4] Add RootEnvironmentModifier --- .../App/App/UIKit/UIKitAppDelegate.swift | 133 ++++++++++++++---- .../OpenSwiftUI/App/Scene/ScenePhase.swift | 4 + .../OpenSwiftUI/App/Scene/SceneStorage.swift | 26 ++++ 3 files changed, 132 insertions(+), 31 deletions(-) create mode 100644 Sources/OpenSwiftUI/App/Scene/SceneStorage.swift diff --git a/Sources/OpenSwiftUI/App/App/UIKit/UIKitAppDelegate.swift b/Sources/OpenSwiftUI/App/App/UIKit/UIKitAppDelegate.swift index dc9e4e14a..578e8b2df 100644 --- a/Sources/OpenSwiftUI/App/App/UIKit/UIKitAppDelegate.swift +++ b/Sources/OpenSwiftUI/App/App/UIKit/UIKitAppDelegate.swift @@ -7,7 +7,15 @@ // ID: 4475FD12FD59DEBA453321BD91F6EA04 (SwiftUI) #if os(iOS) || os(visionOS) -import UIKit +import OpenAttributeGraphShims +package import OpenSwiftUICore +public import UIKit +#if OPENSWIFTUI_OPENCOMBINE +import OpenCombine +#else +import Combine +#endif + // MARK: - AppDelegate [TODO] @@ -145,36 +153,99 @@ class AppSceneDelegate: UIResponder, UIWindowSceneDelegate { // } } -//struct SwiftUI.RootModifier { -// weak var sceneBridge: Swift.Optional -// weak var sceneDelegateBox: Swift.Optional -// weak var sceneStorageValues: Swift.Optional -// var presentationDataValue: Swift.Optional -// var scenePhase: SwiftUI.ScenePhase -// var sceneID: Swift.Optional -// var _rootFocusScope: SwiftUI.Namespace -//} -//struct SwiftUI.(SceneSessionKey in _4475FD12FD59DEBA453321BD91F6EA04) { -// /* Static Stored Variable */ -// static SwiftUI.(SceneSessionKey in _4475FD12FD59DEBA453321BD91F6EA04).defaultValue : Swift.Optional> -//} -//struct SwiftUI.(RootEnvironmentModifier in _4475FD12FD59DEBA453321BD91F6EA04) { -// weak var sceneBridge: Swift.Optional -// weak var sceneDelegateBox: Swift.Optional -// weak var sceneStorageValues: Swift.Optional -// var scenePhase: SwiftUI.ScenePhase -// var sceneID: Swift.Optional -//} -//struct SwiftUI.(RootEnvironmentModifier in _4475FD12FD59DEBA453321BD91F6EA04).Child { -// var _modifier: AttributeGraph.Attribute -// var _env: AttributeGraph.Attribute -// var oldModifier: Swift.Optional -// -// /* Function */ -// SwiftUI.(RootEnvironmentModifier in _4475FD12FD59DEBA453321BD91F6EA04).Child.updateValue() -> () -//} +// MARK: - RootModifier [TODO] + +struct RootModifier { + weak var sceneBridge: SceneBridge? + + weak var sceneDelegateBox: AnyFallbackDelegateBox? + + weak var sceneStorageValues: SceneStorageValues? + + var presentationDataValue: AnyHashable? + + var scenePhase: ScenePhase + + var sceneID: SceneID? + + var _rootFocusScope: Namespace +} + +// MARK: - EnvironmentValues + sceneSession + +private struct SceneSessionKey: EnvironmentKey { + static let defaultValue: WeakBox? = nil +} + +@_spi(Private) +@available(OpenSwiftUI_v2_0, *) +@available(macOS, unavailable) +@available(watchOS, unavailable) +extension EnvironmentValues { + public var sceneSession: UISceneSession? { + get { self[SceneSessionKey.self]?.base } + set { self[SceneSessionKey.self] = newValue.map(WeakBox.init) } + } +} -// TODO -class SceneStorageValues {} +// MARK: - RootEnvironmentModifier + +private struct RootEnvironmentModifier: PrimitiveViewModifier, _GraphInputsModifier { + weak var sceneBridge: SceneBridge? + weak var sceneDelegateBox: AnyFallbackDelegateBox? + weak var sceneStorageValues: SceneStorageValues? + var scenePhase: ScenePhase + var sceneID: SceneID? + + static func _makeInputs( + modifier: _GraphValue, + inputs: inout _GraphInputs + ) { + inputs.environment = Attribute( + Child( + modifier: modifier.value, + env: inputs.environment + ) + ) + } + + struct Child: StatefulRule { + @Attribute var modifier: RootEnvironmentModifier + @Attribute var env: EnvironmentValues + var oldModifier: RootEnvironmentModifier? + + typealias Value = EnvironmentValues + + mutating func updateValue() { + let (modifier, modifierChanged) = $modifier.changedValue() + let (environment, environmentChanged) = $env.changedValue() + let shouldUpdate: Bool + if environmentChanged { + shouldUpdate = true + } else if modifierChanged && oldModifier.map({ compareValues($0, modifier) }) != false { + shouldUpdate = true + } else if !hasValue { + shouldUpdate = true + } else { + shouldUpdate = false + } + guard shouldUpdate else { + return + } + var result = environment + result[keyPath: SceneBridge.environmentStore] = modifier.sceneBridge + result.sceneStorageValues = modifier.sceneStorageValues + result.scenePhase = modifier.scenePhase + result.sceneID = modifier.sceneID + if modifier.scenePhase != .active { + result.redactionReasons.formUnion(.privacy) + } + modifier.sceneDelegateBox?.addDelegate(to: &result) + AppGraph.delegateBox?.addDelegate(to: &result) + value = result + oldModifier = modifier + } + } +} #endif diff --git a/Sources/OpenSwiftUI/App/Scene/ScenePhase.swift b/Sources/OpenSwiftUI/App/Scene/ScenePhase.swift index 3864cf188..e7bbf6c58 100644 --- a/Sources/OpenSwiftUI/App/Scene/ScenePhase.swift +++ b/Sources/OpenSwiftUI/App/Scene/ScenePhase.swift @@ -6,6 +6,8 @@ // Status: Complete // ID: 130BB08D98602D712FD59CAC6992C14A (SwiftUI) +// MARK: - ScenePhase + /// An indication of a scene's operational state. /// /// The system moves your app's ``Scene`` instances through phases that reflect @@ -96,6 +98,8 @@ public enum ScenePhase: Comparable { case active } +// MARK: - EnvironmentValues + scenePhase + private struct ScenePhaseKey: EnvironmentKey { static let defaultValue: ScenePhase = .background } diff --git a/Sources/OpenSwiftUI/App/Scene/SceneStorage.swift b/Sources/OpenSwiftUI/App/Scene/SceneStorage.swift new file mode 100644 index 000000000..048aea65b --- /dev/null +++ b/Sources/OpenSwiftUI/App/Scene/SceneStorage.swift @@ -0,0 +1,26 @@ +// +// SceneStorage.swift +// OpenSwiftUI +// +// Audited for 6.5.4 +// Status: TODO +// ID: 1700ED20D4EA891B02973E899ABDB425 (SwiftUI) + +import OpenSwiftUICore + +// MARK: - SceneStorageValues [WIP] + +class SceneStorageValues {} + +// MARK: - EnvironmentValues + sceneStorageValues + +private struct SceneStorageValuesKey: EnvironmentKey { + static let defaultValue: WeakBox? = nil +} + +extension EnvironmentValues { + var sceneStorageValues: SceneStorageValues? { + get { self[SceneStorageValuesKey.self]?.base } + set { self[SceneStorageValuesKey.self] = newValue.map(WeakBox.init) } + } +} From d11b9d0010d4f97a9e6edffe4219cbdfc7c1b01c Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 1 Feb 2026 18:56:58 +0800 Subject: [PATCH 2/4] Implement RootModifier --- .../App/App/UIKit/UIKitAppDelegate.swift | 42 ++++++++++++++---- .../PresentedSceneValueInputModifier.swift | 44 +++++++++++++++++++ 2 files changed, 77 insertions(+), 9 deletions(-) create mode 100644 Sources/OpenSwiftUI/Modifier/ViewModifier/PresentedSceneValueInputModifier.swift diff --git a/Sources/OpenSwiftUI/App/App/UIKit/UIKitAppDelegate.swift b/Sources/OpenSwiftUI/App/App/UIKit/UIKitAppDelegate.swift index 578e8b2df..a02f9c4eb 100644 --- a/Sources/OpenSwiftUI/App/App/UIKit/UIKitAppDelegate.swift +++ b/Sources/OpenSwiftUI/App/App/UIKit/UIKitAppDelegate.swift @@ -153,22 +153,28 @@ class AppSceneDelegate: UIResponder, UIWindowSceneDelegate { // } } -// MARK: - RootModifier [TODO] +// MARK: - RootModifier -struct RootModifier { +struct RootModifier: ViewModifier { weak var sceneBridge: SceneBridge? - weak var sceneDelegateBox: AnyFallbackDelegateBox? - weak var sceneStorageValues: SceneStorageValues? - var presentationDataValue: AnyHashable? - var scenePhase: ScenePhase - var sceneID: SceneID? - - var _rootFocusScope: Namespace + @Namespace var rootFocusScope + + func body(content: Content) -> some View { + content + .rootEnvironment( + sceneBridge: sceneBridge, + sceneDelegateBox: sceneDelegateBox, + sceneStorageValues: sceneStorageValues, + scenePhase: scenePhase, + sceneID: sceneID + ) + .presentedSceneValue(presentationDataValue) + } } // MARK: - EnvironmentValues + sceneSession @@ -190,6 +196,24 @@ extension EnvironmentValues { // MARK: - RootEnvironmentModifier +extension View { + func rootEnvironment( + sceneBridge: SceneBridge? = nil, + sceneDelegateBox: AnyFallbackDelegateBox? = nil, + sceneStorageValues: SceneStorageValues? = nil, + scenePhase: ScenePhase = .background, + sceneID: SceneID? = nil + ) -> some View { + modifier(RootEnvironmentModifier( + sceneBridge: sceneBridge, + sceneDelegateBox: sceneDelegateBox, + sceneStorageValues: sceneStorageValues, + scenePhase: scenePhase, + sceneID: sceneID + )) + } +} + private struct RootEnvironmentModifier: PrimitiveViewModifier, _GraphInputsModifier { weak var sceneBridge: SceneBridge? weak var sceneDelegateBox: AnyFallbackDelegateBox? diff --git a/Sources/OpenSwiftUI/Modifier/ViewModifier/PresentedSceneValueInputModifier.swift b/Sources/OpenSwiftUI/Modifier/ViewModifier/PresentedSceneValueInputModifier.swift new file mode 100644 index 000000000..4ff0c57ca --- /dev/null +++ b/Sources/OpenSwiftUI/Modifier/ViewModifier/PresentedSceneValueInputModifier.swift @@ -0,0 +1,44 @@ +// +// PresentedSceneValueInputModifier.swift +// OpenSwiftUI +// +// Audited for 6.5.4 +// Status: TODO +// ID: 16926B370582AC5E886A9B0FCFCEA0ED (SwiftUI?) + +import OpenAttributeGraphShims +import OpenSwiftUICore + +extension WindowGroup { + // TODO +} + +// TODO +public struct PresentedWindowContent {} + +// MARK: - PresentedSceneValueInput + +private struct PresentedSceneValueInput: ViewInput { + static var defaultValue: OptionalAttribute { .init() } +} + +// MARK: - PresentedSceneValueInputModifier + +extension View { + func presentedSceneValue( + _ value: AnyHashable? + ) -> some View { + modifier(PresentedSceneValueInputModifier(presentedValue: value)) + } +} + +private struct PresentedSceneValueInputModifier: ViewInputsModifier { + var presentedValue: AnyHashable? + + static func _makeViewInputs( + modifier: _GraphValue, + inputs: inout _ViewInputs + ) { + inputs[PresentedSceneValueInput.self] = .init(modifier.value.presentedValue) + } +} From 4822de970a5d50b887c2499dc1f76c2de6b1cc21 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 1 Feb 2026 19:04:45 +0800 Subject: [PATCH 3/4] Add rootModifier support --- .../App/App/UIKit/UIKitAppDelegate.swift | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/Sources/OpenSwiftUI/App/App/UIKit/UIKitAppDelegate.swift b/Sources/OpenSwiftUI/App/App/UIKit/UIKitAppDelegate.swift index a02f9c4eb..ae75a6ed1 100644 --- a/Sources/OpenSwiftUI/App/App/UIKit/UIKitAppDelegate.swift +++ b/Sources/OpenSwiftUI/App/App/UIKit/UIKitAppDelegate.swift @@ -16,7 +16,6 @@ import OpenCombine import Combine #endif - // MARK: - AppDelegate [TODO] class AppDelegate: UIResponder, UIApplicationDelegate { @@ -144,13 +143,27 @@ class AppSceneDelegate: UIResponder, UIWindowSceneDelegate { super.init() } -// private var rootModifier: RootModifier { -// -// } -// -// private func makeRootView(_ view: AnyView) -> ModifiedContent { -// // for each appRootViewWrappers and then rootModifier -// } + private var rootModifier: RootModifier { + guard let sceneBridge else { + preconditionFailure("Application configuration error.") + } + guard let sceneStorageValues else { + preconditionFailure("State restoration error.") + } + return RootModifier( + sceneBridge: sceneBridge, + sceneDelegateBox: sceneDelegateBox, + sceneStorageValues: sceneStorageValues, + presentationDataValue: presentationDataValue, + scenePhase: scenePhase, + sceneID: sceneItemID + ) + } + + private func makeRootView(_ view: AnyView) -> ModifiedContent { + // TODO: for each appRootViewWrappers and then rootModifier + view.modifier(rootModifier) + } } // MARK: - RootModifier @@ -271,5 +284,4 @@ private struct RootEnvironmentModifier: PrimitiveViewModifier, _GraphInputsModif } } } - #endif From e58e5a7e3a9c7016ea48680a935e512d9123944b Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 1 Feb 2026 19:10:35 +0800 Subject: [PATCH 4/4] Add registerAppRootModifier --- Sources/OpenSwiftUI/App/App/App.swift | 25 +++++++++++++++++-- .../App/App/UIKit/UIKitAppDelegate.swift | 3 +-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Sources/OpenSwiftUI/App/App/App.swift b/Sources/OpenSwiftUI/App/App/App.swift index 8d7b2b870..fa32e6036 100644 --- a/Sources/OpenSwiftUI/App/App/App.swift +++ b/Sources/OpenSwiftUI/App/App/App.swift @@ -6,6 +6,10 @@ // Status: Complete // ID: 20E520D074F8AF54E6253E3E22B86490 (SwiftUI) +import OpenSwiftUICore + +// MARK: - App + /// A type that represents the structure and behavior of an app. /// /// Create an app by declaring a structure that conforms to the `App` protocol. @@ -140,6 +144,25 @@ extension App { } } +// MARK: - AppRootModifier + +private var appRootViewWrappers: [(AnyView) -> AnyView] = [] + +@_spi(Private) +public func registerAppRootModifier(_ modifier: M) where M: ViewModifier { + appRootViewWrappers.append({ AnyView($0.modifier(modifier)) }) +} + +func applyAppRootModifier(_ view: AnyView) -> AnyView { + var result = view + for modifier in appRootViewWrappers { + result = modifier(result) + } + return result +} + +// MARK: - Platform implementation + #if os(iOS) || os(visionOS) import UIKit typealias DelegateBaseClass = UIResponder @@ -165,5 +188,3 @@ func runTestingApp(rootView: V1, comparisonView: V2, didLaunch: @escapin _openSwiftUIPlatformUnimplementedFailure() } #endif - -/*private*/ var appRootViewWrappers: [(AnyView) -> AnyView] = [] diff --git a/Sources/OpenSwiftUI/App/App/UIKit/UIKitAppDelegate.swift b/Sources/OpenSwiftUI/App/App/UIKit/UIKitAppDelegate.swift index ae75a6ed1..0a1bf74c6 100644 --- a/Sources/OpenSwiftUI/App/App/UIKit/UIKitAppDelegate.swift +++ b/Sources/OpenSwiftUI/App/App/UIKit/UIKitAppDelegate.swift @@ -161,8 +161,7 @@ class AppSceneDelegate: UIResponder, UIWindowSceneDelegate { } private func makeRootView(_ view: AnyView) -> ModifiedContent { - // TODO: for each appRootViewWrappers and then rootModifier - view.modifier(rootModifier) + applyAppRootModifier(view).modifier(rootModifier) } }