lottie-ios 4.4.3 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/.github/workflows/main.yml +6 -34
  2. package/Lottie.xcodeproj/project.pbxproj +28 -0
  3. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  4. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +19 -6
  5. package/Package.resolved +2 -2
  6. package/Package.swift +1 -1
  7. package/README.md +2 -2
  8. package/Rakefile +1 -1
  9. package/Sources/Private/CoreAnimation/Animations/CALayer+addAnimation.swift +2 -2
  10. package/Sources/Private/CoreAnimation/Animations/TransformAnimations.swift +6 -6
  11. package/Sources/Private/CoreAnimation/CoreAnimationLayer.swift +6 -6
  12. package/Sources/Private/CoreAnimation/Extensions/Keyframes+combined.swift +2 -2
  13. package/Sources/Private/CoreAnimation/Layers/AnimationLayer.swift +7 -7
  14. package/Sources/Private/CoreAnimation/Layers/ShapeItemLayer.swift +12 -12
  15. package/Sources/Private/CoreAnimation/Layers/ShapeLayer.swift +19 -19
  16. package/Sources/Private/CoreAnimation/ValueProviderStore.swift +4 -4
  17. package/Sources/Private/EmbeddedLibraries/EpoxyCore/SwiftUI/LayoutUtilities/SwiftUIMeasurementContainer.swift +13 -6
  18. package/Sources/Private/EmbeddedLibraries/LRUCache/LRUCache.swift +3 -3
  19. package/Sources/Private/EmbeddedLibraries/ZipFoundation/Archive+BackingConfiguration.swift +10 -6
  20. package/Sources/Private/EmbeddedLibraries/ZipFoundation/Archive+Helpers.swift +4 -0
  21. package/Sources/Private/EmbeddedLibraries/ZipFoundation/Archive+Progress.swift +2 -2
  22. package/Sources/Private/EmbeddedLibraries/ZipFoundation/Archive+Reading.swift +5 -0
  23. package/Sources/Private/EmbeddedLibraries/ZipFoundation/Archive+Writing.swift +2 -0
  24. package/Sources/Private/EmbeddedLibraries/ZipFoundation/Data+Compression.swift +1 -0
  25. package/Sources/Private/EmbeddedLibraries/ZipFoundation/Entry+ZIP64.swift +2 -2
  26. package/Sources/Private/EmbeddedLibraries/ZipFoundation/Entry.swift +1 -0
  27. package/Sources/Private/EmbeddedLibraries/ZipFoundation/FileManager+ZIP.swift +10 -9
  28. package/Sources/Private/MainThread/LayerContainers/CompLayers/CompositionLayer.swift +19 -0
  29. package/Sources/Private/MainThread/LayerContainers/CompLayers/MaskContainerLayer.swift +7 -7
  30. package/Sources/Private/MainThread/LayerContainers/CompLayers/PreCompositionLayer.swift +3 -0
  31. package/Sources/Private/MainThread/LayerContainers/CompLayers/TextCompositionLayer.swift +24 -14
  32. package/Sources/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift +11 -10
  33. package/Sources/Private/MainThread/LayerContainers/Utility/CompositionLayersInitializer.swift +2 -0
  34. package/Sources/Private/MainThread/LayerContainers/Utility/CoreTextRenderLayer.swift +102 -17
  35. package/Sources/Private/MainThread/LayerContainers/Utility/LayerTransformNode.swift +11 -11
  36. package/Sources/Private/MainThread/NodeRenderSystem/Extensions/ItemsExtension.swift +2 -0
  37. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/LayerEffectNodes/DropShadowNode.swift +102 -0
  38. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/LayerEffectNodes/LayerEffectNode.swift +24 -0
  39. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/FillRenderer.swift +4 -4
  40. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/StrokeRenderer.swift +16 -16
  41. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/PolygonNode.swift +4 -4
  42. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift +5 -5
  43. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/Text/TextAnimatorNode.swift +60 -1
  44. package/Sources/Private/Model/DotLottie/DotLottieAnimation.swift +2 -2
  45. package/Sources/Private/Model/Keyframes/KeyframeGroup.swift +9 -6
  46. package/Sources/Private/Model/LayerEffects/EffectValues/EffectValue.swift +4 -4
  47. package/Sources/Private/Model/LayerEffects/LayerEffect.swift +2 -2
  48. package/Sources/Private/Model/LayerStyles/LayerStyle.swift +2 -2
  49. package/Sources/Private/Model/Layers/LayerModel.swift +7 -7
  50. package/Sources/Private/Model/ShapeItems/ShapeItem.swift +15 -15
  51. package/Sources/Private/Model/Text/TextAnimator.swift +47 -1
  52. package/Sources/Private/Utility/Debugging/LayerDebugging.swift +6 -6
  53. package/Sources/Private/Utility/Extensions/AnimationKeypathExtension.swift +16 -16
  54. package/Sources/Private/Utility/Extensions/BlendMode+Filter.swift +16 -16
  55. package/Sources/Private/Utility/Extensions/CGColor+RGB.swift +18 -0
  56. package/Sources/Private/Utility/Extensions/CGFloatExtensions.swift +23 -23
  57. package/Sources/Private/Utility/Extensions/MathKit.swift +4 -11
  58. package/Sources/Private/Utility/Interpolatable/InterpolatableExtensions.swift +9 -3
  59. package/Sources/Private/Utility/LottieAnimationSource.swift +4 -4
  60. package/Sources/Private/Utility/Primitives/BezierPath.swift +16 -2
  61. package/Sources/Private/Utility/Primitives/BezierPathRoundExtension.swift +2 -2
  62. package/Sources/Private/Utility/Primitives/ColorExtension.swift +20 -20
  63. package/Sources/Private/Utility/Primitives/CompoundBezierPath.swift +9 -9
  64. package/Sources/Public/Animation/LottieAnimationLayer.swift +36 -31
  65. package/Sources/Public/Animation/LottieAnimationView.swift +15 -15
  66. package/Sources/Public/Animation/LottieAnimationViewInitializers.swift +4 -0
  67. package/Sources/Public/Animation/LottiePlaybackMode.swift +12 -12
  68. package/Sources/Public/Animation/LottieView.swift +34 -1
  69. package/Sources/Public/Configuration/ReducedMotionOption.swift +5 -5
  70. package/Sources/Public/Configuration/RenderingEngineOption.swift +4 -4
  71. package/Sources/Public/Controls/AnimatedSwitch.swift +2 -2
  72. package/Sources/Public/DotLottie/DotLottieFile.swift +2 -2
  73. package/Sources/Public/DynamicProperties/AnyValueProvider.swift +9 -9
  74. package/Sources/Public/DynamicProperties/ValueProviders/GradientValueProvider.swift +2 -2
  75. package/Sources/Public/Keyframes/Interpolatable.swift +2 -2
  76. package/Sources/Public/Primitives/LottieColor.swift +3 -3
  77. package/Sources/Public/TextProvider/AnimationTextProvider.swift +4 -4
  78. package/Sources/Public/iOS/Compatibility/CompatibleAnimationView.swift +13 -12
  79. package/Version.xcconfig +1 -1
  80. package/lottie-ios.podspec +2 -2
  81. package/package.json +1 -1
