lottie-ios 4.3.4 → 4.4.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 (182) hide show
  1. package/.github/workflows/main.yml +51 -58
  2. package/Lottie.xcodeproj/project.pbxproj +20 -0
  3. package/Lottie.xcodeproj/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +4 -17
  4. package/Lottie.xcworkspace/xcshareddata/swiftpm/Package.resolved +37 -40
  5. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  6. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +9 -680
  7. package/Package.resolved +20 -22
  8. package/Package.swift +3 -2
  9. package/README.md +21 -3
  10. package/Rakefile +52 -28
  11. package/Sources/PrivacyInfo.xcprivacy +23 -0
  12. package/Sources/Private/CoreAnimation/Animations/CAAnimation+TimingConfiguration.swift +1 -1
  13. package/Sources/Private/CoreAnimation/Animations/CALayer+addAnimation.swift +23 -13
  14. package/Sources/Private/CoreAnimation/Animations/CustomPathAnimation.swift +8 -2
  15. package/Sources/Private/CoreAnimation/Animations/EllipseAnimation.swift +7 -1
  16. package/Sources/Private/CoreAnimation/Animations/GradientAnimations.swift +15 -2
  17. package/Sources/Private/CoreAnimation/Animations/LayerProperty.swift +8 -1
  18. package/Sources/Private/CoreAnimation/Animations/RectangleAnimation.swift +8 -1
  19. package/Sources/Private/CoreAnimation/Animations/StarAnimation.swift +12 -1
  20. package/Sources/Private/CoreAnimation/Animations/StrokeAnimation.swift +0 -1
  21. package/Sources/Private/CoreAnimation/Animations/TransformAnimations.swift +19 -11
  22. package/Sources/Private/CoreAnimation/Animations/VisibilityAnimation.swift +45 -19
  23. package/Sources/Private/CoreAnimation/CoreAnimationLayer.swift +38 -3
  24. package/Sources/Private/CoreAnimation/Extensions/CALayer+fillBounds.swift +1 -1
  25. package/Sources/Private/CoreAnimation/Extensions/Keyframes+combined.swift +9 -2
  26. package/Sources/Private/CoreAnimation/Extensions/Keyframes+timeRemapping.swift +46 -0
  27. package/Sources/Private/CoreAnimation/Layers/AnimationLayer.swift +77 -13
  28. package/Sources/Private/CoreAnimation/Layers/BaseCompositionLayer.swift +1 -1
  29. package/Sources/Private/CoreAnimation/Layers/CALayer+setupLayerHierarchy.swift +2 -2
  30. package/Sources/Private/CoreAnimation/Layers/ImageLayer.swift +1 -1
  31. package/Sources/Private/CoreAnimation/Layers/LayerModel+makeAnimationLayer.swift +1 -7
  32. package/Sources/Private/CoreAnimation/Layers/PreCompLayer.swift +19 -53
  33. package/Sources/Private/CoreAnimation/Layers/ShapeItemLayer.swift +2 -2
  34. package/Sources/Private/CoreAnimation/Layers/ShapeLayer.swift +2 -4
  35. package/Sources/Private/CoreAnimation/Layers/SolidLayer.swift +5 -2
  36. package/Sources/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModelArrayBuilder.swift +1 -1
  37. package/Sources/Private/EmbeddedLibraries/EpoxyCore/Model/EpoxyModelProperty.swift +10 -10
  38. package/Sources/Private/EmbeddedLibraries/LRUCache/LRUCache.swift +3 -3
  39. package/Sources/Private/EmbeddedLibraries/README.md +2 -0
  40. package/Sources/Private/EmbeddedLibraries/ZipFoundation/Archive+Helpers.swift +2 -2
  41. package/Sources/Private/EmbeddedLibraries/ZipFoundation/Archive+MemoryFile.swift +7 -7
  42. package/Sources/Private/EmbeddedLibraries/ZipFoundation/Data+Compression.swift +2 -2
  43. package/Sources/Private/EmbeddedLibraries/ZipFoundation/FileManager+ZIP.swift +5 -5
  44. package/Sources/Private/MainThread/LayerContainers/CompLayers/CompositionLayer.swift +1 -2
  45. package/Sources/Private/MainThread/LayerContainers/CompLayers/ImageCompositionLayer.swift +1 -3
  46. package/Sources/Private/MainThread/LayerContainers/CompLayers/MaskContainerLayer.swift +1 -2
  47. package/Sources/Private/MainThread/LayerContainers/CompLayers/PreCompositionLayer.swift +2 -3
  48. package/Sources/Private/MainThread/LayerContainers/CompLayers/SolidCompositionLayer.swift +2 -3
  49. package/Sources/Private/MainThread/LayerContainers/CompLayers/TextCompositionLayer.swift +5 -12
  50. package/Sources/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift +0 -1
  51. package/Sources/Private/MainThread/LayerContainers/Utility/CachedImageProvider.swift +0 -2
  52. package/Sources/Private/MainThread/LayerContainers/Utility/CompositionLayersInitializer.swift +3 -3
  53. package/Sources/Private/MainThread/LayerContainers/Utility/CoreTextRenderLayer.swift +12 -12
  54. package/Sources/Private/MainThread/LayerContainers/Utility/InvertedMatteLayer.swift +1 -2
  55. package/Sources/Private/MainThread/LayerContainers/Utility/LayerFontProvider.swift +0 -2
  56. package/Sources/Private/MainThread/LayerContainers/Utility/LayerImageProvider.swift +1 -3
  57. package/Sources/Private/MainThread/LayerContainers/Utility/LayerTextProvider.swift +0 -2
  58. package/Sources/Private/MainThread/LayerContainers/Utility/LayerTransformNode.swift +0 -2
  59. package/Sources/Private/MainThread/NodeRenderSystem/Extensions/ItemsExtension.swift +1 -3
  60. package/Sources/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/KeypathSearchable.swift +0 -1
  61. package/Sources/Private/MainThread/NodeRenderSystem/NodeProperties/Protocols/NodePropertyMap.swift +0 -1
  62. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/GroupOutputNode.swift +1 -3
  63. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/PassThroughOutputNode.swift +1 -2
  64. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/PathOutputNode.swift +0 -1
  65. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/FillRenderer.swift +0 -2
  66. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientFillRenderer.swift +0 -1
  67. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/GradientStrokeRenderer.swift +0 -1
  68. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/LegacyGradientFillRenderer.swift +0 -1
  69. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/OutputNodes/Renderables/StrokeRenderer.swift +2 -3
  70. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderContainers/GroupNode.swift +1 -3
  71. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift +2 -2
  72. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/Text/TextAnimatorNode.swift +0 -2
  73. package/Sources/Private/MainThread/NodeRenderSystem/Protocols/AnimatorNode.swift +0 -1
  74. package/Sources/Private/MainThread/NodeRenderSystem/Protocols/PathNode.swift +0 -2
  75. package/Sources/Private/MainThread/NodeRenderSystem/Protocols/RenderNode.swift +0 -2
  76. package/Sources/Private/MainThread/NodeRenderSystem/RenderLayers/ShapeContainerLayer.swift +0 -1
  77. package/Sources/Private/MainThread/NodeRenderSystem/RenderLayers/ShapeRenderLayer.swift +0 -1
  78. package/Sources/Private/Model/Assets/Asset.swift +2 -3
  79. package/Sources/Private/Model/Assets/AssetLibrary.swift +11 -11
  80. package/Sources/Private/Model/Assets/ImageAsset.swift +20 -0
  81. package/Sources/Private/Model/Assets/PrecompAsset.swift +0 -2
  82. package/Sources/Private/Model/DictionaryInitializable.swift +18 -10
  83. package/Sources/Private/Model/DotLottie/DotLottieImageProvider.swift +9 -6
  84. package/Sources/Private/Model/DotLottie/DotLottieUtils.swift +1 -1
  85. package/Sources/Private/Model/Extensions/KeyedDecodingContainerExtensions.swift +0 -2
  86. package/Sources/Private/Model/Keyframes/KeyframeData.swift +1 -4
  87. package/Sources/Private/Model/Keyframes/KeyframeGroup.swift +1 -3
  88. package/Sources/Private/Model/LayerEffects/DropShadowEffect.swift +0 -2
  89. package/Sources/Private/Model/LayerEffects/EffectValues/ColorEffectValue.swift +0 -2
  90. package/Sources/Private/Model/LayerEffects/EffectValues/EffectValue.swift +2 -3
  91. package/Sources/Private/Model/LayerEffects/EffectValues/Vector1DEffectValue.swift +0 -2
  92. package/Sources/Private/Model/LayerEffects/LayerEffect.swift +2 -3
  93. package/Sources/Private/Model/LayerStyles/DropShadowStyle.swift +0 -2
  94. package/Sources/Private/Model/LayerStyles/LayerStyle.swift +2 -3
  95. package/Sources/Private/Model/Layers/ImageLayerModel.swift +0 -2
  96. package/Sources/Private/Model/Layers/LayerModel.swift +11 -5
  97. package/Sources/Private/Model/Layers/PreCompLayerModel.swift +0 -2
  98. package/Sources/Private/Model/Layers/ShapeLayerModel.swift +0 -2
  99. package/Sources/Private/Model/Layers/SolidLayerModel.swift +0 -2
  100. package/Sources/Private/Model/Layers/TextLayerModel.swift +0 -2
  101. package/Sources/Private/Model/Objects/DashPattern.swift +1 -3
  102. package/Sources/Private/Model/Objects/Marker.swift +0 -2
  103. package/Sources/Private/Model/Objects/Mask.swift +0 -2
  104. package/Sources/Private/Model/Objects/Transform.swift +46 -9
  105. package/Sources/Private/Model/ShapeItems/Ellipse.swift +0 -2
  106. package/Sources/Private/Model/ShapeItems/Fill.swift +0 -2
  107. package/Sources/Private/Model/ShapeItems/GradientFill.swift +1 -3
  108. package/Sources/Private/Model/ShapeItems/GradientStroke.swift +1 -3
  109. package/Sources/Private/Model/ShapeItems/Group.swift +0 -2
  110. package/Sources/Private/Model/ShapeItems/Merge.swift +1 -3
  111. package/Sources/Private/Model/ShapeItems/Rectangle.swift +0 -2
  112. package/Sources/Private/Model/ShapeItems/Repeater.swift +0 -2
  113. package/Sources/Private/Model/ShapeItems/RoundedCorners.swift +0 -2
  114. package/Sources/Private/Model/ShapeItems/Shape.swift +0 -2
  115. package/Sources/Private/Model/ShapeItems/ShapeItem.swift +2 -3
  116. package/Sources/Private/Model/ShapeItems/ShapeTransform.swift +0 -2
  117. package/Sources/Private/Model/ShapeItems/Star.swift +1 -3
  118. package/Sources/Private/Model/ShapeItems/Stroke.swift +0 -2
  119. package/Sources/Private/Model/ShapeItems/Trim.swift +1 -3
  120. package/Sources/Private/Model/Text/Font.swift +0 -2
  121. package/Sources/Private/Model/Text/Glyph.swift +0 -2
  122. package/Sources/Private/Model/Text/TextAnimator.swift +0 -2
  123. package/Sources/Private/Model/Text/TextDocument.swift +2 -4
  124. package/Sources/Private/Utility/Debugging/AnimatorNodeDebugging.swift +0 -2
  125. package/Sources/Private/Utility/Debugging/LayerDebugging.swift +4 -5
  126. package/Sources/Private/Utility/Extensions/AnimationKeypathExtension.swift +2 -3
  127. package/Sources/Private/Utility/Extensions/DataExtension.swift +0 -1
  128. package/Sources/Private/Utility/Extensions/StringExtensions.swift +5 -0
  129. package/Sources/Private/Utility/Helpers/AnimationContext.swift +2 -3
  130. package/Sources/Private/Utility/Helpers/AnyEquatable.swift +0 -2
  131. package/Sources/Private/Utility/LottieAnimationSource.swift +11 -1
  132. package/Sources/Private/Utility/Primitives/BezierPath.swift +2 -3
  133. package/Sources/Private/Utility/Primitives/CGPointExtension.swift +1 -1
  134. package/Sources/Private/Utility/Primitives/ColorExtension.swift +1 -2
  135. package/Sources/Private/Utility/Primitives/VectorsExtensions.swift +6 -6
  136. package/Sources/Public/Animation/LottieAnimation.swift +2 -2
  137. package/Sources/Public/Animation/LottieAnimationHelpers.swift +7 -5
  138. package/Sources/Public/Animation/LottieAnimationLayer.swift +29 -43
  139. package/Sources/Public/Animation/LottieAnimationView.swift +6 -7
  140. package/Sources/Public/Animation/LottieAnimationViewInitializers.swift +3 -3
  141. package/Sources/Public/Animation/LottiePlaybackMode.swift +53 -0
  142. package/Sources/Public/Animation/LottieView.swift +143 -48
  143. package/Sources/Public/AnimationCache/AnimationCacheProvider.swift +0 -2
  144. package/Sources/Public/AnimationCache/DefaultAnimationCache.swift +11 -1
  145. package/Sources/Public/AnimationCache/LRUAnimationCache.swift +0 -2
  146. package/Sources/Public/Controls/AnimatedButton.swift +4 -6
  147. package/Sources/Public/Controls/AnimatedControl.swift +1 -3
  148. package/Sources/Public/Controls/AnimatedSwitch.swift +1 -3
  149. package/Sources/Public/DotLottie/Cache/DotLottieCache.swift +9 -0
  150. package/Sources/Public/DotLottie/Cache/DotLottieCacheProvider.swift +1 -3
  151. package/Sources/Public/DotLottie/DotLottieConfiguration.swift +53 -5
  152. package/Sources/Public/DotLottie/DotLottieFile.swift +4 -3
  153. package/Sources/Public/DotLottie/DotLottieFileHelpers.swift +6 -6
  154. package/Sources/Public/DynamicProperties/AnimationKeypath.swift +0 -2
  155. package/Sources/Public/DynamicProperties/AnyValueProvider.swift +0 -1
  156. package/Sources/Public/DynamicProperties/ValueProviders/ColorValueProvider.swift +2 -2
  157. package/Sources/Public/DynamicProperties/ValueProviders/FloatValueProvider.swift +1 -1
  158. package/Sources/Public/DynamicProperties/ValueProviders/GradientValueProvider.swift +1 -1
  159. package/Sources/Public/DynamicProperties/ValueProviders/PointValueProvider.swift +1 -1
  160. package/Sources/Public/DynamicProperties/ValueProviders/SizeValueProvider.swift +1 -1
  161. package/Sources/Public/FontProvider/AnimationFontProvider.swift +0 -2
  162. package/Sources/Public/ImageProvider/AnimationImageProvider.swift +0 -2
  163. package/Sources/Public/Keyframes/Interpolatable.swift +26 -0
  164. package/Sources/Public/Primitives/LottieColor.swift +0 -2
  165. package/Sources/Public/Primitives/Vectors.swift +0 -2
  166. package/Sources/Public/TextProvider/AnimationTextProvider.swift +0 -2
  167. package/Sources/Public/iOS/AnimationSubview.swift +0 -1
  168. package/Sources/Public/iOS/BundleImageProvider.swift +3 -8
  169. package/Sources/Public/iOS/Compatibility/CompatibleAnimationView.swift +4 -8
  170. package/Sources/Public/iOS/UIColorExtension.swift +1 -2
  171. package/Sources/Public/macOS/BundleImageProvider.macOS.swift +3 -6
  172. package/lottie-ios.podspec +5 -2
  173. package/package.json +1 -1
  174. package/Lottie.xcodeproj/project.xcworkspace/xcuserdata/cal.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  175. package/Lottie.xcodeproj/project.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  176. package/Lottie.xcodeproj/xcuserdata/cal.xcuserdatad/xcschemes/xcschememanagement.plist +0 -37
  177. package/Lottie.xcworkspace/xcuserdata/cal.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  178. package/Lottie.xcworkspace/xcuserdata/cal.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +0 -6
  179. package/Lottie.xcworkspace/xcuserdata/cal.xcuserdatad/xcdebugger/Expressions.xcexplist +0 -153
  180. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/IDEFindNavigatorScopes.plist +0 -5
  181. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Expressions.xcexplist +0 -231
  182. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +0 -37
