Skip to content

Update ViewInputs API #302

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 25, 2025
Merged
Show file tree
Hide file tree
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
Expand Up @@ -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 {
Expand Down
2 changes: 2 additions & 0 deletions Sources/OpenSwiftUICore/Layout/View/ViewTransform.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
// ID: 1CC2FE016A82CF91549A64E942CE8ED4 (SwiftUICore)

package import Foundation
#if !canImport(Darwin)
package import CoreGraphicsShims
#endif

@_spi(ForOpenSwiftUIOnly)
public struct ViewTransform: Equatable, CustomStringConvertible {
Expand Down
115 changes: 100 additions & 15 deletions Sources/OpenSwiftUICore/View/Input/ViewInputs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
// ViewInputs.swift
// OpenSwiftUICore
//
// Audited for iOS 18.0
// ID: C38EF38637B6130AEFD462CBD5EAC727 (SwiftUICore)
// Status: Complete

#if !canImport(Darwin)
package import Foundation
#endif
package import OpenGraphShims

// MARK: - ViewInputs [6.0.87]

package typealias ViewPhase = _GraphInputs.Phase

package protocol ViewInput: GraphInput {}
Expand Down Expand Up @@ -50,7 +52,10 @@ public struct _ViewInputs {

package var viewPhase: Attribute<ViewPhase> {
get { base.phase }
set { base.phase = newValue }
set {
base.phase = newValue
base.changedDebugProperties.formUnion(.phase)
}
}

package var transaction: Attribute<Transaction> {
Expand Down Expand Up @@ -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<Axis?> = .init()
}

// MARK: - ViewInputs without Geometry Dependencies [6.4.41]

extension _ViewInputs {
mutating func append<Input: ViewInput, Value>(_ 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<Input: ViewInput, Value>(_ 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<ResetDeltaModifier>,
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
)
}
}
35 changes: 35 additions & 0 deletions Tests/OpenSwiftUICoreTests/View/Input/ViewInputsTest.swift
Original file line number Diff line number Diff line change
@@ -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))
}
}
}