@@ -9,13 +9,12 @@ on:
9
9
  jobs:
10
10
  build-package-no-visionOS:
11
11
  name: "Build Package"
12
- runs-on: macos-13
12
+ runs-on: macos-14
13
13
  strategy:
14
14
  fail-fast: false
15
15
  matrix:
16
16
  xcode:
17
- - '14.1' # Swift 5.7
18
- - '14.3' # Swift 5.8
17
+ - '15.0.1' # Swift 5.9, but no visionOS support
19
18
  steps:
20
19
  - uses: actions/checkout@v2
21
20
  - uses: ./.github/actions/setup
@@ -88,7 +87,7 @@ jobs:
88
87
 
89
88
  build-xcframework-minimum-supported-version:
90
89
  name: "Build XCFramework"
91
- runs-on: macos-13
90
+ runs-on: macos-14
92
91
  strategy:
93
92
  matrix:
94
93
  xcode:
@@ -96,36 +95,9 @@ jobs:
96
95
  # The Xcode version we use for this job is that oldest Xcode version that
97
96
  # will be able to use these XCFrameworks and the lottie-spm package.
98
97
  # This should be the minimum Xcode version permitted by the App Store.
99
- # As of April 2023, this is Xcode 14.1: https://developer.apple.com/news/?id=jd9wcyov
100
- # - TODO: Once this minimum supported Xcode version is 15.0 or later,
101
- # we can use Xcode 15.2 here and remove the `build-xcframework-with-visionOS-support` job.
102
- # Testing in https://github.com/airbnb/lottie-spm/pull/12 shows that Xcode 15.0 can
103
- # use an XCFramework built by Xcode 15.2.
104
- - '14.1' # Swift 5.7.1
105
- steps:
106
- - uses: actions/checkout@v2
107
- - uses: apple-actions/import-codesign-certs@v2
108
- continue-on-error: true
109
- with:
110
- p12-file-base64: ${{ secrets.SIGNING_CERTIFICATE_BASE_64 }}
111
- p12-password: ${{ secrets.SIGNING_CERTIFICATE_PASSWORD }}
112
- - uses: ./.github/actions/setup
113
- with:
114
- xcode: ${{ matrix.xcode }}
115
- - name: Build XCFramework
116
- run: SKIP_VISION_OS=true bundle exec rake build:xcframework[Lottie-Xcode-${{ matrix.xcode }}]
117
- - name: Upload XCFramework
118
- uses: actions/upload-artifact@v2
119
- with:
120
- name: BuildProducts
121
- path: .build/archives
122
-
123
- build-xcframework-with-visionOS-support:
124
- name: "Build XCFramework"
125
- runs-on: macos-14
126
- strategy:
127
- matrix:
128
- xcode:
98
+ # As of April 2024, this is Xcode 15.0: https://developer.apple.com/news/?id=fxu2qp7b
99
+ # - However, testing in https://github.com/airbnb/lottie-spm/pull/12 shows that
100
+ # Xcode 15.0 can use an XCFramework built by Xcode 15.2.
129
101
  - '15.2' # Swift 5.9, first Xcode version with visionOS support.
130
102
  steps:
131
103
  - uses: actions/checkout@v2
