lottie-ios 4.1.2 → 4.2.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 (96) hide show
  1. package/.github/workflows/main.yml +27 -9
  2. package/Lottie.xcodeproj/project.pbxproj +158 -70
  3. package/Lottie.xcodeproj/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +2 -2
  4. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/IDEFindNavigatorScopes.plist +5 -0
  5. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  6. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +258 -0
  7. package/Lottie.xcworkspace/xcuserdata/calstephens.xcuserdatad/xcdebugger/Expressions.xcexplist +13 -2
  8. package/Package.swift +2 -1
  9. package/README.md +3 -3
  10. package/Rakefile +8 -4
  11. package/Sources/Private/CoreAnimation/Animations/CALayer+addAnimation.swift +16 -2
  12. package/Sources/Private/CoreAnimation/Animations/CombinedShapeAnimation.swift +1 -1
  13. package/Sources/Private/CoreAnimation/Animations/CustomPathAnimation.swift +1 -1
  14. package/Sources/Private/CoreAnimation/Animations/EllipseAnimation.swift +1 -1
  15. package/Sources/Private/CoreAnimation/Animations/GradientAnimations.swift +6 -6
  16. package/Sources/Private/CoreAnimation/Animations/LayerProperty.swift +76 -7
  17. package/Sources/Private/CoreAnimation/Animations/OpacityAnimation.swift +1 -1
  18. package/Sources/Private/CoreAnimation/Animations/RectangleAnimation.swift +1 -1
  19. package/Sources/Private/CoreAnimation/Animations/ShapeAnimation.swift +66 -102
  20. package/Sources/Private/CoreAnimation/Animations/StarAnimation.swift +2 -2
  21. package/Sources/Private/CoreAnimation/Animations/StrokeAnimation.swift +3 -3
  22. package/Sources/Private/CoreAnimation/Animations/TransformAnimations.swift +66 -17
  23. package/Sources/Private/CoreAnimation/CoreAnimationLayer.swift +55 -32
  24. package/Sources/Private/CoreAnimation/Extensions/Keyframes+combined.swift +16 -12
  25. package/Sources/Private/CoreAnimation/Layers/AnimationLayer.swift +3 -3
  26. package/Sources/Private/CoreAnimation/Layers/BaseCompositionLayer.swift +24 -11
  27. package/Sources/Private/CoreAnimation/Layers/ImageLayer.swift +2 -2
  28. package/Sources/Private/CoreAnimation/Layers/PreCompLayer.swift +1 -1
  29. package/Sources/Private/CoreAnimation/Layers/RepeaterLayer.swift +13 -2
  30. package/Sources/Private/CoreAnimation/Layers/ShapeLayer.swift +9 -1
  31. package/Sources/Private/CoreAnimation/ValueProviderStore.swift +22 -11
  32. package/Sources/Private/MainThread/LayerContainers/CompLayers/MaskContainerLayer.swift +1 -1
  33. package/Sources/Private/MainThread/LayerContainers/MainThreadAnimationLayer.swift +13 -2
  34. package/Sources/Private/MainThread/LayerContainers/Utility/LayerTransformNode.swift +16 -7
  35. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/EllipseNode.swift +1 -1
  36. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/PolygonNode.swift +2 -2
  37. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/RectNode.swift +1 -1
  38. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/PathNodes/StarNode.swift +2 -2
  39. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderContainers/GroupNode.swift +20 -8
  40. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/FillNode.swift +1 -1
  41. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientFillNode.swift +1 -1
  42. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/GradientStrokeNode.swift +1 -1
  43. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/RenderNodes/StrokeNode.swift +1 -1
  44. package/Sources/Private/MainThread/NodeRenderSystem/Nodes/Text/TextAnimatorNode.swift +28 -9
  45. package/Sources/Private/Model/Assets/ImageAsset.swift +4 -3
  46. package/Sources/Private/Model/DotLottie/DotLottieAnimation.swift +2 -8
  47. package/Sources/Private/Model/DotLottie/DotLottieManifest.swift +3 -14
  48. package/Sources/Private/Model/DotLottie/DotLottieUtils.swift +11 -1
  49. package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+BackingConfiguration.swift +147 -0
  50. package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+Helpers.swift +351 -0
  51. package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+MemoryFile.swift +183 -0
  52. package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+Progress.swift +66 -0
  53. package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+Reading.swift +144 -0
  54. package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+ReadingDeprecated.swift +49 -0
  55. package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+Writing.swift +385 -0
  56. package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+WritingDeprecated.swift +91 -0
  57. package/Sources/Private/Model/DotLottie/ZipFoundation/Archive+ZIP64.swift +170 -0
  58. package/Sources/Private/Model/DotLottie/{Zip/ZipArchive.swift → ZipFoundation/Archive.swift} +150 -227
  59. package/Sources/Private/Model/DotLottie/ZipFoundation/Data+Compression.swift +403 -0
  60. package/Sources/Private/Model/DotLottie/ZipFoundation/Data+CompressionDeprecated.swift +44 -0
  61. package/Sources/Private/Model/DotLottie/{Zip → ZipFoundation}/Data+Serialization.swift +62 -0
  62. package/Sources/Private/Model/DotLottie/{Zip/ZipEntry+Serialization.swift → ZipFoundation/Entry+Serialization.swift} +7 -7
  63. package/Sources/Private/Model/DotLottie/{Zip/ZipEntry+ZIP64.swift → ZipFoundation/Entry+ZIP64.swift} +13 -19
  64. package/Sources/Private/Model/DotLottie/{Zip/ZipEntry.swift → ZipFoundation/Entry.swift} +141 -10
  65. package/Sources/Private/Model/DotLottie/ZipFoundation/FileManager+ZIP.swift +368 -0
  66. package/Sources/Private/Model/DotLottie/ZipFoundation/README.md +24 -0
  67. package/Sources/Private/Model/DotLottie/ZipFoundation/URL+ZIP.swift +32 -0
  68. package/Sources/Private/Model/Extensions/Bundle.swift +5 -14
  69. package/Sources/Private/Model/Keyframes/KeyframeGroup.swift +31 -8
  70. package/Sources/Private/Model/Objects/Transform.swift +58 -17
  71. package/Sources/Private/Model/ShapeItems/Repeater.swift +41 -7
  72. package/Sources/Private/Model/ShapeItems/ShapeTransform.swift +61 -7
  73. package/Sources/Private/Model/Text/TextAnimator.swift +37 -5
  74. package/Sources/Private/RootAnimationLayer.swift +3 -1
  75. package/Sources/Private/Utility/Extensions/AnimationKeypathExtension.swift +12 -4
  76. package/Sources/Private/Utility/Extensions/DataExtension.swift +14 -4
  77. package/Sources/Private/Utility/Primitives/BezierPathRoundExtension.swift +11 -0
  78. package/Sources/Private/Utility/Primitives/ColorExtension.swift +10 -13
  79. package/Sources/Private/Utility/Primitives/VectorsExtensions.swift +28 -6
  80. package/Sources/Public/Animation/LottieAnimationHelpers.swift +12 -10
  81. package/Sources/Public/Animation/LottieAnimationView.swift +213 -186
  82. package/Sources/Public/DotLottie/DotLottieFile.swift +11 -34
  83. package/Sources/Public/DotLottie/DotLottieFileHelpers.swift +101 -74
  84. package/Sources/Public/iOS/Compatibility/CompatibleAnimationView.swift +90 -0
  85. package/Sources/Public/iOS/LottieAnimationViewBase.swift +1 -1
  86. package/Sources/Public/macOS/LottieAnimationViewBase.macOS.swift +1 -1
  87. package/lottie-ios.podspec +1 -1
  88. package/package.json +1 -1
  89. package/LottieAnimation/LottieAnimation.xcodeproj/project.xcworkspace/xcuserdata/calstephens.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  90. package/LottieAnimation/LottieAnimation.xcodeproj/project.xcworkspace/xcuserdata/valentinperignon.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  91. package/LottieAnimation/LottieAnimation.xcodeproj/xcuserdata/calstephens.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  92. package/LottieAnimation/LottieAnimation.xcodeproj/xcuserdata/valentinperignon.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +0 -6
  93. package/LottieAnimation/LottieAnimation.xcodeproj/xcuserdata/valentinperignon.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  94. package/Sources/Private/Model/DotLottie/Zip/Data+Compression.swift +0 -134
  95. package/Sources/Private/Model/DotLottie/Zip/FileManager+ZIP.swift +0 -130
  96. package/Sources/Private/Utility/Interpolatable/KeyframeGroup+Extensions.swift +0 -59
