import Foundation @MainActor public struct ErasedViewGraphNode { public var node: AnyObject /// If the new view doesn't have the same type as the old view then the returned /// value will have `viewTypeMatched` set to `false`, allowing views such as `AnyView` /// to choose how to react to a mismatch. In `AnyView`'s case this means throwing away /// the current view graph node and creating a new one for the new view type. public var computeLayoutWithNewView: ( _ newView: Any?, _ proposedSize: ProposedViewSize, _ environment: EnvironmentValues ) -> (viewTypeMatched: Bool, size: ViewLayoutResult) /// The underlying view graph node's commit method. public var commit: () -> ViewLayoutResult public var getWidget: () -> AnyWidget public var viewType: any View.Type public var backendType: any BaseAppBackend.Type public init( for view: V, backend: Backend, snapshot: ViewGraphSnapshotter.NodeSnapshot? = nil, environment: EnvironmentValues ) { self.init( wrapping: ViewGraphNode( for: view, backend: backend, snapshot: snapshot, environment: environment ) ) } public init( wrapping node: ViewGraphNode ) { self.node = node backendType = Backend.self viewType = V.self computeLayoutWithNewView = { view, proposedSize, environment in if let view { guard let view = view as? V else { return (false, ViewLayoutResult.leafView(size: .zero)) } let size = node.computeLayout( with: view, proposedSize: proposedSize, environment: environment ) return (true, size) } else { let size = node.computeLayout( with: nil, proposedSize: proposedSize, environment: environment ) return (true, size) } } commit = node.commit getWidget = { return AnyWidget(node.widget) } } public init(wrapping node: AnyViewGraphNode) { self.init(wrapping: node, backend: node.getBackend()) } private init( wrapping node: AnyViewGraphNode, backend: Backend ) { self.init(wrapping: node.node as! ViewGraphNode) } public func transform(with transformer: any ErasedViewGraphNodeTransformer) -> R { func helper( viewType: V.Type, backendType: Backend.Type ) -> R { transformer.transform(node: node as! ViewGraphNode) } return helper(viewType: viewType, backendType: backendType) } } @MainActor public protocol ErasedViewGraphNodeTransformer { associatedtype Return func transform(node: ViewGraphNode) -> Return }