Skip to content

Commit 7ce96da

Browse files
authored
Implement ArchivedAnimation (#562)
1 parent 0740340 commit 7ce96da

File tree

1 file changed

+122
-6
lines changed

1 file changed

+122
-6
lines changed

Sources/OpenSwiftUICore/Animation/Animation/AnimationModifier.swift

Lines changed: 122 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
// OpenSwiftUICore
44
//
55
// Audited: 6.5.4
6-
// Status: Blocked by ArichevedView
6+
// Status: Complete
77
// ID: 530459AF10BEFD7ED901D8CE93C1E289 (SwiftUICore)
88

99
import OpenAttributeGraphShims
10+
import OpenCoreGraphicsShims
11+
12+
// MARK: - _AnimationModifier
1013

1114
@available(OpenSwiftUI_v1_0, *)
1215
@frozen
@@ -50,8 +53,11 @@ public struct _AnimationModifier<Value>: ViewModifier, PrimitiveViewModifier whe
5053
) -> _ViewOutputs {
5154
let archivedView = inputs.archivedView
5255
if archivedView.isArchived {
53-
// makeArchivedView
54-
_openSwiftUIUnimplementedFailure()
56+
return makeArchivedView(
57+
modifier: modifier,
58+
inputs: inputs,
59+
body: body
60+
)
5561
} else {
5662
var inputs = inputs
5763
_makeInputs(modifier: modifier, inputs: &inputs.base)
@@ -66,19 +72,76 @@ public struct _AnimationModifier<Value>: ViewModifier, PrimitiveViewModifier whe
6672
) -> _ViewListOutputs {
6773
let archivedView = inputs.archivedView
6874
if archivedView.isArchived {
69-
// makeArchivedViewList
70-
_openSwiftUIUnimplementedFailure()
75+
return makeArchivedViewList(
76+
modifier: modifier,
77+
inputs: inputs,
78+
body: body
79+
)
7180
} else {
7281
var inputs = inputs
7382
_makeInputs(modifier: modifier, inputs: &inputs.base)
7483
return body(_Graph(), inputs)
7584
}
7685
}
86+
87+
nonisolated private static func makeArchivedView(
88+
modifier: _GraphValue<Self>,
89+
inputs: _ViewInputs,
90+
body: @escaping (_Graph, _ViewInputs) -> _ViewOutputs
91+
) -> _ViewOutputs {
92+
var inputs = inputs
93+
func project<T>(type: T.Type) -> _ViewOutputs where T: Encodable & Equatable {
94+
let modifier = modifier.value.unsafeBitCast(to: _AnimationModifier<T>.self)
95+
inputs.displayListOptions.formUnion(.disableCanonicalization)
96+
let effect = Attribute(
97+
ArchivedAnimationModifier(modifier: modifier)
98+
)
99+
return ArchivedAnimationModifier.Effect
100+
._makeRendererEffect(
101+
effect: .init(effect),
102+
inputs: inputs,
103+
body: body
104+
)
105+
}
106+
guard let type = Value.self as? (any (Encodable & Equatable).Type) else {
107+
return body(_Graph(), inputs)
108+
}
109+
return project(type: type)
110+
}
111+
112+
nonisolated private static func makeArchivedViewList(
113+
modifier: _GraphValue<Self>,
114+
inputs: _ViewListInputs,
115+
body: @escaping (_Graph, _ViewListInputs) -> _ViewListOutputs
116+
) -> _ViewListOutputs {
117+
var inputs = inputs
118+
func project<T>(type: T.Type) where T: Encodable & Equatable {
119+
let modifier = modifier.value.unsafeBitCast(to: _AnimationModifier<T>.self)
120+
inputs.traits = Attribute(
121+
ArchivedAnimationTrait(
122+
modifier: modifier,
123+
traits: .init(inputs.traits)
124+
)
125+
)
126+
inputs.addTraitKey(ArchivedAnimationTraitKey.self)
127+
}
128+
if inputs.options.contains(.needsArchivedAnimationTraits),
129+
let type = Value.self as? (any (Encodable & Equatable).Type) {
130+
project(type: type)
131+
}
132+
return Self.makeMultiViewList(
133+
modifier: modifier,
134+
inputs: inputs,
135+
body: body
136+
)
137+
}
77138
}
78139

79140
@available(*, unavailable)
80141
extension _AnimationModifier: Sendable {}
81142

143+
// MARK: - _AnimationView
144+
82145
@available(OpenSwiftUI_v3_0, *)
83146
@frozen
84147
public struct _AnimationView<Content>: View, PrimitiveView where Content: Equatable, Content: View {
@@ -193,7 +256,60 @@ struct ValueTransactionSeed<V>: StatefulRule, AsyncAttribute where V: Equatable
193256
}
194257
}
195258

196-
// TODO: Archived stuff
259+
// MARK: - ArchivedAnimationModifier
260+
261+
private struct ArchivedAnimationModifier<Value>: Rule, AsyncAttribute where Value: Encodable, Value: Equatable {
262+
struct Effect: _RendererEffect {
263+
var animation: Animation?
264+
var value: StrongHash
265+
266+
func effectValue(size: CGSize) -> DisplayList.Effect {
267+
.interpolatorAnimation(.init(value: value, animation: animation))
268+
}
269+
}
270+
271+
@Attribute var modifier: _AnimationModifier<Value>
272+
273+
var value: Effect {
274+
let value = (try? StrongHash(encodable: modifier.value)) ?? .random()
275+
return Effect(animation: modifier.animation, value: value)
276+
}
277+
}
278+
279+
// MARK: - ArchivedAnimationTraitKey
280+
281+
struct ArchivedAnimationTraitKey: _ViewTraitKey {
282+
var animation: Animation?
283+
var hash: StrongHash
284+
285+
static var defaultValue: ArchivedAnimationTraitKey? {
286+
nil
287+
}
288+
}
289+
290+
extension ViewTraitCollection {
291+
@inline(__always)
292+
var archivedAnimationTrait: ArchivedAnimationTraitKey? {
293+
get { self[ArchivedAnimationTraitKey.self] }
294+
set { self[ArchivedAnimationTraitKey.self] = newValue }
295+
}
296+
}
297+
298+
// MARK: - ArchivedAnimationTrait
299+
300+
private struct ArchivedAnimationTrait<Value>: Rule, AsyncAttribute where Value: Encodable, Value: Equatable {
301+
@Attribute var modifier: _AnimationModifier<Value>
302+
@OptionalAttribute var traits: ViewTraitCollection?
303+
304+
var value: ViewTraitCollection {
305+
let value = (try? StrongHash(encodable: modifier.value)) ?? .random()
306+
var traits = traits ?? .init()
307+
traits.archivedAnimationTrait = .init(animation: modifier.animation, hash: value)
308+
return traits
309+
}
310+
}
311+
312+
// MARK: - ChildTransaction
197313

198314
private struct ChildTransaction: Rule, AsyncAttribute {
199315
@Attribute var valueTransactionSeed: UInt32

0 commit comments

Comments
 (0)