@@ -20,7 +20,9 @@ final class GroupNodeProperties: NodePropertyMap, KeypathSearchable {
20
20
  anchor = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.anchor.keyframes))
21
21
  position = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.position.keyframes))
22
22
  scale = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.scale.keyframes))
23
- rotation = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.rotation.keyframes))
23
+ rotationX = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.rotationX.keyframes))
24
+ rotationY = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.rotationY.keyframes))
25
+ rotationZ = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.rotationZ.keyframes))
24
26
  opacity = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.opacity.keyframes))
25
27
  skew = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.skew.keyframes))
26
28
  skewAxis = NodeProperty(provider: KeyframeInterpolator(keyframes: transform.skewAxis.keyframes))
@@ -29,17 +31,22 @@ final class GroupNodeProperties: NodePropertyMap, KeypathSearchable {
29
31
  anchor = NodeProperty(provider: SingleValueProvider(LottieVector3D(x: CGFloat(0), y: CGFloat(0), z: CGFloat(0))))
30
32
  position = NodeProperty(provider: SingleValueProvider(LottieVector3D(x: CGFloat(0), y: CGFloat(0), z: CGFloat(0))))
31
33
  scale = NodeProperty(provider: SingleValueProvider(LottieVector3D(x: CGFloat(100), y: CGFloat(100), z: CGFloat(100))))
32
- rotation = NodeProperty(provider: SingleValueProvider(LottieVector1D(0)))
34
+ rotationX = NodeProperty(provider: SingleValueProvider(LottieVector1D(0)))
35
+ rotationY = NodeProperty(provider: SingleValueProvider(LottieVector1D(0)))
36
+ rotationZ = NodeProperty(provider: SingleValueProvider(LottieVector1D(0)))
33
37
  opacity = NodeProperty(provider: SingleValueProvider(LottieVector1D(100)))
34
38
  skew = NodeProperty(provider: SingleValueProvider(LottieVector1D(0)))
35
39
  skewAxis = NodeProperty(provider: SingleValueProvider(LottieVector1D(0)))
36
40
  }