@@ -50,7 +50,7 @@ extension LottieAnimation {
50
50
 
51
51
  /// Check cache for animation
52
52
  if
53
- let animationCache = animationCache,
53
+ let animationCache,
54
54
  let animation = animationCache.animation(forKey: cacheKey)
55
55
  {
56
56
  /// If found, return the animation.
@@ -82,7 +82,7 @@ extension LottieAnimation {
82
82
  {
83
83
  /// Check cache for animation
84
84
  if
85
- let animationCache = animationCache,
85
+ let animationCache,
86
86
  let animation = animationCache.animation(forKey: filepath)
87
87
  {
88
88
  return animation
@@ -119,7 +119,7 @@ extension LottieAnimation {
119
119
 
120
120
  /// Check cache for animation
121
121
  if
122
- let animationCache = animationCache,
122
+ let animationCache,
123
123
  let animation = animationCache.animation(forKey: cacheKey)
124
124
  {
125
125
  /// If found, return the animation.
@@ -160,7 +160,7 @@ extension LottieAnimation {
160
160
  case .dictionaryBased:
161
161
  let json = try JSONSerialization.jsonObject(with: data)
162
162
  guard let dict = json as? [String: Any] else {
163
- throw InitializableError.invalidInput
163
+ throw InitializableError.invalidInput()
164
164
  }
165
165
  return try LottieAnimation(dictionary: dict)
166
166
  }
@@ -201,7 +201,7 @@ extension LottieAnimation {
201
201
  closure: @escaping LottieAnimation.DownloadClosure,
202
202
  animationCache: AnimationCacheProvider? = LottieAnimationCache.shared)
203
203
  {
204
- if let animationCache = animationCache, let animation = animationCache.animation(forKey: url.absoluteString) {
204
+ if let animationCache, let animation = animationCache.animation(forKey: url.absoluteString) {
205
205
  closure(animation)
206
206
  } else {
207
207
  let task = session.dataTask(with: url) { data, _, error in
@@ -316,4 +316,6 @@ extension LottieAnimation {
316
316
  /// This retroactive conformance is safe because Sendable is a marker protocol that doesn't
317
317
  /// include any runtime component. Multiple modules in the same package graph can provide this
318
318
  /// conformance without causing any conflicts.
319
+ ///
320
+ // swiftlint:disable:next no_unchecked_sendable
319
321
  extension Foundation.Bundle: @unchecked Sendable { }
@@ -3,7 +3,6 @@
3
3
  // Lottie
4
4
  //
5
5
 
6
- import Foundation
7
6
  import QuartzCore
8
7
 
9
8
  // MARK: - LottieAnimationLayer
@@ -32,7 +31,7 @@ public class LottieAnimationLayer: CALayer {
32
31
  self.logger = logger
33
32
  super.init()
34
33
  makeAnimationLayer(usingEngine: configuration.renderingEngine)
35
- if let animation = animation {
34
+ if let animation {
36
35
  frame = animation.bounds
37
36
  }
38
37
  }
@@ -58,7 +57,7 @@ public class LottieAnimationLayer: CALayer {
58
57
  loopMode = dotLottieAnimation?.configuration.loopMode ?? .playOnce
59
58
  animationSpeed = CGFloat(dotLottieAnimation?.configuration.speed ?? 1)
60
59
  makeAnimationLayer(usingEngine: configuration.renderingEngine)
61
- if let animation = animation {
60
+ if let animation {
62
61
  frame = animation.bounds
63
62
  }
64
63
  }
@@ -104,7 +103,7 @@ public class LottieAnimationLayer: CALayer {
104
103
  ///
105
104
  /// - Parameter completion: An optional completion closure to be called when the animation completes playing.
106
105
  open func play(completion: LottieCompletionBlock? = nil) {
107
- guard let animation = animation else { return }
106
+ guard let animation else { return }
108
107
 
109
108
  defer {
110
109
  currentPlaybackMode = .playing(.fromProgress(nil, toProgress: 1, loopMode: loopMode))
@@ -136,7 +135,7 @@ public class LottieAnimationLayer: CALayer {
136
135
  loopMode: LottieLoopMode? = nil,
137
136
  completion: LottieCompletionBlock? = nil)
138
137
  {
139
- guard let animation = animation else { return }
138
+ guard let animation else { return }
140
139
 
141
140
  defer {
142
141
  currentPlaybackMode = .playing(.fromProgress(fromProgress, toProgress: toProgress, loopMode: loopMode ?? self.loopMode))
@@ -148,7 +147,7 @@ public class LottieAnimationLayer: CALayer {
148
147
  }
149
148
 
150
149
  removeCurrentAnimationIfNecessary()
151
- if let loopMode = loopMode {
150
+ if let loopMode {
152
151
  /// Set the loop mode, if one was supplied
153
152
  self.loopMode = loopMode
154
153
  }
@@ -181,7 +180,7 @@ public class LottieAnimationLayer: CALayer {
181
180
  }
182
181
 
183
182
  removeCurrentAnimationIfNecessary()
184
- if let loopMode = loopMode {
183
+ if let loopMode {
185
184
  /// Set the loop mode, if one was supplied
186
185
  self.loopMode = loopMode
187
186
  }
@@ -228,12 +227,12 @@ public class LottieAnimationLayer: CALayer {
228
227
  return
229
228
  }
230
229
 
231
- guard let animation = animation, let markers = animation.markerMap, let to = markers[toMarker] else {
230
+ guard let animation, let markers = animation.markerMap, let to = markers[toMarker] else {
232
231
  return
233
232
  }
234
233
 
235
234
  removeCurrentAnimationIfNecessary()
236
- if let loopMode = loopMode {
235
+ if let loopMode {
237
236
  /// Set the loop mode, if one was supplied
238
237
  self.loopMode = loopMode
239
238
  }
@@ -331,7 +330,7 @@ public class LottieAnimationLayer: CALayer {
331
330
  // If the completion handler is called with `completed: false` (which typically means
332
331
  // that another animation was played by calling some `play` method),
333
332
  // we should cancel the marker sequence and not play the next marker.
334
- guard completed, let self = self else {
333
+ guard completed, let self else {
335
334
  completion?(false)
336
335
  return
337
336
  }
@@ -488,7 +487,7 @@ public class LottieAnimationLayer: CALayer {
488
487
 
489
488
  /// A closure called when the animation layer has been loaded.
490
489
  /// Will inform the receiver the type of rendering engine that is used for the layer.
491
- public var animationLayerDidLoad:((_ animationLayer: LottieAnimationLayer, _ renderingEngine: RenderingEngineOption) -> Void)?
490
+ public var animationLayerDidLoad: ((_ animationLayer: LottieAnimationLayer, _ renderingEngine: RenderingEngineOption) -> Void)?
492
491
 
493
492
  /// The configuration that this `LottieAnimationView` uses when playing its animation
494
493
  public var configuration: LottieConfiguration {
@@ -549,7 +548,7 @@ public class LottieAnimationLayer: CALayer {
549
548
  didSet {
550
549
  makeAnimationLayer(usingEngine: configuration.renderingEngine)
551
550
 
552
- if let animation = animation {
551
+ if let animation {
553
552
  animationLoaded?(self, animation)
554
553
  }
555
554
  }
@@ -584,7 +583,7 @@ public class LottieAnimationLayer: CALayer {
584
583
  /// ```
585
584
  public var animationLoaded: ((_ animationLayer: LottieAnimationLayer, _ animation: LottieAnimation) -> Void)? {
586
585
  didSet {
587
- if let animation = animation {
586
+ if let animation {
588
587
  animationLoaded?(self, animation)
589
588
  }
590
589
  }
@@ -662,7 +661,7 @@ public class LottieAnimationLayer: CALayer {
662
661
  /// Note 2: If `animation` is nil, setting this will fallback to 0
663
662
  public var currentProgress: AnimationProgressTime {
664
663
  set {
665
- if let animation = animation {
664
+ if let animation {
666
665
  currentFrame = animation.frameTime(forProgress: newValue)
667
666
  currentPlaybackMode = .paused(at: .progress(newValue))
668
667
  } else {
@@ -670,7 +669,7 @@ public class LottieAnimationLayer: CALayer {
670
669
  }
671
670
  }
672
671
  get {
673
- if let animation = animation {
672
+ if let animation {
674
673
  return animation.progressTime(forFrame: currentFrame)
675
674
  } else {
676
675
  return 0
@@ -684,7 +683,7 @@ public class LottieAnimationLayer: CALayer {
684
683
  /// Note 2: If `animation` is nil, setting this will fallback to 0
685
684
  public var currentTime: TimeInterval {
686
685
  set {
687
- if let animation = animation {
686
+ if let animation {
688
687
  currentFrame = animation.frameTime(forTime: newValue)
689
688
  currentPlaybackMode = .paused(at: .time(newValue))
690
689
  } else {
@@ -692,7 +691,7 @@ public class LottieAnimationLayer: CALayer {
692
691
  }
693
692
  }
694
693
  get {
695
- if let animation = animation {
694
+ if let animation {
696
695
  return animation.time(forFrame: currentFrame)
697
696
  } else {
698
697
  return 0
@@ -721,7 +720,7 @@ public class LottieAnimationLayer: CALayer {
721
720
 
722
721
  /// Returns the current animation frame while an animation is playing.
723
722
  public var realtimeAnimationProgress: AnimationProgressTime {
724
- if let animation = animation {
723
+ if let animation {
725
724
  return animation.progressTime(forFrame: realtimeAnimationFrame)
726
725
  }
727
726
  return 0
@@ -754,7 +753,7 @@ public class LottieAnimationLayer: CALayer {
754
753
  return engine
755
754
 
756
755
  case .automatic:
757
- guard let animationLayer = animationLayer else {
756
+ guard let animationLayer else {
758
757
  return nil
759
758
  }
760
759
 
@@ -893,7 +892,7 @@ public class LottieAnimationLayer: CALayer {
893
892
  /// - Parameter toLayerAt: The keypath used to find the layer.
894
893
  public func convert(_ rect: CGRect, toLayerAt keypath: AnimationKeypath?) -> CGRect? {
895
894
  guard let animationLayer = rootAnimationLayer else { return nil }
896
- guard let keypath = keypath else {
895
+ guard let keypath else {
897
896
  return convert(rect, to: animationLayer)
898
897
  }
899
898
  guard let sublayer = animationLayer.layer(for: keypath) else {
@@ -914,7 +913,7 @@ public class LottieAnimationLayer: CALayer {
914
913
  /// - Parameter toLayerAt: The keypath used to find the layer.
915
914
  public func convert(_ point: CGPoint, toLayerAt keypath: AnimationKeypath?) -> CGPoint? {
916
915
  guard let animationLayer = rootAnimationLayer else { return nil }
917
- guard let keypath = keypath else {
916
+ guard let keypath else {
918
917
  return convert(point, to: animationLayer)
919
918
  }
920
919
  guard let sublayer = animationLayer.layer(for: keypath) else {
@@ -934,7 +933,7 @@ public class LottieAnimationLayer: CALayer {
934
933
  public func setNodeIsEnabled(isEnabled: Bool, keypath: AnimationKeypath) {
935
934
  guard let animationLayer = rootAnimationLayer else { return }
936
935
  let nodes = animationLayer.animatorNodes(for: keypath)
937
- if let nodes = nodes {
936
+ if let nodes {
938
937
  for node in nodes {
939
938
  node.isEnabled = isEnabled
940
939
  }
@@ -951,7 +950,7 @@ public class LottieAnimationLayer: CALayer {
951
950
  ///
952
951
  /// Returns the Progress Time for the marker named. Returns nil if no marker found.
953
952
  public func progressTime(forMarker named: String) -> AnimationProgressTime? {
954
- guard let animation = animation else {
953
+ guard let animation else {
955
954
  return nil
956
955
  }
957
956
  return animation.progressTime(forMarker: named)
@@ -966,7 +965,7 @@ public class LottieAnimationLayer: CALayer {
966
965
  ///
967
966
  /// Returns the Frame Time for the marker named. Returns nil if no marker found.
968
967
  public func frameTime(forMarker named: String) -> AnimationFrameTime? {
969
- guard let animation = animation else {
968
+ guard let animation else {
970
969
  return nil
971
970
  }
972
971
  return animation.frameTime(forMarker: named)
@@ -981,7 +980,7 @@ public class LottieAnimationLayer: CALayer {
981
980
  ///
982
981
  /// - Returns: The duration frame time for the marker, or `nil` if no marker found.
983
982
  public func durationFrameTime(forMarker named: String) -> AnimationFrameTime? {
984
- guard let animation = animation else {
983
+ guard let animation else {
985
984
  return nil
986
985
  }
987
986
  return animation.durationFrameTime(forMarker: named)
@@ -1074,7 +1073,7 @@ public class LottieAnimationLayer: CALayer {
1074
1073
 
1075
1074
  /// Updates an in flight animation.
1076
1075
  func updateInFlightAnimation() {
1077
- guard let animationContext = animationContext else { return }
1076
+ guard let animationContext else { return }
1078
1077
 
1079
1078
  guard animationContext.closure.animationState != .complete else {
1080
1079
  // Tried to re-add an already completed animation. Cancel.
@@ -1146,7 +1145,7 @@ public class LottieAnimationLayer: CALayer {
1146
1145
  rootAnimationLayer = nil
1147
1146
  }
1148
1147
 
1149
- guard let animation = animation else {
1148
+ guard let animation else {
1150
1149
  return
1151
1150
  }
1152
1151
  let rootAnimationLayer: RootAnimationLayer?
@@ -1294,7 +1293,7 @@ public class LottieAnimationLayer: CALayer {
1294
1293
  // was being used by the previous Core Animation layer
1295
1294
  self.currentFrame = currentFrame
1296
1295
 
1297
- if let animationContext = animationContext {
1296
+ if let animationContext {
1298
1297
  // `AnimationContext.closure` (`AnimationCompletionDelegate`) is a reference type
1299
1298
  // that is the animation layer's `CAAnimationDelegate`, and holds a reference to
1300
1299
  // the animation layer. Reusing a single instance across different animation layers
@@ -1328,25 +1327,12 @@ public class LottieAnimationLayer: CALayer {
1328
1327
 
1329
1328
  /// Adds animation to animation layer and sets the delegate. If animation layer or animation are nil, exits.
1330
1329
  fileprivate func addNewAnimationForContext(_ animationContext: AnimationContext) {
1331
- guard let animationlayer = rootAnimationLayer, let animation = animation else {
1330
+ guard let animationlayer = rootAnimationLayer, let animation else {
1332
1331
  return
1333
1332
  }
1334
1333
 
1335
1334
  self.animationContext = animationContext
1336
1335
 
1337
- switch currentRenderingEngine {
1338
- case .mainThread:
1339
- // On the CALayer side, just play all animations immediately. The UIView side
1340
- // will handle queueing animations.
1341
- break
1342
-
1343
- case .coreAnimation, nil:
1344
- // The Core Animation engine automatically batches animation setup to happen
1345
- // in `CALayer.display()`, which won't be called until the layer is on-screen,
1346
- // so we don't need to defer animation setup at this layer.
1347
- break
1348
- }
1349
-
1350
1336
  animationID = animationID + 1
1351
1337
  _activeAnimationName = LottieAnimationLayer.animationName + String(animationID)
1352
1338
 
@@ -1495,7 +1481,7 @@ public class LottieAnimationLayer: CALayer {
1495
1481
 
1496
1482
  /// Plays the marker that corresponds to the current "reduced motion" mode if present.
1497
1483
  private func playReducedMotionAnimation(completion: LottieCompletionBlock?) {
1498
- guard let reducedMotionMarker = reducedMotionMarker else { return }
1484
+ guard let reducedMotionMarker else { return }
1499
1485
 
1500
1486
  // `play(marker:)` calls the `play(fromFrame:toFrame:)` method which calls this
1501
1487
  // `playReducedMotionAnimation` method when `shouldOverrideWithReducedMotionAnimation`
@@ -5,7 +5,6 @@
5
5
  // Created by Brandon Withrow on 1/23/19.
6
6
  //
7
7
 
8
- import Foundation
9
8
  import QuartzCore
10
9
 
11
10
  // MARK: - LottieBackgroundBehavior
@@ -115,7 +114,7 @@ open class LottieAnimationView: LottieAnimationViewBase {
115
114
  self.logger = logger
116
115
  super.init(frame: .zero)
117
116
  commonInit()
118
- if let animation = animation {
117
+ if let animation {
119
118
  frame = animation.bounds
120
119
  }
121
120
  }
@@ -139,7 +138,7 @@ open class LottieAnimationView: LottieAnimationViewBase {
139
138
  self.logger = logger
140
139
  super.init(frame: .zero)
141
140
  commonInit()
142
- if let animation = animation {
141
+ if let animation {
143
142
  frame = animation.bounds
144
143
  }
145
144
  }
@@ -438,7 +437,7 @@ open class LottieAnimationView: LottieAnimationViewBase {
438
437
  /// ```
439
438
  public var animationLoaded: ((_ animationView: LottieAnimationView, _ animation: LottieAnimation) -> Void)? {
440
439
  didSet {
441
- if let animation = animation {
440
+ if let animation {
442
441
  animationLoaded?(self, animation)
443
442
  }
444
443
  }
@@ -835,14 +834,14 @@ open class LottieAnimationView: LottieAnimationViewBase {
835
834
  viewLayer?.addSublayer(lottieAnimationLayer)
836
835
 
837
836
  lottieAnimationLayer.animationLoaded = { [weak self] _, animation in
838
- guard let self = self else { return }
837
+ guard let self else { return }
839
838
  self.animationLoaded?(self, animation)
840
839
  self.invalidateIntrinsicContentSize()
841
840
  self.setNeedsLayout()
842
841
  }
843
842
 
844
843
  lottieAnimationLayer.animationLayerDidLoad = { [weak self] _, _ in
845
- guard let self = self else { return }
844
+ guard let self else { return }
846
845
  self.invalidateIntrinsicContentSize()
847
846
  self.setNeedsLayout()
848
847
  }
@@ -855,7 +854,7 @@ open class LottieAnimationView: LottieAnimationViewBase {
855
854
  let xform: CATransform3D
856
855
  var shouldForceUpdates = false
857
856
 
858
- if let viewportFrame = viewportFrame {
857
+ if let viewportFrame {
859
858
  setNeedsLayout()
860
859
  shouldForceUpdates = contentMode == .redraw
861
860
 
@@ -62,14 +62,14 @@ extension LottieAnimationView {
62
62
  animationCache: AnimationCacheProvider? = LottieAnimationCache.shared,
63
63
  configuration: LottieConfiguration = .shared)
64
64
  {
65
- if let animationCache = animationCache, let animation = animationCache.animation(forKey: url.absoluteString) {
65
+ if let animationCache, let animation = animationCache.animation(forKey: url.absoluteString) {
66
66
  self.init(animation: animation, imageProvider: imageProvider, configuration: configuration)
67
67
  closure(nil)
68
68
  } else {
69
69
  self.init(animation: nil, imageProvider: imageProvider, configuration: configuration)
70
70
 
71
71
  LottieAnimation.loadedFrom(url: url, session: session, closure: { animation in
72
- if let animation = animation {
72
+ if let animation {
73
73
  self.animation = animation
74
74
  closure(nil)
75
75
  } else {
@@ -166,7 +166,7 @@ extension LottieAnimationView {
166
166
  session: URLSession = .shared,
167
167
  completion: ((LottieAnimationView, Error?) -> Void)? = nil)
168
168
  {
169
- if let dotLottieCache = dotLottieCache, let lottie = dotLottieCache.file(forKey: url.absoluteString) {
169
+ if let dotLottieCache, let lottie = dotLottieCache.file(forKey: url.absoluteString) {
170
170
  self.init(dotLottie: lottie, animationId: animationId, configuration: configuration)
171
171
  completion?(self, nil)
172
172
  } else {
@@ -205,3 +205,56 @@ public enum LottieMarkerPosition: Hashable {
205
205
  case start
206
206
  case end
207
207
  }
208
+
209
+ extension LottiePlaybackMode {
210
+ /// Returns a copy of this `PlaybackMode` with the `LottieLoopMode` updated to the given value
211
+ func loopMode(_ updatedLoopMode: LottieLoopMode) -> LottiePlaybackMode {
212
+ switch self {
213
+ case .playing(let playbackMode):
214
+ return .playing(playbackMode.loopMode(updatedLoopMode))
215
+
216
+ case .fromProgress(let fromProgress, toProgress: let toProgress, _):
217
+ return .playing(.fromProgress(
218
+ fromProgress,
219
+ toProgress: toProgress,
220
+ loopMode: updatedLoopMode))
221
+
222
+ case .fromFrame(let fromFrame, toFrame: let toFrame, _):
223
+ return .playing(.fromFrame(
224
+ fromFrame,
225
+ toFrame: toFrame,
226
+ loopMode: updatedLoopMode))
227
+
228
+ case .fromMarker(let fromMarker, let toMarker, let playEndMarkerFrame, _):
229
+ return .playing(.fromMarker(
230
+ fromMarker,
231
+ toMarker: toMarker,
232
+ playEndMarkerFrame: playEndMarkerFrame,
233
+ loopMode: updatedLoopMode))
234
+
235
+ case .marker(let marker, _):
236
+ return .playing(.marker(marker, loopMode: updatedLoopMode))
237
+
238
+ case .pause, .paused, .progress(_), .time(_), .frame(_), .markers:
239
+ return self
240
+ }
241
+ }
242
+ }
243
+
244
+ extension LottiePlaybackMode.PlaybackMode {
245
+ /// Returns a copy of this `PlaybackMode` with the `LottieLoopMode` updated to the given value
246
+ func loopMode(_ updatedLoopMode: LottieLoopMode) -> LottiePlaybackMode.PlaybackMode {
247
+ switch self {
248
+ case .fromProgress(let fromProgress, let toProgress, _):
249
+ return .fromProgress(fromProgress, toProgress: toProgress, loopMode: updatedLoopMode)
250
+ case .fromFrame(let fromFrame, let toFrame, _):
251
+ return .fromFrame(fromFrame, toFrame: toFrame, loopMode: updatedLoopMode)
252
+ case .fromMarker(let fromMarker, let toMarker, let playEndMarkerFrame, _):
253
+ return .fromMarker(fromMarker, toMarker: toMarker, playEndMarkerFrame: playEndMarkerFrame, loopMode: updatedLoopMode)
254
+ case .marker(let marker, _):
255
+ return .marker(marker, loopMode: updatedLoopMode)
256
+ case .markers:
257
+ return self
258
+ }
259
+ }
260
+ }