Skip to content

Commit c57e109

Browse files
authored
Update Transaction implementation (#295)
* Update Transaction implementation * Update TransactionModifier implementation * Add documentation for TransactionModifier * Add TransactionAnimation and move folder * Fix SwiftPM build issue for release configuration error: function type mismatch, declared as '@convention(c) (Optional<UnsafeMutableRawPointer>) -> ()' but used as '@convention(thin) (@owned Optional<AnyObject>) -> ()
1 parent 265d0a5 commit c57e109

20 files changed

+548
-197
lines changed

Package.resolved

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"location" : "https://github.com/OpenSwiftUIProject/DarwinPrivateFrameworks.git",
88
"state" : {
99
"branch" : "main",
10-
"revision" : "e431e3fd08c3d960639c0c95c998f17d0b0f48f3"
10+
"revision" : "2ba5179547b9cefddfd304bbda6d0d0704946fe3"
1111
}
1212
},
1313
{
@@ -25,7 +25,7 @@
2525
"location" : "https://github.com/OpenSwiftUIProject/OpenGraph",
2626
"state" : {
2727
"branch" : "main",
28-
"revision" : "5d2296f685b461c53432be78373a5c9a4f80fff3"
28+
"revision" : "732ce4507120fbee7bc43ec0c8407f4c3d431811"
2929
}
3030
},
3131
{

Sources/OpenSwiftUICore/Data/State/StoredLocation.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,7 @@ package class StoredLocationBase<Value>: AnyLocation<Value>, Location, @unchecke
9999
guard shouldCommit else {
100100
return
101101
}
102-
var newTransaction = transaction
103-
newTransaction.override(.current)
102+
var newTransaction = transaction.current
104103
onMainThread { [weak self] in
105104
guard let self else {
106105
return

Sources/OpenSwiftUICore/Data/Transaction/Transaction+Animation.swift

Lines changed: 0 additions & 42 deletions
This file was deleted.

Sources/OpenSwiftUICore/OpenGraph/Attribute/AsyncAttribute.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,21 @@ extension AsyncAttribute {
1515

1616
extension Attribute {
1717
package func syncMainIfReferences<V>(do body: (Value) -> V) -> V {
18-
preconditionFailure("TODO")
18+
let (value, flags) = valueAndFlags(options: [._2])
19+
if flags.contains(.requiresMainThread) {
20+
var result: V?
21+
Update.syncMain {
22+
result = body(value)
23+
}
24+
return result!
25+
} else {
26+
return body(value)
27+
}
1928
}
2029
}
30+
31+
// FIXME: Add OGChangedValueFlagsRequiresMainThread in OpenGraph
32+
33+
extension OGChangedValueFlags {
34+
static let requiresMainThread = Self(rawValue: 2)
35+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
//
2+
// TransactionAnimation.swift
3+
// OpenSwiftUICore
4+
//
5+
// Audited for iOS 18.0
6+
// Status: Complete
7+
// ID: 39EC6D46662E6D7A6963F5C611934B0A (SwiftUI)
8+
// ID: D98E9A1069CEEADA58829ED440E36F30 (SwiftUICore)
9+
10+
extension Transaction {
11+
/// Creates a transaction and assigns its animation property.
12+
///
13+
/// - Parameter animation: The animation to perform when the current state
14+
/// changes.
15+
public init(animation: Animation?) {
16+
self.init()
17+
self.animation = animation
18+
}
19+
20+
/// The animation, if any, associated with the current state change.
21+
public var animation: Animation? {
22+
get { self[AnimationKey.self] }
23+
set { self[AnimationKey.self] = newValue }
24+
}
25+
26+
package var effectiveAnimation: Animation? {
27+
animation ?? (tracksVelocity ? .velocityTracking : nil)
28+
}
29+
30+
package var _animationFrameInterval: Double? {
31+
get { self[AnimationFrameIntervalKey.self] }
32+
set { self[AnimationFrameIntervalKey.self] = newValue }
33+
}
34+
35+
package var _animationReason: UInt32? {
36+
get { self[AnimationReasonKey.self] }
37+
set { self[AnimationReasonKey.self] = newValue }
38+
}
39+
40+
package var isAnimated: Bool {
41+
guard let animation,
42+
!disablesAnimations else {
43+
return false
44+
}
45+
return true
46+
}
47+
48+
/// A Boolean value that indicates whether views should disable animations.
49+
///
50+
/// This value is `true` during the initial phase of a two-part transition
51+
/// update, to prevent ``View/animation(_:)`` from inserting new animations
52+
/// into the transaction.
53+
public var disablesAnimations: Bool {
54+
get { self[DisablesAnimationsKey.self] }
55+
set { self[DisablesAnimationsKey.self] = newValue }
56+
}
57+
58+
package var disablesContentTransitions: Bool {
59+
get { self[DisablesContentTransactionKey.self] }
60+
set { self[DisablesContentTransactionKey.self] = newValue }
61+
}
62+
63+
package mutating func disableAnimations() {
64+
animation = nil
65+
disablesAnimations = true
66+
}
67+
68+
package var animationIgnoringTransitionPhase: Animation? {
69+
guard disablesAnimations else {
70+
return animation
71+
}
72+
var result: Animation?
73+
forEach(keyType: AnimationKey.self) { animation, stop in
74+
guard let animation else {
75+
return
76+
}
77+
result = animation
78+
stop = true
79+
}
80+
return result
81+
}
82+
}
83+
84+
private struct AnimationKey: TransactionKey {
85+
static var defaultValue: Animation? { nil }
86+
}
87+
88+
private struct DisablesAnimationsKey: TransactionKey {
89+
static var defaultValue: Bool { false }
90+
}
91+
92+
private struct AnimationFrameIntervalKey: TransactionKey {
93+
static var defaultValue: Double? { nil }
94+
}
95+
96+
private struct AnimationReasonKey: TransactionKey {
97+
static var defaultValue: UInt32? { nil }
98+
}
99+
100+
private struct DisablesContentTransactionKey: TransactionKey {
101+
static var defaultValue: Bool { false }
102+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//
2+
// VelocityTrackingAnimation.swift
3+
// OpenSwiftUICore
4+
//
5+
// Audited for iOS 18.0
6+
// Status: WIP
7+
// ID: FD9125BC1E04E33D1D7BE4A31225AA98 (SwiftUICore)
8+
9+
// MARK: - TracksVelocityKey
10+
11+
private struct TracksVelocityKey: TransactionKey {
12+
static var defaultValue: Bool { false }
13+
}
14+
15+
extension Transaction {
16+
/// Whether this transaction will track the velocity of any animatable
17+
/// properties that change.
18+
///
19+
/// This property can be enabled in an interactive context to track velocity
20+
/// during a user interaction so that when the interaction ends, an
21+
/// animation can use the accumulated velocities to create animations that
22+
/// preserve them. This tracking is mutually exclusive with an animation
23+
/// being used during a view change, since if there is an animation, it is
24+
/// responsible for managing its own velocity.
25+
///
26+
/// Gesture onChanged and updating callbacks automatically set this property
27+
/// to true.
28+
///
29+
/// This example shows an interaction which applies changes, tracking
30+
/// velocity until the final change, which applies an animation (which will
31+
/// start with the velocity that was tracked during the previous changes).
32+
/// These changes could come from a server or from an interactive control
33+
/// like a slider.
34+
///
35+
/// func receiveChange(change: ChangeInfo) {
36+
/// var transaction = Transaction()
37+
/// if change.isFinal {
38+
/// transaction.animation = .spring
39+
/// } else {
40+
/// transaction.tracksVelocity = true
41+
/// }
42+
/// withTransaction(transaction) {
43+
/// state.applyChange(change)
44+
/// }
45+
/// }
46+
public var tracksVelocity: Bool {
47+
get { self[TracksVelocityKey.self] }
48+
set { self[TracksVelocityKey.self] = newValue }
49+
}
50+
}
51+
52+
extension Animation {
53+
// FIXME: VelocityTrackingAnimation
54+
static let velocityTracking: Animation = Animation()
55+
}

0 commit comments

Comments
 (0)