37
41
  keypathProperties = [
38
42
  "Anchor Point" : anchor,
39
- "Position" : position,
40
- "Scale" : scale,
41
- "Rotation" : rotation,
42
- "Opacity" : opacity,
43
+ PropertyName.position.rawValue : position,
44
+ PropertyName.scale.rawValue : scale,
45
+ PropertyName.rotation.rawValue : rotationZ,
46
+ "Rotation X" : rotationX,
47
+ "Rotation Y" : rotationY,
48
+ "Rotation Z" : rotationZ,
49
+ PropertyName.opacity.rawValue : opacity,
43
50
  "Skew" : skew,
44
51
  "Skew Axis" : skewAxis,
45
52
  ]
@@ -58,7 +65,10 @@ final class GroupNodeProperties: NodePropertyMap, KeypathSearchable {
58
65
  let anchor: NodeProperty<LottieVector3D>
59
66
  let position: NodeProperty<LottieVector3D>
60
67
  let scale: NodeProperty<LottieVector3D>
61
- let rotation: NodeProperty<LottieVector1D>
68
+ let rotationX: NodeProperty<LottieVector1D>
69
+ let rotationY: NodeProperty<LottieVector1D>
70
+ let rotationZ: NodeProperty<LottieVector1D>
71
+
62
72
  let opacity: NodeProperty<LottieVector1D>
63
73
  let skew: NodeProperty<LottieVector1D>
64
74
  let skewAxis: NodeProperty<LottieVector1D>
@@ -68,7 +78,9 @@ final class GroupNodeProperties: NodePropertyMap, KeypathSearchable {
68
78
  anchor: anchor.value.pointValue,
69
79
  position: position.value.pointValue,
70
80
  scale: scale.value.sizeValue,
71
- rotation: rotation.value.cgFloatValue,
81
+ rotationX: rotationX.value.cgFloatValue,
82
+ rotationY: rotationY.value.cgFloatValue,
83
+ rotationZ: rotationZ.value.cgFloatValue,
72
84
  skew: skew.value.cgFloatValue,
73
85
  skewAxis: skewAxis.value.cgFloatValue)
74
86
  }
