// // EquatableView.swift // ark_ui_basic // // Audited for 6.5.4 // Status: Complete // ID: 93C51C71D9D4CBAB391E78A2AAC640D6 (SwiftUI) import OpenAttributeGraphShims @_spi(ForOpenSwiftUIOnly) import ark_ui_basic_core // MARK: - EquatableView /// A view type that compares itself against its previous value and prevents its /// child updating if its new value is the same as its old value. @available(OpenSwiftUI_v1_0, *) @frozen public struct EquatableView: View, UnaryView, PrimitiveView where Content: Equatable, Content: View { public var content: Content @inlinable public init(content: Content) { self.content = content } nonisolated public static func _makeView( view: _GraphValue, inputs: _ViewInputs ) -> _ViewOutputs { let child = Child(view: view.value) return Content.makeDebuggableView( view: _GraphValue(child), inputs: inputs ) } private struct Child: Rule, AsyncAttribute { @Attribute var view: EquatableView typealias Value = Content var value: Value { view.content } static var comparisonMode: ComparisonMode { .equatableAlways } } } @available(*, unavailable) extension EquatableView: Sendable {} extension View where Self: Equatable { /// Prevents the view from updating its child view when its new value is the /// same as its old value. @inlinable nonisolated public func equatable() -> EquatableView { EquatableView(content: self) } } // MARK: - EquatableProxyView package struct EquatableProxyView: View, UnaryView, PrimitiveView where Content: View, Token: Equatable { package var content: Content package var token: Token package init(content: Content, token: Token) { self.content = content self.token = token } nonisolated public static func _makeView( view: _GraphValue, inputs: _ViewInputs ) -> _ViewOutputs { let child = Child(view: view.value, lastToken: nil) return Content.makeDebuggableView( view: _GraphValue(child), inputs: inputs ) } private struct Child: StatefulRule, AsyncAttribute { @Attribute var view: EquatableProxyView var lastToken: Token? init(view: Attribute, lastToken: Token?) { self._view = view self.lastToken = lastToken } typealias Value = Content mutating func updateValue() { guard hasValue && lastToken == view.token else { value = view.content lastToken = view.token return } } } } extension View { /// Prevents the view from updating its child view when its new value is the /// same as its old value. nonisolated package func equatableProxy(_ token: Token) -> EquatableProxyView where Token: Equatable { EquatableProxyView(content: self, token: token) } }