diff --git a/Package.resolved b/Package.resolved index cabe9deb9..c35f679df 100644 --- a/Package.resolved +++ b/Package.resolved @@ -7,7 +7,7 @@ "location" : "https://github.com/OpenSwiftUIProject/DarwinPrivateFrameworks.git", "state" : { "branch" : "main", - "revision" : "e12014b79f31a1483d7633f188c520fdf40f79c1" + "revision" : "d115c29b7468940969b0c2f5cb0d612a28563a02" } }, { @@ -25,7 +25,7 @@ "location" : "https://github.com/OpenSwiftUIProject/OpenGraph", "state" : { "branch" : "main", - "revision" : "c35c4812e5b0803153bbf09a95e28a115d44e798" + "revision" : "cbe7eaf78ee9a3b29714131f7699d79b61bf4f81" } }, { diff --git a/Sources/OpenSwiftUI/Integration/Hosting/UIKit/View/UIHostingView.swift b/Sources/OpenSwiftUI/Integration/Hosting/UIKit/View/UIHostingView.swift index c5ce3dd6d..c62d66338 100644 --- a/Sources/OpenSwiftUI/Integration/Hosting/UIKit/View/UIHostingView.swift +++ b/Sources/OpenSwiftUI/Integration/Hosting/UIKit/View/UIHostingView.swift @@ -684,7 +684,8 @@ extension _UIHostingView: ViewRendererHost { } package func rootTransform() -> ViewTransform { - preconditionFailure("TODO") + openSwiftUIUnimplementedWarning() + return ViewTransform() } public func preferencesDidChange() { diff --git a/Sources/OpenSwiftUICore/Data/Preference/PreferenceTransformModifier.swift b/Sources/OpenSwiftUICore/Data/Preference/PreferenceTransformModifier.swift index 20140d9b7..148cea7b9 100644 --- a/Sources/OpenSwiftUICore/Data/Preference/PreferenceTransformModifier.swift +++ b/Sources/OpenSwiftUICore/Data/Preference/PreferenceTransformModifier.swift @@ -7,7 +7,7 @@ package import OpenGraphShims -// MARK: - PreferenceTransformModifier [6.4.41] [WIP] +// MARK: - PreferenceTransformModifier [6.4.41] @available(OpenSwiftUI_v1_0, *) @frozen @@ -52,29 +52,114 @@ extension View { } } +// MARK: - PreferencesOutputs + makePreferenceTransformer [6.0.87] + extension PreferencesOutputs { package mutating func makePreferenceTransformer( inputs: PreferencesInputs, - key _: K.Type, + key: K.Type, transform: @autoclosure () -> Attribute<(inout K.Value) -> Void> ) where K: PreferenceKey { - openSwiftUIUnimplementedWarning() + let contains = inputs.contains(K.self) + let transformValue: Attribute<(inout K.Value) -> Void>! + if contains { + transformValue = transform() + let transform = PreferenceTransform( + transform: transformValue, + childValue: OptionalAttribute(self[key]) + ) + self[key] = Attribute(transform) + } else { + transformValue = nil + } + guard K._isReadableByHost, inputs.contains(HostPreferencesKey.self) else { + return + } + let hostTransform = HostPreferencesTransform( + transform: transformValue ?? transform(), + keys: inputs.hostKeys, + childValues: OptionalAttribute(self[HostPreferencesKey.self]), + keyRequested: false, + wasEmpty: false, + delta: 0, + nodeId: HostPreferencesKey.makeNodeId() + ) + self[HostPreferencesKey.self] = Attribute(hostTransform) } } -// TODO -private struct PreferenceTransform where K: PreferenceKey { +// MARK: - PreferenceTransform [6.0.87] + +private struct PreferenceTransform: Rule, AsyncAttribute, CustomStringConvertible where K: PreferenceKey { @Attribute var transform: (inout K.Value) -> Void @OptionalAttribute var childValue: K.Value? + + var value: K.Value { + var value = childValue ?? K.defaultValue + $transform.syncMainIfReferences { transform in + // TODO: Observation support + transform(&value) + } + return value + } + + var description: String { + "Transform: \(K.readableName)" + } } -// TODO -private struct HostPreferencesTransform where K: PreferenceKey { +// MARK: - HostPreferencesTransform [6.0.87] + +private struct HostPreferencesTransform: StatefulRule, AsyncAttribute, CustomStringConvertible where K: PreferenceKey { @Attribute var transform: (inout K.Value) -> Void - @Attribute var keys: Attribute - @OptionalAttribute var childValues: PreferenceValues? + @Attribute var keys: PreferenceKeys + // FIXME: [6.4.41] + // @OptionalAttribute var childValues: PreferenceValues? + @OptionalAttribute var childValues: PreferenceList? var keyRequested: Bool var wasEmpty: Bool var delta: UInt32 let nodeId: UInt32 + + typealias Value = PreferenceList + + mutating func updateValue() { + var values: PreferenceList + let valuesChanged: Bool + if let childValues = $childValues { + (values, valuesChanged) = childValues.changedValue() + wasEmpty = false + } else { + (values, valuesChanged) = (PreferenceList(), !wasEmpty) + wasEmpty = true + } + var requiresUpdate = valuesChanged + let (keys, keysChanged) = $keys.changedValue() + + let keyContains = keysChanged ? keys.contains(K.self) : false + if keyRequested != keyContains { + keyRequested = keyContains + requiresUpdate = true + } + if keyRequested { + let anyInputsChanged = [_keys.identifier, _childValues.base.identifier].anyInputsChanged + if anyInputsChanged { + delta &+= 1 + requiresUpdate = true + } + if anyInputsChanged || requiresUpdate { + $transform.syncMainIfReferences { transform in + let transformValue = PreferenceList.Value(value: transform, seed: VersionSeed(nodeId: nodeId, viewSeed: delta)) + values.modifyValue(for: K.self, transform: transformValue) + } + } + } + if requiresUpdate || !hasValue { + value = values + } + } + + var description: String { + "HostTransform: \(K.readableName)" + } } diff --git a/Sources/OpenSwiftUICore/Data/Preference/PreferencesInputs.swift b/Sources/OpenSwiftUICore/Data/Preference/PreferencesInputs.swift index adbc86ed5..4708b996a 100644 --- a/Sources/OpenSwiftUICore/Data/Preference/PreferencesInputs.swift +++ b/Sources/OpenSwiftUICore/Data/Preference/PreferencesInputs.swift @@ -34,14 +34,11 @@ package struct PreferencesInputs { @inlinable package func contains(_ key: K.Type, includeHostPreferences: Bool) -> Bool where K: PreferenceKey { - let result = keys.contains(key) + let result = contains(key) guard !result, includeHostPreferences else { return result } - guard K._isReadableByHost else { - return false - } - return keys.contains(_AnyPreferenceKey.self) + return K._isReadableByHost && contains(HostPreferencesKey.self) } package func makeIndirectOutputs() -> PreferencesOutputs { diff --git a/Sources/OpenSwiftUICore/OpenGraph/Attribute/AnyAttributeFix.swift b/Sources/OpenSwiftUICore/OpenGraph/Attribute/AnyAttributeFix.swift index 0f0d4b526..fc9099aa9 100644 --- a/Sources/OpenSwiftUICore/OpenGraph/Attribute/AnyAttributeFix.swift +++ b/Sources/OpenSwiftUICore/OpenGraph/Attribute/AnyAttributeFix.swift @@ -173,4 +173,10 @@ extension Rule where Self: Hashable { preconditionFailure("#39") } } + +extension [AnyAttribute] { + package var anyInputsChanged: Bool { + false + } +} #endif