@@ -20,7 +20,7 @@ final class FillNodeProperties: NodePropertyMap, KeypathSearchable {
20
20
  opacity = NodeProperty(provider: KeyframeInterpolator(keyframes: fill.opacity.keyframes))
21
21
  type = fill.fillRule
22
22
  keypathProperties = [
23
- "Opacity" : opacity,
23
+ PropertyName.opacity.rawValue : opacity,
24
24
  PropertyName.color.rawValue : color,
25
25
  ]
26
26
  properties = Array(keypathProperties.values)
@@ -24,7 +24,7 @@ final class GradientFillProperties: NodePropertyMap, KeypathSearchable {
24
24
  numberOfColors = gradientfill.numberOfColors
25
25
  fillRule = gradientfill.fillRule
26
26
  keypathProperties = [
27
- "Opacity" : opacity,
27
+ PropertyName.opacity.rawValue : opacity,
28
28
  "Start Point" : startPoint,
29
29
  "End Point" : endPoint,
30
30
  "Colors" : colors,
@@ -44,7 +44,7 @@ final class GradientStrokeProperties: NodePropertyMap, KeypathSearchable {
44
44
  dashPhase = NodeProperty(provider: SingleValueProvider(LottieVector1D(0)))
45
45
  }
46
46
  keypathProperties = [
47
- "Opacity" : opacity,
47
+ PropertyName.opacity.rawValue : opacity,
48
48
  "Start Point" : startPoint,
49
49
  "End Point" : endPoint,
50
50
  "Colors" : colors,
@@ -36,7 +36,7 @@ final class StrokeNodeProperties: NodePropertyMap, KeypathSearchable {
36
36
  dashPhase = NodeProperty(provider: SingleValueProvider(LottieVector1D(0)))
37
37
  }
38
38
  keypathProperties = [
39
- "Opacity" : opacity,
39
+ PropertyName.opacity.rawValue : opacity,
40
40
  PropertyName.color.rawValue : color,
41
41
  "Stroke Width" : width,
42
42
  "Dashes" : dashPattern,
@@ -28,14 +28,14 @@ final class TextAnimatorNodeProperties: NodePropertyMap, KeypathSearchable {
28
28
 
29
29
  if let keyframeGroup = textAnimator.position {
30
30
  position = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframeGroup.keyframes))
31
- properties["Position"] = position
31
+ properties[PropertyName.position.rawValue] = position
32
32
  } else {
33
33
  position = nil
34
34
  }
35
35
 
36
36
  if let keyframeGroup = textAnimator.scale {
37
37
  scale = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframeGroup.keyframes))
38
- properties["Scale"] = scale
38
+ properties[PropertyName.scale.rawValue] = scale
39
39
  } else {
40
40
  scale = nil
41
41
  }
@@ -54,16 +54,31 @@ final class TextAnimatorNodeProperties: NodePropertyMap, KeypathSearchable {
54
54
  skewAxis = nil
55
55
  }
56
56
 
57
- if let keyframeGroup = textAnimator.rotation {
58
- rotation = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframeGroup.keyframes))
59
- properties["Rotation"] = rotation
57
+ if let keyframeGroup = textAnimator.rotationX {
58
+ rotationX = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframeGroup.keyframes))
59
+ properties["Rotation X"] = rotationX
60
60
  } else {
61
- rotation = nil
61
+ rotationX = nil
62
+ }
63
+
64
+ if let keyframeGroup = textAnimator.rotationY {
65
+ rotationY = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframeGroup.keyframes))
66
+ properties["Rotation Y"] = rotationY
67
+ } else {
68
+ rotationY = nil
69
+ }
70
+
71
+ if let keyframeGroup = textAnimator.rotationZ {
72
+ rotationZ = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframeGroup.keyframes))
73
+ properties["Rotation Z"] = rotationZ
74
+ properties[PropertyName.rotation.rawValue] = rotationZ
75
+ } else {
76
+ rotationZ = nil
62
77
  }
63
78
 
64
79
  if let keyframeGroup = textAnimator.opacity {
65
80
  opacity = NodeProperty(provider: KeyframeInterpolator(keyframes: keyframeGroup.keyframes))
66
- properties["Opacity"] = opacity
81
+ properties[PropertyName.opacity.rawValue] = opacity
67
82
  } else {
68
83
  opacity = nil
69
84
  }