@@ -1151,6 +1151,14 @@
1151
1151
  D453D8B228FF9EA900D3F49C /* DefaultAnimationCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D453D8B028FF9E3A00D3F49C /* DefaultAnimationCache.swift */; };
1152
1152
  D453D8B328FF9EAA00D3F49C /* DefaultAnimationCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D453D8B028FF9E3A00D3F49C /* DefaultAnimationCache.swift */; };
1153
1153
  D453D8B428FF9EAA00D3F49C /* DefaultAnimationCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D453D8B028FF9E3A00D3F49C /* DefaultAnimationCache.swift */; };
1154
+ E95C386F2C14B7FC00329910 /* DropShadowNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95C386E2C14B7FC00329910 /* DropShadowNode.swift */; };
1155
+ E95C38712C14D14300329910 /* LayerEffectNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95C38702C14D14300329910 /* LayerEffectNode.swift */; };
1156
+ E95C38722C15559500329910 /* DropShadowNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95C386E2C14B7FC00329910 /* DropShadowNode.swift */; };
1157
+ E95C38732C15559600329910 /* DropShadowNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95C386E2C14B7FC00329910 /* DropShadowNode.swift */; };
1158
+ E95C38742C15559700329910 /* DropShadowNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95C386E2C14B7FC00329910 /* DropShadowNode.swift */; };
1159
+ E95C38752C15559D00329910 /* LayerEffectNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95C38702C14D14300329910 /* LayerEffectNode.swift */; };
1160
+ E95C38762C15559E00329910 /* LayerEffectNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95C38702C14D14300329910 /* LayerEffectNode.swift */; };
1161
+ E95C38772C15559F00329910 /* LayerEffectNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E95C38702C14D14300329910 /* LayerEffectNode.swift */; };
1154
1162
  /* End PBXBuildFile section */
1155
1163
 
1156
1164
  /* Begin PBXContainerItemProxy section */
@@ -1476,6 +1484,8 @@
1476
1484
  D453D8AA28FE6EE300D3F49C /* LottieAnimationCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LottieAnimationCache.swift; sourceTree = "<group>"; };
1477
1485
  D453D8AE28FF9BC600D3F49C /* AnimationCacheProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimationCacheProviderTests.swift; sourceTree = "<group>"; };
1478
1486
  D453D8B028FF9E3A00D3F49C /* DefaultAnimationCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultAnimationCache.swift; sourceTree = "<group>"; };
1487
+ E95C386E2C14B7FC00329910 /* DropShadowNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropShadowNode.swift; sourceTree = "<group>"; };
1488
+ E95C38702C14D14300329910 /* LayerEffectNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayerEffectNode.swift; sourceTree = "<group>"; };
1479
1489
  /* End PBXFileReference section */
1480
1490
 
1481
1491
  /* Begin PBXFrameworksBuildPhase section */
