Skip to content
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
109 changes: 109 additions & 0 deletions Sources/OpenSwiftUICore/Animation/Transition/AnyTransition.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
//
// AnyTransition.swift
// OpenSwiftUICore
//
// Audited for 6.5.4
// Status: Complete
// ID: 142ABD4E569D763299C4081019352BCD (SwiftUICore)

/// A type-erased transition.
///
/// - See Also: `Transition`
@available(OpenSwiftUI_v1_0, *)
@frozen
public struct AnyTransition {
fileprivate let box: AnyTransitionBox

/// Create an instance that type-erases `transition`.
@available(OpenSwiftUI_v5_0, *)
public init<T>(_ transition: T) where T: Transition {
self.box = TransitionBox(transition)
}

package func visitBase<V>(applying v: inout V) where V: TransitionVisitor {
box.visitBase(applying: &v)
}

package func visitType<V>(applying v: inout V) where V: TransitionTypeVisitor {
box.visitType(applying: &v)
}

package func base<T>(as _: T.Type) -> T? where T: Transition {
guard let box = box as? TransitionBox<T> else {
return nil
}
return box.base
}

package var isIdentity: Bool {
box.isIdentity
}

package func adjustedForAccessibility(prefersCrossFade: Bool) -> AnyTransition {
guard box.hasMotion, prefersCrossFade else {
return self
}
return .opacity
}
}

@available(*, unavailable)
extension AnyTransition: Sendable {}

package protocol TransitionVisitor {
mutating func visit<T>(_ transition: T) where T: Transition
}

package protocol TransitionTypeVisitor {
mutating func visit<T>(_ type: T.Type) where T: Transition
}

@available(OpenSwiftUI_v1_0, *)
@usableFromInline
class AnyTransitionBox {
init() {}

func visitBase<V>(applying v: inout V) where V: TransitionVisitor {
_openSwiftUIBaseClassAbstractMethod()
}

func visitType<V>(applying v: inout V) where V: TransitionTypeVisitor {
_openSwiftUIBaseClassAbstractMethod()
}

var isIdentity: Bool {
_openSwiftUIBaseClassAbstractMethod()
}

var hasMotion: Bool {
_openSwiftUIBaseClassAbstractMethod()
}
}

@available(*, unavailable)
extension AnyTransitionBox: Sendable {}

@available(OpenSwiftUI_v5_0, *)
private final class TransitionBox<T>: AnyTransitionBox where T: Transition {
let base: T

init(_ base: T) {
self.base = base
}

override func visitBase<V>(applying v: inout V) where V: TransitionVisitor {
v.visit(base)
}

override func visitType<V>(applying v: inout V) where V: TransitionTypeVisitor {
v.visit(T.self)
}

override var isIdentity: Bool {
T.Body.self == PlaceholderContentView<T>.self
}

override var hasMotion: Bool {
T.properties.hasMotion
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//
// ContentTransition.swift
// OpenSwiftUICore

// TODO

@available(OpenSwiftUI_v4_0, *)
public struct ContentTransition: Equatable, Sendable {
package enum Storage: Equatable, @unchecked Sendable {
case named(ContentTransition.NamedTransition)
// case custom(ContentTransition.CustomTransition)
// case symbolReplace(_SymbolEffect.ReplaceConfiguration)
}

@_spi(Private)
public struct Style: Hashable, Sendable/*, Codable*/ {
package enum Storage: Hashable, Sendable {
case `default`

case sessionWidget

case animatedWidget
}

package var storage: ContentTransition.Style.Storage

package init(_ storage: ContentTransition.Style.Storage) {
self.storage = storage
}

public static let `default`: ContentTransition.Style = .init(.default)

public static let sessionWidget: ContentTransition.Style = .init(.sessionWidget)

@available(OpenSwiftUI_v5_0, *)
public static let animatedWidget: ContentTransition.Style = .init(.animatedWidget)
}

package var storage: ContentTransition.Storage

package var isReplaceable: Bool

package init(storage: ContentTransition.Storage) {
_openSwiftUIUnimplementedFailure()
}

package struct NamedTransition: Hashable, Sendable {
package enum Name: Hashable {
case `default`
case identity
case opacity
case diff
case fadeIfDifferent
case text(different: Bool)
// case numericText(ContentTransition.NumericTextConfiguration)
}

package var name: ContentTransition.NamedTransition.Name
package var layoutDirection: LayoutDirection?
package var style: ContentTransition.Style?

package init(
name: ContentTransition.NamedTransition.Name = .default,
layoutDirection: LayoutDirection? = nil,
style: ContentTransition.Style? = nil
) {
self.name = name
self.layoutDirection = layoutDirection
self.style = style
}
}

// TODO: NumericTextConfiguration

// TODO
package enum Effect {}

package enum State {}
}
Loading