@@ -110,7 +125,9 @@ final class TextAnimatorNodeProperties: NodePropertyMap, KeypathSearchable {
110
125
  let scale: NodeProperty<LottieVector3D>?
111
126
  let skew: NodeProperty<LottieVector1D>?
112
127
  let skewAxis: NodeProperty<LottieVector1D>?
113
- let rotation: NodeProperty<LottieVector1D>?
128
+ let rotationX: NodeProperty<LottieVector1D>?
129
+ let rotationY: NodeProperty<LottieVector1D>?
130
+ let rotationZ: NodeProperty<LottieVector1D>?
114
131
  let opacity: NodeProperty<LottieVector1D>?
115
132
  let strokeColor: NodeProperty<LottieColor>?
116
133
  let fillColor: NodeProperty<LottieColor>?
@@ -125,7 +142,9 @@ final class TextAnimatorNodeProperties: NodePropertyMap, KeypathSearchable {
125
142
  anchor: anchor?.value.pointValue ?? .zero,
126
143
  position: position?.value.pointValue ?? .zero,
127
144
  scale: scale?.value.sizeValue ?? CGSize(width: 100, height: 100),
128
- rotation: rotation?.value.cgFloatValue ?? 0,
145
+ rotationX: rotationX?.value.cgFloatValue ?? 0,
146
+ rotationY: rotationY?.value.cgFloatValue ?? 0,
147
+ rotationZ: rotationZ?.value.cgFloatValue ?? 0,
129
148
  skew: skew?.value.cgFloatValue,
130
149
  skewAxis: skewAxis?.value.cgFloatValue)
131
150
  }