@@ -1959,6 +1969,7 @@
1959
1969
  2E9C95662822F43000677516 /* Nodes */ = {
1960
1970
  isa = PBXGroup;
1961
1971
  children = (
1972
+ E95C386D2C14B7DC00329910 /* LayerEffectNodes */,
1962
1973
  2E9C95672822F43000677516 /* ModifierNodes */,
1963
1974
  2E9C95692822F43000677516 /* RenderContainers */,
1964
1975
  2E9C956B2822F43000677516 /* OutputNodes */,
@@ -2446,6 +2457,15 @@
2446
2457
  path = DotLottie;
2447
2458
  sourceTree = "<group>";
2448
2459
  };
2460
+ E95C386D2C14B7DC00329910 /* LayerEffectNodes */ = {
2461
+ isa = PBXGroup;
2462
+ children = (
2463
+ E95C386E2C14B7FC00329910 /* DropShadowNode.swift */,
2464
+ E95C38702C14D14300329910 /* LayerEffectNode.swift */,
2465
+ );
2466
+ path = LayerEffectNodes;
2467
+ sourceTree = "<group>";
2468
+ };
2449
2469
  /* End PBXGroup section */
2450
2470
 
2451
2471
  /* Begin PBXHeadersBuildPhase section */
@@ -2710,11 +2730,13 @@
2710
2730
  080DEF6F2A95709700BE2D96 /* RenderingEngineOption.swift in Sources */,
2711
2731
  080DEFB22A9570FE00BE2D96 /* ErasedContentProviding.swift in Sources */,
2712
2732
  080DF0772A95717D00BE2D96 /* CompoundBezierPath.swift in Sources */,
2733
+ E95C38742C15559700329910 /* DropShadowNode.swift in Sources */,
2713
2734
  080DEF8E2A9570D500BE2D96 /* LottieColor.swift in Sources */,
2714
2735
  080DF0162A95713800BE2D96 /* PathOutputNode.swift in Sources */,
2715
2736
  080DF00A2A95713000BE2D96 /* InvertedMatteLayer.swift in Sources */,
2716
2737
  080DEFCD2A95711400BE2D96 /* Archive.swift in Sources */,
2717
2738
  080DEF912A9570DD00BE2D96 /* LRUAnimationCache.swift in Sources */,
2739
+ E95C38772C15559F00329910 /* LayerEffectNode.swift in Sources */,
2718
2740
  080DF05D2A95716A00BE2D96 /* ImageAsset.swift in Sources */,
2719
2741
  080DF0722A95717D00BE2D96 /* UnitBezier.swift in Sources */,
2720
2742
  080DF05E2A95716D00BE2D96 /* EffectValue.swift in Sources */,
@@ -3005,6 +3027,7 @@
3005
3027
  2E9C96152822F43100677516 /* Transform.swift in Sources */,
3006
3028
  2E9C97472822F43100677516 /* CGFloatExtensions.swift in Sources */,
3007
3029
  2EAF5AC527A0798700E00531 /* UIColorExtension.swift in Sources */,
3030
+ E95C386F2C14B7FC00329910 /* DropShadowNode.swift in Sources */,
3008
3031
  2E9C967E2822F43100677516 /* GradientStrokeRenderer.swift in Sources */,
3009
3032
  08E207182A56014E002DCE17 /* SwiftUIView.swift in Sources */,
3010
3033
  2E9C96932822F43100677516 /* PolygonNode.swift in Sources */,
@@ -3186,6 +3209,7 @@
3186
3209
  2E9C97652822F43100677516 /* CurveVertex.swift in Sources */,
3187
3210
  0820D5C52A8BF60F007D705C /* EffectValue.swift in Sources */,
3188
3211
  08C002042A46150D00AB54BA /* FileManager+ZIP.swift in Sources */,
3212
+ E95C38712C14D14300329910 /* LayerEffectNode.swift in Sources */,
3189
3213
  08E2072A2A56014E002DCE17 /* DidSelectProviding.swift in Sources */,
3190
3214
  0820D5CD2A8BF6FF007D705C /* ColorEffectValue.swift in Sources */,
3191
3215
  2E9C96482822F43100677516 /* NullCompositionLayer.swift in Sources */,
@@ -3318,6 +3342,7 @@
3318
3342
  0887347028F0CBDE00458627 /* LottieAnimation.swift in Sources */,
3319
3343
  2E9C97422822F43100677516 /* TestHelpers.swift in Sources */,
3320
3344
  08EF21DD289C643B0097EA47 /* KeyframeInterpolator.swift in Sources */,
3345
+ E95C38722C15559500329910 /* DropShadowNode.swift in Sources */,
3321
3346
  2E9C96162822F43100677516 /* Transform.swift in Sources */,
3322
3347
  2E9C97482822F43100677516 /* CGFloatExtensions.swift in Sources */,
3323
3348
  0820D5942A8ACD67007D705C /* LottieButton.swift in Sources */,
@@ -3499,6 +3524,7 @@
3499
3524
  2E9C96492822F43100677516 /* NullCompositionLayer.swift in Sources */,
3500
3525
  2EAF5AFF27A0798700E00531 /* GradientValueProvider.swift in Sources */,
3501
3526
  2E9C96BE2822F43100677516 /* AnyValueContainer.swift in Sources */,
3527
+ E95C38752C15559D00329910 /* LayerEffectNode.swift in Sources */,
3502
3528
  08E2072B2A56014E002DCE17 /* DidSelectProviding.swift in Sources */,
3503
3529
  2E9C96612822F43100677516 /* LayerFontProvider.swift in Sources */,
3504
3530
  6C7698442A38A71200E9BEF4 /* DotLottieConfiguration.swift in Sources */,
@@ -3605,6 +3631,7 @@
3605
3631
  2E9C97492822F43100677516 /* CGFloatExtensions.swift in Sources */,
3606
3632
  2EAF5AC727A0798700E00531 /* UIColorExtension.swift in Sources */,
3607
3633
  2E9C96802822F43100677516 /* GradientStrokeRenderer.swift in Sources */,
3634
+ E95C38732C15559600329910 /* DropShadowNode.swift in Sources */,
3608
3635
  2E9C96952822F43100677516 /* PolygonNode.swift in Sources */,
3609
3636
  08E2071A2A56014E002DCE17 /* SwiftUIView.swift in Sources */,
3610
3637
  2E9C96E62822F43100677516 /* MaskCompositionLayer.swift in Sources */,
@@ -3786,6 +3813,7 @@
3786
3813
  2E9C97672822F43100677516 /* CurveVertex.swift in Sources */,
3787
3814
  0820D5C72A8BF60F007D705C /* EffectValue.swift in Sources */,
3788
3815
  2E9C964A2822F43100677516 /* NullCompositionLayer.swift in Sources */,
3816
+ E95C38762C15559E00329910 /* LayerEffectNode.swift in Sources */,
3789
3817
  08E2072C2A56014E002DCE17 /* DidSelectProviding.swift in Sources */,
3790
3818
  0820D5CF2A8BF6FF007D705C /* ColorEffectValue.swift in Sources */,
3791
3819
  08C002ED2A46196300AB54BA /* Archive+Helpers.swift in Sources */,
@@ -7,17 +7,30 @@
7
7
  <BreakpointProxy
8
8
  BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
9
9
  <BreakpointContent
10
- uuid = "82609F00-E052-4A66-A922-03120D26327C"
10
+ uuid = "9F6F6DCE-17A1-4400-B8C2-87FC3C2073DF"
11
11
  shouldBeEnabled = "No"
12
+ condition = "customShape.direction != nil"
12
13
  ignoreCount = "0"
13
14
  continueAfterRunningActions = "No"
14
- filePath = "Sources/Private/CoreAnimation/CoreAnimationLayer.swift"
15
+ filePath = "Sources/Private/CoreAnimation/Animations/ShapeAnimation.swift"
15
16
  startingColumnNumber = "9223372036854775807"
16
17
  endingColumnNumber = "9223372036854775807"
17
- startingLineNumber = "26"
18
- endingLineNumber = "26"
19
- landmarkName = "CoreAnimationLayer"
20
- landmarkType = "3">
18
+ startingLineNumber = "18"
19
+ endingLineNumber = "18"
20
+ landmarkName = "CAShapeLayer"
21
+ landmarkType = "21">
22
+ </BreakpointContent>
23
+ </BreakpointProxy>
24
+ <BreakpointProxy
25
+ BreakpointExtensionID = "Xcode.Breakpoint.ExceptionBreakpoint">
26
+ <BreakpointContent
27
+ uuid = "CC6852A0-E9B0-4870-9299-A62D4DE8C83A"
28
+ shouldBeEnabled = "Yes"
29
+ ignoreCount = "0"
30
+ continueAfterRunningActions = "No"
31
+ breakpointStackSelectionBehavior = "1"
32
+ scope = "1"
33
+ stopOnStyle = "0">
21
34
  </BreakpointContent>
22
35
  </BreakpointProxy>
23
36
  </Breakpoints>
package/Package.resolved CHANGED
@@ -5,8 +5,8 @@
5
5
  "kind" : "remoteSourceControl",
6
6
  "location" : "https://github.com/airbnb/swift",
7
7
  "state" : {
8
- "revision" : "bc6aa7c3e21b6ab951ce75afc0a6e6d16fd6caef",
9
- "version" : "1.0.6"
8
+ "revision" : "fa3ae574d0b9c93a1655424bd4381044274c5cb4",
9
+ "version" : "1.0.7"
10
10
  }
11
11
  },
