From 8db0141da7508f217f74b1c7939b57239b161ac4 Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 25 May 2025 20:25:16 +0800 Subject: [PATCH 1/2] Update ViewInputs API --- .../Data/Environment/CachedEnvironment.swift | 8 ++ .../Layout/View/ViewTransform.swift | 2 + .../View/Input/ViewInputs.swift | 115 +++++++++++++++--- 3 files changed, 110 insertions(+), 15 deletions(-) diff --git a/Sources/OpenSwiftUICore/Data/Environment/CachedEnvironment.swift b/Sources/OpenSwiftUICore/Data/Environment/CachedEnvironment.swift index 6dd419e8..11c25ef9 100644 --- a/Sources/OpenSwiftUICore/Data/Environment/CachedEnvironment.swift +++ b/Sources/OpenSwiftUICore/Data/Environment/CachedEnvironment.swift @@ -58,6 +58,14 @@ package struct CachedEnvironment { } // func resolvedForegroundStyle() {} + + func resolvedShapeStyles( + for inputs: _ViewInputs, + role: ShapeRole, + mode: Attribute<_ShapeStyle_ResolverMode>? + ) -> Attribute<_ShapeStyle_Pack> { + preconditionFailure("TODO") + } } extension CachedEnvironment { diff --git a/Sources/OpenSwiftUICore/Layout/View/ViewTransform.swift b/Sources/OpenSwiftUICore/Layout/View/ViewTransform.swift index 93d584d6..e10643ad 100644 --- a/Sources/OpenSwiftUICore/Layout/View/ViewTransform.swift +++ b/Sources/OpenSwiftUICore/Layout/View/ViewTransform.swift @@ -8,7 +8,9 @@ // ID: 1CC2FE016A82CF91549A64E942CE8ED4 (SwiftUICore) package import Foundation +#if !canImport(Darwin) package import CoreGraphicsShims +#endif @_spi(ForOpenSwiftUIOnly) public struct ViewTransform: Equatable, CustomStringConvertible { diff --git a/Sources/OpenSwiftUICore/View/Input/ViewInputs.swift b/Sources/OpenSwiftUICore/View/Input/ViewInputs.swift index cb4d0d6e..d389ab63 100644 --- a/Sources/OpenSwiftUICore/View/Input/ViewInputs.swift +++ b/Sources/OpenSwiftUICore/View/Input/ViewInputs.swift @@ -2,7 +2,7 @@ // ViewInputs.swift // OpenSwiftUICore // -// Audited for iOS 18.0 +// ID: C38EF38637B6130AEFD462CBD5EAC727 (SwiftUICore) // Status: Complete #if !canImport(Darwin) @@ -10,6 +10,8 @@ package import Foundation #endif package import OpenGraphShims +// MARK: - ViewInputs [6.0.87] + package typealias ViewPhase = _GraphInputs.Phase package protocol ViewInput: GraphInput {} @@ -50,7 +52,10 @@ public struct _ViewInputs { package var viewPhase: Attribute { get { base.phase } - set { base.phase = newValue } + set { + base.phase = newValue + base.changedDebugProperties.formUnion(.phase) + } } package var transaction: Attribute { @@ -227,28 +232,108 @@ extension _ViewInputs { } @inline(__always) - func detachedEnvironmentInputs() -> Self { + func detachedEnvironmentInputs() -> _ViewInputs { var newInputs = self newInputs.detachEnvironmentInputs() return newInputs } } -// FIXME -@available(*, deprecated, message: "TO BE REMOVED") +// MARK: - DynamicStackOrientation [6.0.87] + +package struct DynamicStackOrientation: ViewInput { + package static let defaultValue: OptionalAttribute = .init() +} + +// MARK: - ViewInputs without Geometry Dependencies [6.4.41] + extension _ViewInputs { - mutating func append(_ value: Value, to type: Input.Type) where Input.Value == [Value] { - var values = base[type] - values.append(value) - base[type] = values + package var withoutGeometryDependencies: _ViewInputs { + let viewGraph = ViewGraph.current + var inputs = self + inputs.position = viewGraph.$zeroPoint + inputs.transform = viewGraph.intern(ViewTransform(), id: .defaultValue) + inputs.containerPosition = viewGraph.$zeroPoint + inputs.size = viewGraph.intern(ViewSize.zero, id: .defaultValue) + inputs.requestsLayoutComputer = false + inputs.needsGeometry = false + inputs.preferences.remove(DisplayList.Key.self) + inputs.preferences.remove(ViewRespondersKey.self) + return inputs } - mutating func popLast(_ type: Input.Type) -> Value? where Input.Value == [Value] { - var values = base[type] - guard let value = values.popLast() else { - return nil + package init(withoutGeometry base: _GraphInputs) { + let base = base + let viewGraph = ViewGraph.current + let position = viewGraph.$zeroPoint + let size = viewGraph.intern(ViewSize.zero, id: .defaultValue) + let transform = viewGraph.intern(ViewTransform(), id: .defaultValue) + let containerPosition = viewGraph.$zeroPoint + let hostKeys = Attribute(value: PreferenceKeys()) + + self.base = base + self.preferences = PreferencesInputs(hostKeys: hostKeys) + self.transform = transform + self.position = position + self.containerPosition = containerPosition + self.size = size + self.safeAreaInsets = .init() + self.scrollableContainerSize = .init() + } +} + +extension _ViewListInputs { + package var withoutGeometryDependencies: _ViewInputs { + let inputs = _ViewInputs(withoutGeometry: base) + return inputs.withoutGeometryDependencies + } +} + +// MARK: ResetDeltaModifier [6.4.41] + +private struct ResetDeltaModifier: MultiViewModifier, PrimitiveViewModifier { + var delta: UInt32 + + nonisolated static func _makeView( + modifier: _GraphValue, + inputs: _ViewInputs, + body: @escaping (_Graph, _ViewInputs) -> _ViewOutputs + ) -> _ViewOutputs { + var inputs = inputs + let phase = ChildPhase(base: inputs.base.phase, delta: modifier.value.unsafeOffset(at: 0, as: UInt32.self)) + inputs.viewPhase = Attribute(phase) + return body(_Graph(), inputs) + } + + struct ChildPhase: Rule { + @Attribute var base: _GraphInputs.Phase + @Attribute var delta: UInt32 + + var value: _GraphInputs.Phase { + var phase = base + phase.resetSeed += delta + return phase } - base[type] = values - return value + } +} + +extension View { + package func reset(delta: UInt32) -> some View { + modifier(ResetDeltaModifier(delta: delta)) + } +} + +// MARK: Resolve Shape Style [6.4.41] + +extension _ViewInputs { + package func resolvedShapeStyles( + role: ShapeRole, + mode: Attribute<_ShapeStyle_ResolverMode>? = nil + ) -> Attribute<_ShapeStyle_Pack> { + base.cachedEnvironment.wrappedValue.resolvedShapeStyles( + for: self, + role: role, + mode: mode + ) } } From 6fcbbaccf3609f314ef3a1c4906a3ac386e5fd7e Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 25 May 2025 20:25:29 +0800 Subject: [PATCH 2/2] Add test case to cover ViewInputs change --- .../View/Input/ViewInputsTest.swift | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 Tests/OpenSwiftUICoreTests/View/Input/ViewInputsTest.swift diff --git a/Tests/OpenSwiftUICoreTests/View/Input/ViewInputsTest.swift b/Tests/OpenSwiftUICoreTests/View/Input/ViewInputsTest.swift new file mode 100644 index 00000000..a2fb0c40 --- /dev/null +++ b/Tests/OpenSwiftUICoreTests/View/Input/ViewInputsTest.swift @@ -0,0 +1,35 @@ +// +// ViewInputsTest.swift +// OpenSwiftUICoreTests + +import OpenGraphShims +@_spi(ForOpenSwiftUIOnly) +import OpenSwiftUICore +import Testing + +@MainActor +@Suite(.enabled(if: attributeGraphEnabled)) +struct ViewInputsTest { + @Test + func debugProperties() { + let graph = ViewGraph(rootViewType: EmptyView.self) + graph.globalSubgraph.apply { + var inputs = _ViewInputs(withoutGeometry: graph.graphInputs) + + #expect(inputs.changedDebugProperties == .all) + inputs.changedDebugProperties = [] + + inputs.transform = .init(value: .init()) + #expect(inputs.changedDebugProperties.contains(.transform)) + + inputs.size = .init(value: .zero) + #expect(inputs.changedDebugProperties.contains(.size)) + + inputs.environment = .init(value: .init()) + #expect(inputs.changedDebugProperties.contains(.environment)) + + inputs.viewPhase = .init(value: .invalid) + #expect(inputs.changedDebugProperties.contains(.phase)) + } + } +}