@@ -80,9 +80,10 @@ extension Data {
80
80
  /// - parameter dataString: The data string to parse.
81
81
  /// - parameter options: Options for the string parsing. Default value is `[]`.
82
82
  internal init?(dataString: String, options: DataURLReadOptions = []) {
83
+ let trimmedDataString = dataString.trimmingCharacters(in: .whitespacesAndNewlines)
83
84
  guard
84
85
  dataString.hasPrefix("data:"),
85
- let url = URL(string: dataString)
86
+ let url = URL(string: trimmedDataString)
86
87
  else {
87
88
  return nil
88
89
  }
@@ -90,10 +91,10 @@ extension Data {
90
91
  // with messages since url doesn't have a host. This only fixes flooding logs
91
92
  // when data inside Data URL is base64 encoded.
92
93
  if
93
- let base64Range = dataString.range(of: ";base64,"),
94
+ let base64Range = trimmedDataString.range(of: ";base64,"),
94
95
  !options.contains(DataURLReadOptions.legacy)
95
96
  {
96
- let encodedString = String(dataString[base64Range.upperBound...])
97
+ let encodedString = String(trimmedDataString[base64Range.upperBound...])
97
98
  self.init(base64Encoded: encodedString)
98
99
  } else {
99
100
  try? self.init(contentsOf: url)
@@ -23,9 +23,6 @@ struct DotLottieAnimation: Codable {
23
23
  /// mode - "bounce" | "normal"
24
24
  var mode: String? = "normal"
25
25
 
26
- /// URL to animation, to be set internally
27
- var animationUrl: URL?
28
-
29
26
  /// Loop mode for animation
30
27
  var loopMode: LottieLoopMode {
31
28
  mode == "bounce" ? .autoReverse : ((loop ?? false) ? .loop : .playOnce)
@@ -38,12 +35,9 @@ struct DotLottieAnimation: Codable {
38
35
 
39
36
  /// Loads `LottieAnimation` from `animationUrl`
40
37
  /// - Returns: Deserialized `LottieAnimation`. Optional.
41
- func animation() throws -> LottieAnimation {
42
- guard let animationUrl = animationUrl else {
43
- throw DotLottieError.animationNotAvailable
44
- }
38
+ func animation(url: URL) throws -> LottieAnimation {
39
+ let animationUrl = url.appendingPathComponent("\(id).json")
45
40
  let data = try Data(contentsOf: animationUrl)
46
41
  return try LottieAnimation.from(data: data)
47
42
  }
48
-
49
43
  }
@@ -10,21 +10,10 @@ import Foundation
10
10
  /// Manifest model for .lottie File
11
11
  struct DotLottieManifest: Codable {
12
12
 
13
- // MARK: Lifecycle
14
-
15
- init(animations: [DotLottieAnimation], version: String, author: String, generator: String) {
16
- self.animations = animations
17
- self.version = version
18
- self.author = author
19
- self.generator = generator
20
- }
21
-
22
- // MARK: Internal
23
-
24
13
  var animations: [DotLottieAnimation]
25
- var version: String
26
- var author: String
27
- var generator: String
14
+ var version: String?
15
+ var author: String?
16
+ var generator: String?
28
17
 
29
18
  /// Decodes data to Manifest model
30
19
  /// - Parameter data: Data to decode
@@ -15,7 +15,7 @@ struct DotLottieUtils {
15
15
 
16
16
  /// Temp folder to app directory
17
17
  static var tempDirectoryURL: URL {
18
- if #available(iOS 10.0, *) {
18
+ if #available(iOS 10.0, macOS 10.12, *) {
19
19
  return FileManager.default.temporaryDirectory
20
20
  }
21
21
  return URL(fileURLWithPath: NSTemporaryDirectory())
@@ -52,7 +52,17 @@ extension FileManager {
52
52
  // MARK: - DotLottieError
53
53
 
54
54
  public enum DotLottieError: Error {
55
+ /// URL response has no data.
56
+ case noDataLoaded
57
+ /// Asset with this name was not found in the provided bundle.
58
+ case assetNotFound(name: String, bundle: Bundle?)
59
+ /// Animation loading from asset is not supported on macOS 10.10.
60
+ case loadingFromAssetNotSupported
61
+
62
+ @available(*, deprecated, message: "Unused")
55
63
  case invalidFileFormat
64
+ @available(*, deprecated, message: "Unused")
56
65
  case invalidData
66
+ @available(*, deprecated, message: "Unused")
57
67
  case animationNotAvailable
58
68
  }
@@ -0,0 +1,147 @@
1
+ //
2
+ // Archive+BackingConfiguration.swift
3
+ // ZIPFoundation
4
+ //
5
+ // Copyright © 2017-2021 Thomas Zoechling, https://www.peakstep.com and the ZIP Foundation project authors.
6
+ // Released under the MIT License.
7
+ //
8
+ // See https://github.com/weichsel/ZIPFoundation/blob/master/LICENSE for license information.
9
+ //
10
+
11
+ import Foundation
12
+
13
+ extension Archive {
14
+
15
+ struct BackingConfiguration {
16
+ let file: FILEPointer
17
+ let endOfCentralDirectoryRecord: EndOfCentralDirectoryRecord
18
+ let zip64EndOfCentralDirectory: ZIP64EndOfCentralDirectory?
19
+
20
+ #if swift(>=5.0)
21
+ let memoryFile: MemoryFile?
22
+
23
+ init(
24
+ file: FILEPointer,
25
+ endOfCentralDirectoryRecord: EndOfCentralDirectoryRecord,
26
+ zip64EndOfCentralDirectory: ZIP64EndOfCentralDirectory? = nil,
27
+ memoryFile: MemoryFile? = nil)
28
+ {
29
+ self.file = file
30
+ self.endOfCentralDirectoryRecord = endOfCentralDirectoryRecord
31
+ self.zip64EndOfCentralDirectory = zip64EndOfCentralDirectory
32
+ self.memoryFile = memoryFile
33
+ }
34
+ #else
35
+
36
+ init(
37
+ file: FILEPointer,
38
+ endOfCentralDirectoryRecord: EndOfCentralDirectoryRecord,
39
+ zip64EndOfCentralDirectory: ZIP64EndOfCentralDirectory?)
40
+ {
41
+ self.file = file
42
+ self.endOfCentralDirectoryRecord = endOfCentralDirectoryRecord
43
+ self.zip64EndOfCentralDirectory = zip64EndOfCentralDirectory
44
+ }
45
+ #endif
46
+ }
47
+
48
+ static func makeBackingConfiguration(for url: URL, mode: AccessMode)
49
+ -> BackingConfiguration?
50
+ {
51
+ let fileManager = FileManager()
52
+ switch mode {
53
+ case .read:
54
+ let fileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: url.path)
55
+ guard
56
+ let archiveFile = fopen(fileSystemRepresentation, "rb"),
57
+ let (eocdRecord, zip64EOCD) = Archive.scanForEndOfCentralDirectoryRecord(in: archiveFile) else
58
+ {
59
+ return nil
60
+ }
61
+ return BackingConfiguration(
62
+ file: archiveFile,
63
+ endOfCentralDirectoryRecord: eocdRecord,
64
+ zip64EndOfCentralDirectory: zip64EOCD)
65
+ case .create:
66
+ let endOfCentralDirectoryRecord = EndOfCentralDirectoryRecord(
67
+ numberOfDisk: 0,
68
+ numberOfDiskStart: 0,
69
+ totalNumberOfEntriesOnDisk: 0,
70
+ totalNumberOfEntriesInCentralDirectory: 0,
71
+ sizeOfCentralDirectory: 0,
72
+ offsetToStartOfCentralDirectory: 0,
73
+ zipFileCommentLength: 0,
74
+ zipFileCommentData: Data())
75
+ do {
76
+ try endOfCentralDirectoryRecord.data.write(to: url, options: .withoutOverwriting)
77
+ } catch { return nil }
78
+ fallthrough
79
+ case .update:
80
+ let fileSystemRepresentation = fileManager.fileSystemRepresentation(withPath: url.path)
81
+ guard
82
+ let archiveFile = fopen(fileSystemRepresentation, "rb+"),
83
+ let (eocdRecord, zip64EOCD) = Archive.scanForEndOfCentralDirectoryRecord(in: archiveFile) else
84
+ {
85
+ return nil
86
+ }
87
+ fseeko(archiveFile, 0, SEEK_SET)
88
+ return BackingConfiguration(
89
+ file: archiveFile,
90
+ endOfCentralDirectoryRecord: eocdRecord,
91
+ zip64EndOfCentralDirectory: zip64EOCD)
92
+ }
93
+ }
94
+
95
+ #if swift(>=5.0)
96
+ static func makeBackingConfiguration(for data: Data, mode: AccessMode)
97
+ -> BackingConfiguration?
98
+ {
99
+ let posixMode: String
100
+ switch mode {
101
+ case .read: posixMode = "rb"
102
+ case .create: posixMode = "wb+"
103
+ case .update: posixMode = "rb+"
104
+ }
105
+ let memoryFile = MemoryFile(data: data)
106
+ guard let archiveFile = memoryFile.open(mode: posixMode) else { return nil }
107
+
108
+ switch mode {
109
+ case .read:
110
+ guard let (eocdRecord, zip64EOCD) = Archive.scanForEndOfCentralDirectoryRecord(in: archiveFile) else {
111
+ return nil
112
+ }
113
+
114
+ return BackingConfiguration(
115
+ file: archiveFile,
116
+ endOfCentralDirectoryRecord: eocdRecord,
117
+ zip64EndOfCentralDirectory: zip64EOCD,
118
+ memoryFile: memoryFile)
119
+ case .create:
120
+ let endOfCentralDirectoryRecord = EndOfCentralDirectoryRecord(
121
+ numberOfDisk: 0,
122
+ numberOfDiskStart: 0,
123
+ totalNumberOfEntriesOnDisk: 0,
124
+ totalNumberOfEntriesInCentralDirectory: 0,
125
+ sizeOfCentralDirectory: 0,
126
+ offsetToStartOfCentralDirectory: 0,
127
+ zipFileCommentLength: 0,
128
+ zipFileCommentData: Data())
129
+ _ = endOfCentralDirectoryRecord.data.withUnsafeBytes { (buffer: UnsafeRawBufferPointer) in
130
+ fwrite(buffer.baseAddress, buffer.count, 1, archiveFile) // Errors handled during read
131
+ }
132
+ fallthrough
133
+ case .update:
134
+ guard let (eocdRecord, zip64EOCD) = Archive.scanForEndOfCentralDirectoryRecord(in: archiveFile) else {
135
+ return nil
136
+ }
137
+
138
+ fseeko(archiveFile, 0, SEEK_SET)
139
+ return BackingConfiguration(
140
+ file: archiveFile,
141
+ endOfCentralDirectoryRecord: eocdRecord,
142
+ zip64EndOfCentralDirectory: zip64EOCD,
143
+ memoryFile: memoryFile)
144
+ }
145
+ }
146
+ #endif
147
+ }