12
12
  {
package/Package.swift CHANGED
@@ -1,4 +1,4 @@
1
- // swift-tools-version:5.7
1
+ // swift-tools-version:5.9
2
2
  import PackageDescription
3
3
 
4
4
  let package = Package(
package/README.md CHANGED
@@ -41,7 +41,7 @@ To install Lottie using [Swift Package Manager](https://github.com/apple/swift-p
41
41
  or you can add the following dependency to your `Package.swift`:
42
42
 
43
43
  ```swift
44
- .package(url: "https://github.com/airbnb/lottie-spm.git", from: "4.4.3")
44
+ .package(url: "https://github.com/airbnb/lottie-spm.git", from: "4.5.0")
45
45
  ```
46
46
 
47
47
  When using Swift Package Manager we recommend using the [lottie-spm](https://github.com/airbnb/lottie-spm) repo instead of the main lottie-ios repo. The main git repository for [lottie-ios](https://github.com/airbnb/lottie-ios) is somewhat large (300+ MB), and Swift Package Manager always downloads the full repository with all git history. The [lottie-spm](https://github.com/airbnb/lottie-spm) repo is much smaller (less than 500kb), so can be downloaded much more quickly.
@@ -77,7 +77,7 @@ In your application targets “General” tab under the “Linked Frameworks and
77
77
 
78
78
  ## Swift Version Support
79
79
 
80
- Lottie supports Swift / Xcode versions back to the minimum version that is permited by Apple for submissions to the App Store. You can see the most up-to-date information for which Swift versions Lottie supports on [Swift Package Index](https://swiftpackageindex.com/airbnb/lottie-ios):
80
+ Lottie supports Swift / Xcode versions back to the minimum version that is permitted by Apple for submissions to the App Store. You can see the most up-to-date information for which Swift versions Lottie supports on [Swift Package Index](https://swiftpackageindex.com/airbnb/lottie-ios):
81
81
 
82
82
  [![Swift Versions](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fairbnb%2Flottie-ios%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/airbnb/lottie-ios)
83
83
 
package/Rakefile CHANGED
@@ -249,7 +249,7 @@ def xcodebuild(command)
249
249
  end
250
250
 
251
251
  # Runs the given code block, unless `SKIP_VISION_OS=true`.
252
- # TODO: Remove this once CI only uses Xcode 15.2+.
252
+ # TODO: Remove this once Lottie only supports Xcode 15.2+.
253
253
  def ifVisionOSEnabled
254
254
  if ENV["SKIP_VISION_OS"] == "true"
255
255
  puts "Skipping visionOS build"
@@ -305,9 +305,9 @@ extension CALayer {
305
305
  // to segments based on the `CAAnimationCalculationMode`, so we can just
306
306
  // check the first keyframe.
307
307
  if keyframes[0].isHold {
308
- return .discrete
308
+ .discrete
309
309
  } else {
310
- return .linear
310
+ .linear
311
311
  }
312
312
  }
313
313
 
@@ -280,12 +280,12 @@ extension CALayer {
280
280
  anchor, position, positionX, positionY, scale, rotationX, rotationY, rotationZ, skew, skewAxis
281
281
  -> Hold<CATransform3D> in
282
282
 
283
- let transformPosition: CGPoint
284
- if transformModel._positionX != nil, transformModel._positionY != nil {
285
- transformPosition = CGPoint(x: positionX.cgFloatValue, y: positionY.cgFloatValue)
286
- } else {
287
- transformPosition = position.pointValue
288
- }
283
+ let transformPosition: CGPoint =
284
+ if transformModel._positionX != nil, transformModel._positionY != nil {
285
+ CGPoint(x: positionX.cgFloatValue, y: positionY.cgFloatValue)
286
+ } else {
287
+ position.pointValue
288
+ }
289
289
 
290
290
  let transform = CATransform3D.makeTransform(
291
291
  anchor: anchor.pointValue,
@@ -308,8 +308,8 @@ final class CoreAnimationLayer: BaseAnimationLayer {
308
308
  add(timedProgressAnimation, forKey: #keyPath(animationProgress))
309
309
  }
310
310
 
311
- // Removes the current `CAAnimation`s, and rebuilds new animations
312
- // using the same configuration as the previous animations.
311
+ /// Removes the current `CAAnimation`s, and rebuilds new animations
312
+ /// using the same configuration as the previous animations.
313
313
  private func rebuildCurrentAnimation() {
314
314
  guard
315
315
  // Don't replace any pending animations that are queued to begin
@@ -343,15 +343,15 @@ extension CoreAnimationLayer: RootAnimationLayer {
343
343
  var isAnimationPlaying: Bool? {
344
344
  switch pendingAnimationConfiguration?.playbackState {
345
345
  case .playing:
346
- return true
346
+ true
347
347
  case .paused:
348
- return false
348
+ false
349
349
  case nil:
350
350
  switch playbackState {
351
351
  case .playing:
352
- return animation(forKey: #keyPath(animationProgress)) != nil
352
+ animation(forKey: #keyPath(animationProgress)) != nil
353
353
  case nil, .paused:
354
- return false
354
+ false
355
355
  }
356
356
  }
357
357
  }
@@ -320,9 +320,9 @@ extension KeyframeGroup {
320
320
  /// The value to use for a combined set of keyframes, for the given index
321
321
  fileprivate func valueForCombinedKeyframes(at index: Int) -> T {
322
322
  if keyframes.count == 1 {
323
- return keyframes[0].value
323
+ keyframes[0].value
324
324
  } else {
325
- return keyframes[index].value
325
+ keyframes[index].value
326
326
  }
327
327
  }
328
328
  }
@@ -15,7 +15,7 @@ protocol AnimationLayer: CALayer {
15
15
 
16
16
  // MARK: - LayerAnimationContext
17
17
 
18
- // Context describing the timing parameters of the current animation
18
+ /// Context describing the timing parameters of the current animation
19
19
  struct LayerAnimationContext {
20
20
  /// The animation being played
21
21
  let animation: LottieAnimation
@@ -74,12 +74,12 @@ struct LayerAnimationContext {
74
74
  // Normal animation playback (like when looping) skips the last frame.
75
75
  // However when the animation is paused, we need to be able to render the final frame.
76
76
  // To allow this we have to extend the length of the animation by one frame.
77
- let animationEndFrame: AnimationFrameTime
78
- if timingConfiguration.speed == 0 {
79
- animationEndFrame = animation.endFrame + 1
80
- } else {
81
- animationEndFrame = animation.endFrame
82
- }
77
+ let animationEndFrame: AnimationFrameTime =
78
+ if timingConfiguration.speed == 0 {
79
+ animation.endFrame + 1
80
+ } else {
81
+ animation.endFrame
82
+ }
83
83
 
84
84
  return Double(animationEndFrame - animation.startFrame) / animation.framerate
85
85
  }
@@ -118,19 +118,19 @@ final class ShapeItemLayer: BaseAnimationLayer {
118
118
  // We have to build a different layer hierarchy depending on if
119
119
  // we're rendering a gradient (a `CAGradientLayer` masked by a `CAShapeLayer`)
120
120
  // or a solid shape (a simple `CAShapeLayer`).
121
- let fillLayerConfiguration: FillLayerConfiguration
122
- if let gradientFill = otherItems.first(GradientFill.self) {
123
- fillLayerConfiguration = setupGradientFillLayerHierarchy(for: gradientFill)
124
- } else {
125
- fillLayerConfiguration = setupSolidFillLayerHierarchy()
126
- }
121
+ let fillLayerConfiguration: FillLayerConfiguration =
122
+ if let gradientFill = otherItems.first(GradientFill.self) {
123
+ setupGradientFillLayerHierarchy(for: gradientFill)
124
+ } else {
125
+ setupSolidFillLayerHierarchy()
126
+ }
127
127
 
128
- let gradientStrokeConfiguration: GradientLayers?
129
- if let gradientStroke = otherItems.first(GradientStroke.self) {
130
- gradientStrokeConfiguration = setupGradientStrokeLayerHierarchy(for: gradientStroke)
131
- } else {
132
- gradientStrokeConfiguration = nil
133
- }
128
+ let gradientStrokeConfiguration: GradientLayers? =
129
+ if let gradientStroke = otherItems.first(GradientStroke.self) {
130
+ setupGradientStrokeLayerHierarchy(for: gradientStroke)
131
+ } else {
132
+ nil
133
+ }
134
134
 
135
135
  sublayerConfiguration = (fillLayerConfiguration, gradientStrokeConfiguration)
136
136
  }
@@ -308,11 +308,11 @@ extension ShapeItem {
308
308
  var drawsCGPath: Bool {
309
309
  switch type {
310
310
  case .ellipse, .rectangle, .shape, .star:
311
- return true
311
+ true
312
312
 
313
313
  case .fill, .gradientFill, .group, .gradientStroke, .merge,
314
314
  .repeater, .round, .stroke, .trim, .transform, .unknown:
315
- return false
315
+ false
316
316
  }
317
317
  }
318
318
 
@@ -320,11 +320,11 @@ extension ShapeItem {
320
320
  var isFill: Bool {
321
321
  switch type {
322
322
  case .fill, .gradientFill:
323
- return true
323
+ true
324
324
 
325
325
  case .ellipse, .rectangle, .shape, .star, .group, .gradientStroke,
326
326
  .merge, .repeater, .round, .stroke, .trim, .transform, .unknown:
327
- return false
327
+ false
328
328
  }
329
329
  }
330
330
 
@@ -332,18 +332,18 @@ extension ShapeItem {
332
332
  var isStroke: Bool {
333
333
  switch type {
334
334
  case .stroke, .gradientStroke:
335
- return true
335
+ true
336
336
 
337
337
  case .ellipse, .rectangle, .shape, .star, .group, .gradientFill,
338
338
  .merge, .repeater, .round, .fill, .trim, .transform, .unknown:
339
- return false
339
+ false
340
340
  }
341
341
  }
342
342
 
343
- // For any inherited shape items that are affected by scaling (e.g. strokes but not fills),
344
- // any `ShapeTransform` in the given child group isn't supposed to be applied to the item.
345
- // To cancel out the effect of the transform, we can apply an inverse transform to the
346
- // shape item.
343
+ /// For any inherited shape items that are affected by scaling (e.g. strokes but not fills),
344
+ /// any `ShapeTransform` in the given child group isn't supposed to be applied to the item.
345
+ /// To cancel out the effect of the transform, we can apply an inverse transform to the
346
+ /// shape item.
347
347
  func scaledCopyForChildGroup(_ childGroup: Group, context: LayerContext) throws -> ShapeItem {
348
348
  guard
349
349
  // Path-drawing items aren't inherited by child groups in this way
@@ -502,15 +502,15 @@ extension [ShapeItemLayer.Item] {
502
502
 
503
503
  // A `CAShapeLayer` can only draw a stroke on top of a fill -- if the fill is supposed to be
504
504
  // drawn on top of the stroke, then they have to be rendered as separate layers.
505
- let strokeDrawnOnTopOfFill: Bool
506
- if
507
- let strokeIndex = strokesAndFills.firstIndex(where: { $0.item.isStroke }),
508
- let fillIndex = strokesAndFills.firstIndex(where: { $0.item.isFill })
509
- {
510
- strokeDrawnOnTopOfFill = strokeIndex < fillIndex
511
- } else {
512
- strokeDrawnOnTopOfFill = false
513
- }
505
+ let strokeDrawnOnTopOfFill: Bool =
506
+ if
507
+ let strokeIndex = strokesAndFills.firstIndex(where: { $0.item.isStroke }),
508
+ let fillIndex = strokesAndFills.firstIndex(where: { $0.item.isFill })
509
+ {
510
+ strokeIndex < fillIndex
511
+ } else {
512
+ false
513
+ }
514
514
 
515
515
  // `Fill` and `Stroke` items have an `alpha` property that can be animated separately,
516
516
  // but each layer only has a single `opacity` property. We can only use a single `CAShapeLayer`
@@ -40,8 +40,8 @@ final class ValueProviderStore {
40
40
  valueProviders.append((keypath: keypath, valueProvider: valueProvider))
41
41
  }
42
42
 
43
- // Retrieves the custom value keyframes for the given property,
44
- // if an `AnyValueProvider` was registered for the given keypath.
43
+ /// Retrieves the custom value keyframes for the given property,
44
+ /// if an `AnyValueProvider` was registered for the given keypath.
45
45
  func customKeyframes<Value>(
46
46
  of customizableProperty: CustomizableProperty<Value>,
47
47
  for keypath: AnimationKeypath,
@@ -115,9 +115,9 @@ extension AnyValueProviderStorage {
115
115
  var isSupportedByCoreAnimationRenderingEngine: Bool {
116
116
  switch self {
117
117
  case .singleValue, .keyframes:
118
- return true
118
+ true
119
119
  case .closure:
120
- return false
120
+ false
121
121
  }
122
122
  }
123
123
  }
@@ -24,12 +24,12 @@ final class SwiftUIMeasurementContainer<Content: ViewType>: ViewType {
24
24
  // On iOS 15 and below, passing zero can result in a constraint failure the first time a view
25
25
  // is displayed, but the system gracefully recovers afterwards. On iOS 16, it's fine to pass
26
26
  // zero.
27
- let initialSize: CGSize
28
- if #available(iOS 16, tvOS 16, macOS 13, *) {
29
- initialSize = .zero
30
- } else {
31
- initialSize = .init(width: 375, height: 150)
32
- }
27
+ let initialSize: CGSize =
28
+ if #available(iOS 16, tvOS 16, macOS 13, *) {
29
+ .zero
30
+ } else {
31
+ .init(width: 375, height: 150)
32
+ }
33
33
  super.init(frame: .init(origin: .zero, size: initialSize))
34
34
 
35
35
  addSubview(content)
@@ -180,12 +180,16 @@ final class SwiftUIMeasurementContainer<Content: ViewType>: ViewType {
180
180
  resolved = .intrinsic(intrinsicSize)
181
181
  }
182
182
  }
183
+
183
184
  case .proposed:
184
185
  resolved = .proposed
186
+
185
187
  case .intrinsicHeightProposedWidth:
186
188
  resolved = .intrinsicHeightProposedWidth
189
+
187
190
  case .intrinsicWidthProposedHeight:
188
191
  resolved = .intrinsicWidthProposedHeight
192
+
189
193
  case .intrinsic:
190
194
  resolved = .intrinsic(content.systemLayoutFittingIntrinsicSize())
191
195
  }
@@ -223,12 +227,15 @@ final class SwiftUIMeasurementContainer<Content: ViewType>: ViewType {
223
227
  case .proposed:
224
228
  constraints[.trailing]?.priority = .required
225
229
  constraints[.bottom]?.priority = .required
230
+
226
231
  case .intrinsicHeightProposedWidth:
227
232
  constraints[.trailing]?.priority = .required
228
233
  constraints[.bottom]?.priority = .almostRequired
234
+
229
235
  case .intrinsicWidthProposedHeight:
230
236
  constraints[.trailing]?.priority = .almostRequired
231
237
  constraints[.bottom]?.priority = .required
238
+
232
239
  case .intrinsic:
233
240
  constraints[.trailing]?.priority = .almostRequired
234
241
  constraints[.bottom]?.priority = .almostRequired
@@ -216,7 +216,7 @@ extension LRUCache {
216
216
 
217
217
  // MARK: Private
218
218
 
219
- // Remove container from list (must be called inside lock)
219
+ /// Remove container from list (must be called inside lock)
220
220
  private func remove(_ container: Container) {
221
221
  if head === container {
222
222
  head = container.next
@@ -229,7 +229,7 @@ extension LRUCache {
229
229
  container.next = nil
230
230
  }
231
231
 
232
- // Append container to list (must be called inside lock)
232
+ /// Append container to list (must be called inside lock)
233
233
  private func append(_ container: Container) {
234
234
  assert(container.next == nil)
235
235
  if head == nil {
@@ -240,7 +240,7 @@ extension LRUCache {
240
240
  tail = container
241
241
  }
242
242
 
243
- // Remove expired values (must be called outside lock)
243
+ /// Remove expired values (must be called outside lock)
244
244
  private func clean() {
245
245
  lock.lock()
246
246
  defer { lock.unlock() }
@@ -62,6 +62,7 @@ extension Archive {
62
62
  file: archiveFile,
63
63
  endOfCentralDirectoryRecord: eocdRecord,
64
64
  zip64EndOfCentralDirectory: zip64EOCD)
65
+
65
66
  case .create:
66
67
  let endOfCentralDirectoryRecord = EndOfCentralDirectoryRecord(
67
68
  numberOfDisk: 0,
@@ -76,6 +77,7 @@ extension Archive {
76
77
  try endOfCentralDirectoryRecord.data.write(to: url, options: .withoutOverwriting)
77
78
  } catch { return nil }
78
79
  fallthrough
80
+
79
81
  case .update:
80
82
  let fileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: url.path)
81
83
  guard
@@ -96,12 +98,12 @@ extension Archive {
96
98
  static func makeBackingConfiguration(for data: Data, mode: AccessMode)
97
99
  -> BackingConfiguration?
98
100
  {
99
- let posixMode: String
100
- switch mode {
101
- case .read: posixMode = "rb"
102
- case .create: posixMode = "wb+"
103
- case .update: posixMode = "rb+"
104
- }
101
+ let posixMode =
102
+ switch mode {
103
+ case .read: "rb"
104
+ case .create: "wb+"
105
+ case .update: "rb+"
106
+ }
105
107
  let memoryFile = MemoryFile(data: data)
106
108
  guard let archiveFile = memoryFile.open(mode: posixMode) else { return nil }
107
109
 
@@ -116,6 +118,7 @@ extension Archive {
116
118
  endOfCentralDirectoryRecord: eocdRecord,
117
119
  zip64EndOfCentralDirectory: zip64EOCD,
118
120
  memoryFile: memoryFile)
121
+
119
122
  case .create:
120
123
  let endOfCentralDirectoryRecord = EndOfCentralDirectoryRecord(
121
124
  numberOfDisk: 0,
@@ -130,6 +133,7 @@ extension Archive {
130
133
  fwrite(buffer.baseAddress, buffer.count, 1, archiveFile) // Errors handled during read
131
134
  }
132
135
  fallthrough
136
+
133
137
  case .update:
134
138
  guard let (eocdRecord, zip64EOCD) = Archive.scanForEndOfCentralDirectoryRecord(in: archiveFile) else {
135
139
  return nil