Skip to content

Commit

Permalink
Fix issue where AnimationKeypath in SolidLayer could be incorrect (#2278
Browse files Browse the repository at this point in the history
)
  • Loading branch information
calda authored Jan 8, 2024
1 parent c3d493b commit 9dc7d74
Show file tree
Hide file tree
Showing 36 changed files with 9,626 additions and 44 deletions.
3 changes: 3 additions & 0 deletions Sources/Private/CoreAnimation/Layers/SolidLayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ final class SolidLayer: BaseCompositionLayer {
override func setupAnimations(context: LayerAnimationContext) throws {
try super.setupAnimations(context: context)

var context = context
context = context.addingKeypathComponent(solidLayer.name)

// Even though the Lottie json schema provides a fixed `solidLayer.colorHex` value,
// we still need to create a set of keyframes and go through the standard `CAAnimation`
// codepath so that this value can be customized using the custom `ValueProvider`s API.
Expand Down
78 changes: 49 additions & 29 deletions Tests/AnimationKeypathTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,30 @@ final class AnimationKeypathTests: XCTestCase {

// MARK: Internal

/// All of the sample animations with custom value providers defined in `SnapshotConfiguration.swift`
/// should also participate in more in-depth tests for `AnimationKeypath` generation.
var animationKeypathTestAnimations: [String] {
Samples.sampleAnimationNames.filter { sampleAnimationName in
!SnapshotConfiguration.forSample(named: sampleAnimationName).customValueProviders.isEmpty
}
}

func testMainThreadEngineKeypathLogging() async {
for animationKeypathTestAnimation in animationKeypathTestAnimations {
await snapshotHierarchyKeypaths(
animationName: animationKeypathTestAnimation,
configuration: LottieConfiguration(renderingEngine: .mainThread))
}
}

func testCoreAnimationEngineKeypathLogging() async {
for animationKeypathTestAnimation in animationKeypathTestAnimations {
await snapshotHierarchyKeypaths(
animationName: animationKeypathTestAnimation,
configuration: LottieConfiguration(renderingEngine: .coreAnimation))
}
}

func testKeypathMatches() {
let keypath = AnimationKeypath(keypath: "Layer.Shape Group.Stroke 1.Color")

Expand Down Expand Up @@ -61,41 +85,37 @@ final class AnimationKeypathTests: XCTestCase {
XCTAssertNotNil(animationView.animationLayer?.layer(for: "Success.*.Fish1Tail 7"))
}

func testMainThreadEngineKeypathLogging() async {
await snapshotHierarchyKeypaths(
animationName: "Switch",
configuration: LottieConfiguration(renderingEngine: .mainThread))
}

func testCoreAnimationEngineKeypathLogging() async {
await snapshotHierarchyKeypaths(
animationName: "Switch",
configuration: LottieConfiguration(renderingEngine: .coreAnimation))

await snapshotHierarchyKeypaths(
animationName: "Issues/issue_1664",
configuration: LottieConfiguration(renderingEngine: .coreAnimation))
}

/// The Core Animation engine supports a subset of the keypaths supported by the Main Thread engine.
/// All keypaths that are supported in the Core Animation engine should also be supported by the Main Thread engine.
func testCoreAnimationEngineKeypathCompatibility() async {
let mainThreadKeypaths =
Set(await hierarchyKeypaths(animationName: "Switch", configuration: .init(renderingEngine: .mainThread)))
let coreAnimationKeypaths = await hierarchyKeypaths(
animationName: "Switch",
configuration: .init(renderingEngine: .coreAnimation))

for coreAnimationKeypath in coreAnimationKeypaths {
XCTAssert(
mainThreadKeypaths.contains(coreAnimationKeypath),
"""
\(coreAnimationKeypath) from Core Animation rendering engine \
is not supported in Main Thread rendering engine
""")
for animationName in animationKeypathTestAnimations {
let mainThreadKeypaths = Set(await hierarchyKeypaths(
animationName: animationName,
configuration: .init(renderingEngine: .mainThread)))

let coreAnimationKeypaths = await hierarchyKeypaths(
animationName: animationName,
configuration: .init(renderingEngine: .coreAnimation))

for coreAnimationKeypath in coreAnimationKeypaths {
XCTAssert(
mainThreadKeypaths.contains(coreAnimationKeypath),
"""
[\(animationName)] "\(coreAnimationKeypath)" from Core Animation rendering engine \
is not supported in Main Thread rendering engine
""")
}
}
}

override func setUp() {
LottieLogger.shared = .printToConsole
}

override func tearDown() {
LottieLogger.shared = LottieLogger()
}

// MARK: Private

private func snapshotHierarchyKeypaths(
Expand Down
1 change: 1 addition & 0 deletions Tests/Samples/Issues/issue_2262.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":"5.7.4","fr":60,"ip":0,"op":60,"w":70,"h":70,"nm":"close_icon","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"AccentContrast","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":42,"s":[100]},{"t":45,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[35,35,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":35,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[6.438,-6.469],[-0.031,0.062]],"c":false}]},{"t":45,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[15.062,-14.906],[14.367,-14.242]],"c":false}]}],"ix":2},"nm":"lot","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":35,"op":51,"st":-1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"AccentContrast","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":42,"s":[100]},{"t":45,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[35,35,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":35,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0.031,0.031],[-6.562,6.812]],"c":false}]},{"t":45,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-14.404,14.533],[-14.845,15.03]],"c":false}]}],"ix":2},"nm":"lot","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":35,"op":51,"st":-1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"AccentContrast","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":42,"s":[100]},{"t":45,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[35,35,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":35,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-6.438,-6.51],[0.125,0.135]],"c":false}]},{"t":45,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-15.062,-14.947],[-14.579,-14.7]],"c":false}]}],"ix":2},"nm":"lot","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":35,"op":51,"st":-1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"AccentContrast","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":42,"s":[100]},{"t":45,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[35,35,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":35,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0.125,-0.01],[6.312,6.322]],"c":false}]},{"t":45,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[14.661,14.517],[15.062,15.072]],"c":false}]}],"ix":2},"nm":"lot","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":35,"op":51,"st":-1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"AccentContrast","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[35,35,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0.078,-0.109],[-0.125,0.062]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":9,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[9.344,-9.375],[-9.312,9.281]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":15,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[8.719,-8.75],[-8.688,8.656]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":30,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[8.719,-8.75],[-8.688,8.656]],"c":false}]},{"t":35,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[6.438,-6.469],[-6.406,6.375]],"c":false}]}],"ix":2},"nm":"lot","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":35,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"AccentContrast","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[35,35,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.031,-0.094],[0.047,0.047]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":9,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-9.413,-9.5],[9.288,9.312]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":15,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-8.788,-8.875],[8.663,8.688]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":30,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-8.788,-8.875],[8.663,8.688]],"c":false}]},{"t":35,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-6.438,-6.51],[6.312,6.322]],"c":false}]}],"ix":2},"nm":"lot","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":35,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":1,"nm":"Accent","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":53,"s":[100]},{"t":60,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[35,35,0],"ix":2,"l":2},"a":{"a":0,"k":[25,25,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.505,0.505,0.667],"y":[1.01,1.01,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":38,"s":[100,100,100]},{"i":{"x":[0.336,0.336,0.667],"y":[1,1,1]},"o":{"x":[0.535,0.535,0.333],"y":[0.003,0.003,0]},"t":47,"s":[120,120,100]},{"t":60,"s":[10,10,100]}],"ix":6,"l":2}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"a","pt":{"a":0,"k":{"i":[[13.807,0],[0,-13.807],[-13.807,0],[0,13.807]],"o":[[-13.807,0],[0,13.807],[13.807,0],[0,-13.807]],"v":[[25,0],[0,25],[25,50],[50,25]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"sw":50,"sh":50,"sc":"#ee1d4c","ip":0,"op":60,"st":0,"bm":0}],"markers":[]}
34 changes: 19 additions & 15 deletions Tests/SnapshotConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,40 +76,40 @@ extension SnapshotConfiguration {

/// Test cases for the `AnimationKeypath` / `AnyValueProvider` system
"Nonanimating/keypathTest": .customValueProviders([
AnimationKeypath(keypath: "**.Stroke 1.Color"): ColorValueProvider(.black),
AnimationKeypath(keypath: "**.Fill 1.Color"): ColorValueProvider(.red),
"**.Stroke 1.Color": ColorValueProvider(.black),
"**.Fill 1.Color": ColorValueProvider(.red),
]),

"Switch": .customValueProviders([
AnimationKeypath(keypath: "Checkmark Outlines.Group 1.Stroke 1.Color"): ColorValueProvider(.black),
AnimationKeypath(keypath: "Checkmark Outlines 2.Group 1.Stroke 1.Color"): ColorValueProvider(.black),
AnimationKeypath(keypath: "X Outlines.Group 1.Stroke 1.Color"): ColorValueProvider(.black),
AnimationKeypath(keypath: "Switch Outline Outlines.Fill 1.Color"): ColorValueProvider([
"Checkmark Outlines.Group 1.Stroke 1.Color": ColorValueProvider(.black),
"Checkmark Outlines 2.Group 1.Stroke 1.Color": ColorValueProvider(.black),
"X Outlines.Group 1.Stroke 1.Color": ColorValueProvider(.black),
"Switch Outline Outlines.Fill 1.Color": ColorValueProvider([
Keyframe(value: LottieColor.black, time: 0),
Keyframe(value: LottieColor(r: 0.76, g: 0.76, b: 0.76, a: 1), time: 75),
Keyframe(value: LottieColor.black, time: 150),
]),
]),

"Issues/issue_1837_opacity": .customValueProviders([
AnimationKeypath(keypath: "Dark Gray Solid 1.Transform.Opacity"): FloatValueProvider(10),
"Dark Gray Solid 1.Transform.Opacity": FloatValueProvider(10),
]),

"Issues/issue_1837_scale_rotation": .customValueProviders([
AnimationKeypath(keypath: "H2.Transform.Scale"): PointValueProvider(CGPoint(x: 200, y: 150)),
AnimationKeypath(keypath: "H2.Transform.Rotation"): FloatValueProvider(90),
"H2.Transform.Scale": PointValueProvider(CGPoint(x: 200, y: 150)),
"H2.Transform.Rotation": FloatValueProvider(90),
]),

"Issues/issue_2042": .customValueProviders([
AnimationKeypath(keypath: "MASTER.Transform.Position"): PointValueProvider(CGPoint(x: 214, y: 120)),
"MASTER.Transform.Position": PointValueProvider(CGPoint(x: 214, y: 120)),
]),

"Issues/issue_1664": .customValueProviders([
AnimationKeypath(keypath: "**.base_color.**.Color"): ColorValueProvider(.black),
"**.base_color.**.Color": ColorValueProvider(.black),
]).precision(0.95),

"Issues/issue_1854": .customValueProviders([
AnimationKeypath(keypath: "**.Colors"): GradientValueProvider(
"**.Colors": GradientValueProvider(
[
LottieColor(r: 0, g: 0, b: 0, a: 0),
LottieColor(r: 1, g: 1, b: 1, a: 0.5),
Expand All @@ -119,15 +119,19 @@ extension SnapshotConfiguration {
]),

"Issues/issue_1847": .customValueProviders([
AnimationKeypath(keypath: "**.Stroke 1.**.Color"): ColorValueProvider(.red),
"**.Stroke 1.**.Color": ColorValueProvider(.red),
]),

"Issues/issue_2150": .customValueProviders([
AnimationKeypath(keypath: "**.Color"): ColorValueProvider(.red),
"**.Color": ColorValueProvider(.red),
]),

"Issues/issue_2094": .customValueProviders([
AnimationKeypath(keypath: "**.Stroke Width"): FloatValueProvider(2),
"**.Stroke Width": FloatValueProvider(2),
]),

"Issues/issue_2262": .customValueProviders([
"**.Accent.**.Color": ColorValueProvider(.black),
]),

// Test cases for `AnimatedImageProvider`
Expand Down
Loading

0 comments on commit 9dc7d74

Please sign in to comment.