From ce41830d8d566828e3f1621b20e191eb6576c015 Mon Sep 17 00:00:00 2001 From: Evandro Date: Wed, 23 Jun 2021 09:48:21 +0800 Subject: [PATCH 01/13] [FEAT] Added alternative appearance capability to dot lottie creation --- Example/dotLottieLoader/ViewController.swift | 15 ++++++++ Sources/dotLottieLoader/DotLottieFile.swift | 31 +++++++++++++++- Sources/dotLottieLoader/DotLottieLoader.swift | 5 ++- .../dotLottieLoader/DotLottieManifest.swift | 37 +++++++++++++++++++ 4 files changed, 84 insertions(+), 4 deletions(-) diff --git a/Example/dotLottieLoader/ViewController.swift b/Example/dotLottieLoader/ViewController.swift index 09790e4..2622f92 100644 --- a/Example/dotLottieLoader/ViewController.swift +++ b/Example/dotLottieLoader/ViewController.swift @@ -28,6 +28,21 @@ class ViewController: UIViewController { print("dotLottieFile decompressed successfuly with \(dotLottieFile.animations.count) animation\(dotLottieFile.animations.count == 1 ? "" : "s")") } } + + DotLottieLoader.dotLottie(fromJsonLottieAt: URL(string: "https://assets7.lottiefiles.com/packages/lf20_6k4jsmai.json")!, + appearances: [.dark: "https://assets2.lottiefiles.com/packages/lf20_EMJU5F.json", + .custom("sunset"): "https://assets1.lottiefiles.com/private_files/lf30_uYTfuZ.json"]) { url in + // file compressed into dotLottie + guard let url = url else { return } + DotLottieLoader.load(from: url) { dotLottieFile in + // file decompressed from dotLottie + guard let dotLottieFile = dotLottieFile else { + print("invalid dotLottie file") + return + } + print("dotLottieFile decompressed successfuly with \(dotLottieFile.animations.count) animation\(dotLottieFile.animations.count == 1 ? "" : "s")") + } + } } override func didReceiveMemoryWarning() { diff --git a/Sources/dotLottieLoader/DotLottieFile.swift b/Sources/dotLottieLoader/DotLottieFile.swift index 2894d63..7cb1b7f 100644 --- a/Sources/dotLottieLoader/DotLottieFile.swift +++ b/Sources/dotLottieLoader/DotLottieFile.swift @@ -92,11 +92,12 @@ public struct DotLottieFile { /// Creates dotLottieFile from animation json /// - Parameters: /// - url: url of JSON lottie animation + /// - appearances: Array of alternative appearances (dark/light/custom) /// - directory: directory to save file /// - loop: loop enabled /// - themeColor: theme color /// - Returns: URL of .lottie file - static func compress(jsonLottieAt url: URL, in directory: URL = DotLottieUtils.tempDirectoryURL, loop: Bool = true, themeColor: String = "#ffffff") -> URL? { + static func compress(jsonLottieAt url: URL, appearances: DotLottieAppearance? = nil, in directory: URL = DotLottieUtils.tempDirectoryURL, loop: Bool = true, themeColor: String = "#ffffff") -> URL? { Zip.addCustomFileExtension(DotLottieUtils.dotLottieExtension) do { @@ -110,9 +111,11 @@ public struct DotLottieFile { let animationData = try Data(contentsOf: url) try animationData.write(to: animationsDirectory.appendingPathComponent(fileName).appendingPathExtension("json")) + let processedAppearance = processsAppearance(forJsonLottieAt: url, appearances: appearances, fileName: fileName, animationsDirectory: animationsDirectory) + let manifest = DotLottieManifest(animations: [ DotLottieAnimation(loop: loop, themeColor: themeColor, speed: 1.0, id: fileName) - ], version: "1.0", author: "LottieFiles", generator: "LottieFiles dotLottieLoader-iOS 0.1.4") + ], version: "1.0", author: "LottieFiles", generator: "LottieFiles dotLottieLoader-iOS 0.1.4", appearance: processedAppearance) let manifestUrl = dotLottieDirectory.appendingPathComponent("manifest").appendingPathExtension("json") let manifestData = try manifest.encode() try manifestData.write(to: manifestUrl) @@ -129,4 +132,28 @@ public struct DotLottieFile { } } + + private static func processsAppearance(forJsonLottieAt jsonUrl: URL, appearances: DotLottieAppearance?, fileName: String, animationsDirectory: URL) -> DotLottieAppearance { + var dotLottieAppearance: DotLottieAppearance = [.light: fileName] + + appearances?.forEach({ + guard let url = URL(string: $0.value), url.isJsonFile else { + DotLottieUtils.log("Value for appearance \($0.key) is not a valid JSON URL") + return + } + + do { + let appearanceFileName = "\(fileName)-\($0.key.rawValue)" + let apperanceUrl = animationsDirectory.appendingPathComponent(appearanceFileName).appendingPathExtension("json") + let animationData = try Data(contentsOf: url) + try animationData.write(to: apperanceUrl) + + dotLottieAppearance[$0.key] = appearanceFileName + } catch { + DotLottieUtils.log("Could not process value for appearance: \($0.key)") + } + }) + + return dotLottieAppearance + } } diff --git a/Sources/dotLottieLoader/DotLottieLoader.swift b/Sources/dotLottieLoader/DotLottieLoader.swift index ac4ceee..b8904b8 100644 --- a/Sources/dotLottieLoader/DotLottieLoader.swift +++ b/Sources/dotLottieLoader/DotLottieLoader.swift @@ -85,16 +85,17 @@ public class DotLottieLoader { /// Creates .lottie file from a json animation /// - Parameters: /// - jsonUrl: URL to JSON lottie animation + /// - appearances: Array of alternative appearances (dark/light/custom) /// - loop: loop enabled /// - themeColor: theme color in HEX /// - completion: URL to .lottie file - public static func dotLottie(fromJsonLottieAt jsonUrl: URL, loop: Bool = true, themeColor: String = "#ffffff", completion: @escaping (URL?) -> Void) { + public static func dotLottie(fromJsonLottieAt jsonUrl: URL, appearances: DotLottieAppearance? = nil, loop: Bool = true, themeColor: String = "#ffffff", completion: @escaping (URL?) -> Void) { guard jsonUrl.isJsonFile else { DotLottieUtils.log("Not a json file") return } - guard let dotLottieUrl = DotLottieFile.compress(jsonLottieAt: jsonUrl, loop: loop, themeColor: themeColor) else { + guard let dotLottieUrl = DotLottieFile.compress(jsonLottieAt: jsonUrl, appearances: appearances, loop: loop, themeColor: themeColor) else { DotLottieUtils.log("Failed to create dotLottie file") completion(nil) return diff --git a/Sources/dotLottieLoader/DotLottieManifest.swift b/Sources/dotLottieLoader/DotLottieManifest.swift index 224653c..57be7b9 100644 --- a/Sources/dotLottieLoader/DotLottieManifest.swift +++ b/Sources/dotLottieLoader/DotLottieManifest.swift @@ -14,6 +14,7 @@ public struct DotLottieManifest: Codable { public var version: String public var author: String public var generator: String + public var appearance: DotLottieAppearance? /// Decodes data to Manifest model /// - Parameter data: Data to decode @@ -48,3 +49,39 @@ public struct DotLottieAnimation: Codable { public var speed: Float public var id: String } + +/// Theme model for .lottie File +public typealias DotLottieAppearance = [DotLottieAppearanceType: String] + +/// Type of Appearance +public enum DotLottieAppearanceType: RawRepresentable, Equatable, Hashable, Codable { + case dark + case light + case custom(String) + + public typealias RawValue = String + + public init?(rawValue: RawValue) { + switch rawValue { + case "dark": self = .dark + case "light": self = .light + case (let value): self = .custom(value) + } + } + + public var rawValue: RawValue { + switch self { + case .dark: return "dark" + case .light: return "light" + case .custom(let value): return value + } + } + + public static func == (lhs: DotLottieAppearanceType, rhs: DotLottieAppearanceType) -> Bool { + lhs.rawValue == rhs.rawValue + } + + public var hashValue: Int { + rawValue.hashValue + } +} From b389fbdaa77d62801ca7bbc1eae3027903260bf9 Mon Sep 17 00:00:00 2001 From: Evandro Date: Wed, 23 Jun 2021 13:43:30 +0800 Subject: [PATCH 02/13] [FEAT] Adds ability to fetch animation by appearance --- Example/dotLottieLoader/ViewController.swift | 39 ++++++++++++-------- Sources/dotLottieLoader/DotLottieFile.swift | 21 +++++++++-- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/Example/dotLottieLoader/ViewController.swift b/Example/dotLottieLoader/ViewController.swift index 2622f92..9014e51 100644 --- a/Example/dotLottieLoader/ViewController.swift +++ b/Example/dotLottieLoader/ViewController.swift @@ -16,22 +16,21 @@ class ViewController: UIViewController { // Do any additional setup after loading the view, typically from a nib. DotLottieUtils.isLogEnabled = true - DotLottieLoader.dotLottie(fromJsonLottieAt: URL(string: "https://assets7.lottiefiles.com/packages/lf20_6k4jsmai.json")!) { url in - // file compressed into dotLottie - guard let url = url else { return } - DotLottieLoader.load(from: url) { dotLottieFile in - // file decompressed from dotLottie - guard let dotLottieFile = dotLottieFile else { - print("invalid dotLottie file") - return - } - print("dotLottieFile decompressed successfuly with \(dotLottieFile.animations.count) animation\(dotLottieFile.animations.count == 1 ? "" : "s")") - } - } +// DotLottieLoader.dotLottie(fromJsonLottieAt: URL(string: "https://assets7.lottiefiles.com/packages/lf20_6k4jsmai.json")!) { url in +// // file compressed into dotLottie +// guard let url = url else { return } +// DotLottieLoader.load(from: url) { dotLottieFile in +// // file decompressed from dotLottie +// guard let dotLottieFile = dotLottieFile else { +// print("invalid dotLottie file") +// return +// } +// print("dotLottieFile decompressed successfuly with \(dotLottieFile.animations.count) animation\(dotLottieFile.animations.count == 1 ? "" : "s")") +// } +// } - DotLottieLoader.dotLottie(fromJsonLottieAt: URL(string: "https://assets7.lottiefiles.com/packages/lf20_6k4jsmai.json")!, - appearances: [.dark: "https://assets2.lottiefiles.com/packages/lf20_EMJU5F.json", - .custom("sunset"): "https://assets1.lottiefiles.com/private_files/lf30_uYTfuZ.json"]) { url in + DotLottieLoader.dotLottie(fromJsonLottieAt: URL(string: "https://assets7.lottiefiles.com/private_files/lf30_p25uf33d.json")!, + appearances: [.dark: "https://assets8.lottiefiles.com/private_files/lf30_yiodtvs6.json"]) { url in // file compressed into dotLottie guard let url = url else { return } DotLottieLoader.load(from: url) { dotLottieFile in @@ -40,7 +39,15 @@ class ViewController: UIViewController { print("invalid dotLottie file") return } - print("dotLottieFile decompressed successfuly with \(dotLottieFile.animations.count) animation\(dotLottieFile.animations.count == 1 ? "" : "s")") + + print(""" + dotLottieFile decompressed successfuly with: + - \(dotLottieFile.animations.count) animations + - \(dotLottieFile.images.count) images + - \(dotLottieFile.manifest?.appearance?.count ?? 0) appearances + - Light theme: \(dotLottieFile.animationURL(for: .light)?.absoluteString ?? "not defined") + - Dark theme: \(dotLottieFile.animationURL(for: .dark)?.absoluteString ?? "not defined") + """) } } } diff --git a/Sources/dotLottieLoader/DotLottieFile.swift b/Sources/dotLottieLoader/DotLottieFile.swift index 7cb1b7f..dffc0d4 100644 --- a/Sources/dotLottieLoader/DotLottieFile.swift +++ b/Sources/dotLottieLoader/DotLottieFile.swift @@ -31,6 +31,15 @@ public struct DotLottieFile { return localUrl.appendingPathComponent(dotLottieJson) } + /// Animation for specified appearance + /// - Parameter appearance: appearance (dark/light/custom) + /// - Returns: URL to animation + public func animationURL(for appearance: DotLottieAppearanceType) -> URL? { + guard let animationId = manifest?.appearance?[appearance] else { return nil } + let dotLottieJson = "\(DotLottieFile.animationsFolderName)/\(animationId).json" + return localUrl.appendingPathComponent(dotLottieJson) + } + /// Animations folder url public var animationsUrl: URL { localUrl.appendingPathComponent("\(DotLottieFile.animationsFolderName)") @@ -111,7 +120,7 @@ public struct DotLottieFile { let animationData = try Data(contentsOf: url) try animationData.write(to: animationsDirectory.appendingPathComponent(fileName).appendingPathExtension("json")) - let processedAppearance = processsAppearance(forJsonLottieAt: url, appearances: appearances, fileName: fileName, animationsDirectory: animationsDirectory) + let processedAppearance = processAppearance(forJsonLottieAt: url, appearances: appearances, fileName: fileName, animationsDirectory: animationsDirectory) let manifest = DotLottieManifest(animations: [ DotLottieAnimation(loop: loop, themeColor: themeColor, speed: 1.0, id: fileName) @@ -132,8 +141,14 @@ public struct DotLottieFile { } } - - private static func processsAppearance(forJsonLottieAt jsonUrl: URL, appearances: DotLottieAppearance?, fileName: String, animationsDirectory: URL) -> DotLottieAppearance { + /// Process appearances for animation + /// - Parameters: + /// - jsonUrl: url of JSON lottie animation + /// - appearances: Array of alternative appearances (dark/light/custom) + /// - fileName: name of animation file + /// - animationsDirectory: directory of animations + /// - Returns: DotLottieAppearance + private static func processAppearance(forJsonLottieAt jsonUrl: URL, appearances: DotLottieAppearance?, fileName: String, animationsDirectory: URL) -> DotLottieAppearance { var dotLottieAppearance: DotLottieAppearance = [.light: fileName] appearances?.forEach({ From 6d4a3fd8c7f824fc8253b9d3322228cf5d376b3a Mon Sep 17 00:00:00 2001 From: Evandro Date: Thu, 24 Jun 2021 13:54:23 +0800 Subject: [PATCH 03/13] [CHORE] Moved dot lottie compression params to Configuration file --- DotLottieConfiguration.swift | 102 ++++++++++++++++++ Example/Pods/Pods.xcodeproj/project.pbxproj | 6 ++ Example/dotLottieLoader/ViewController.swift | 18 +--- Sources/dotLottieLoader/DotLottieFile.swift | 66 ++---------- Sources/dotLottieLoader/DotLottieLoader.swift | 13 ++- 5 files changed, 126 insertions(+), 79 deletions(-) create mode 100644 DotLottieConfiguration.swift diff --git a/DotLottieConfiguration.swift b/DotLottieConfiguration.swift new file mode 100644 index 0000000..3ea19e7 --- /dev/null +++ b/DotLottieConfiguration.swift @@ -0,0 +1,102 @@ +// +// DotLottieConfiguration.swift +// Pods +// +// Created by Evandro Harrison Hoffmann on 23/06/2021. +// + +import Foundation + +/// Configuration model +public struct DotLottieConfiguration { + /// URL to main animation JSON file + public var url: URL + + /// Loop enabled - Default true + public var loop: Bool = true + + /// Theme color in HEX - Default #ffffff + public var themeColor: String = "#ffffff" + + /// Array of alternative appearances (dark/light/custom) + public var appearances: DotLottieAppearance? + + /// URL to directory where we are saving the files + public var directory: URL = DotLottieUtils.tempDirectoryURL + + public init(animationUrl: URL) { + url = animationUrl + } + + var dotLottieDirectory: URL { + directory.appendingPathComponent(fileName) + } + + var animationsDirectory: URL { + dotLottieDirectory.appendingPathComponent("animations") + } + + var isLottie: Bool { + url.isJsonFile + } + + var fileName: String { + url.deletingPathExtension().lastPathComponent + } + + var animationUrl: URL { + animationsDirectory.appendingPathComponent(fileName).appendingPathExtension("json") + } + + var manifestUrl: URL { + dotLottieDirectory.appendingPathComponent("manifest").appendingPathExtension("json") + } + + var outputUrl: URL { + directory.appendingPathComponent(fileName).appendingPathExtension("lottie") + } + + /// Process appearances for animation + private var processedAppearance: DotLottieAppearance { + var dotLottieAppearance: DotLottieAppearance = [.light: fileName] + + appearances?.forEach({ + guard let url = URL(string: $0.value), url.isJsonFile else { + DotLottieUtils.log("Value for appearance \($0.key) is not a valid JSON URL") + return + } + + do { + let appearanceFileName = "\(fileName)-\($0.key.rawValue)" + let apperanceUrl = animationsDirectory.appendingPathComponent(appearanceFileName).appendingPathExtension("json") + let animationData = try Data(contentsOf: url) + try animationData.write(to: apperanceUrl) + + dotLottieAppearance[$0.key] = appearanceFileName + } catch { + DotLottieUtils.log("Could not process value for appearance: \($0.key)") + } + }) + + return dotLottieAppearance + } + + func createFolders() throws { + try FileManager.default.createDirectory(at: dotLottieDirectory, withIntermediateDirectories: true, attributes: nil) + try FileManager.default.createDirectory(at: animationsDirectory, withIntermediateDirectories: true, attributes: nil) + } + + func createAnimation() throws { + let animationData = try Data(contentsOf: url) + try animationData.write(to: animationUrl) + } + + func createManifest() throws { + let manifest = DotLottieManifest(animations: [ + DotLottieAnimation(loop: loop, themeColor: themeColor, speed: 1.0, id: fileName) + ], version: "1.0", author: "LottieFiles", generator: "LottieFiles dotLottieLoader-iOS 0.1.4", appearance: processedAppearance) + let manifestData = try manifest.encode() + try manifestData.write(to: manifestUrl) + } + +} diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 771b2ff..68f0228 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -32,6 +32,8 @@ 63636F2A3158789EF86C37967D99CE98 /* DotLottieUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC167FC21DEB21FA3EBFFF34E9BD1EC8 /* DotLottieUtils.swift */; }; 6ACEE2E7B99A4E1ADDDA21F9886DD833 /* ioapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 045E96CC34EEC8345457CEA214262ECE /* ioapi.h */; settings = {ATTRIBUTES = (Project, ); }; }; 6AD52FD945993536B98EE5A3C385608B /* zip.h in Headers */ = {isa = PBXBuildFile; fileRef = D798C1CF43C9E7BB81DFE49408335C1E /* zip.h */; settings = {ATTRIBUTES = (Project, ); }; }; + 6C9D0CDA2683540000BAA5A9 /* DotLottieConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C9D0CD92683540000BAA5A9 /* DotLottieConfiguration.swift */; }; + 6C9D0CDB2683540000BAA5A9 /* DotLottieConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C9D0CD92683540000BAA5A9 /* DotLottieConfiguration.swift */; }; 70F87507873628BCC20217481C8F1DFA /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 0DE99ECA8C10E925D64451BC9B2D8CB1 /* ioapi.c */; }; 72BBDC69E80CC91B382D7058D00DF634 /* dotLottieLoader-iOS-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A29D83E8A884C427D03E5D50AFA362E8 /* dotLottieLoader-iOS-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 76B42F2A73659CB866C43133F3276187 /* crypt.h in Headers */ = {isa = PBXBuildFile; fileRef = F68E17F98966D0A1C0F94B93EB282CA9 /* crypt.h */; settings = {ATTRIBUTES = (Project, ); }; }; @@ -152,6 +154,7 @@ 5EFF315BEE48371B60C5A5569A4BD29C /* Pods-dotLottieLoader_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-dotLottieLoader_Example-frameworks.sh"; sourceTree = ""; }; 6509E8C84824B4846ED72833CE18A1B5 /* DotLottieFile.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DotLottieFile.swift; path = Sources/dotLottieLoader/DotLottieFile.swift; sourceTree = ""; }; 68A086C42F5FF6DD7C896F9FE2BB81FC /* Pods-dotLottieLoader_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-dotLottieLoader_Example.debug.xcconfig"; sourceTree = ""; }; + 6C9D0CD92683540000BAA5A9 /* DotLottieConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotLottieConfiguration.swift; sourceTree = ""; }; 6F5BE91CF8B7927A645868E309E74793 /* Pods_dotLottieLoader_watchos_Extension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_dotLottieLoader_watchos_Extension.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 712A0E0C1C0C98A05E7D38560C8538B2 /* Pods_dotLottieLoader_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_dotLottieLoader_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 714C9CD9CD39C1F2ACEDB01DB3D0B5C7 /* dotLottieLoader-watchOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "dotLottieLoader-watchOS.release.xcconfig"; path = "../dotLottieLoader-watchOS/dotLottieLoader-watchOS.release.xcconfig"; sourceTree = ""; }; @@ -471,6 +474,7 @@ children = ( C1E12DEA275754C83548A211D728E45F /* DotLottieCache.swift */, 6509E8C84824B4846ED72833CE18A1B5 /* DotLottieFile.swift */, + 6C9D0CD92683540000BAA5A9 /* DotLottieConfiguration.swift */, 24568ACDD338DF0BBD5482C0192F9CD0 /* DotLottieLoader.swift */, C6997F0ACE9F49152C601C2E99294939 /* DotLottieManifest.swift */, BC167FC21DEB21FA3EBFFF34E9BD1EC8 /* DotLottieUtils.swift */, @@ -795,6 +799,7 @@ FF94A034FCBFE01E3AE764E289F7B1F2 /* dotLottieLoader-iOS-dummy.m in Sources */, 215752BC2C637FB4A5137BB85C41E6B7 /* DotLottieLoader.swift in Sources */, EB31105FC0B87C96CCB907262BF7AA93 /* DotLottieManifest.swift in Sources */, + 6C9D0CDA2683540000BAA5A9 /* DotLottieConfiguration.swift in Sources */, 305EFC8665461DE83A201F16349A7FFA /* DotLottieUtils.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -846,6 +851,7 @@ 5538832A75AC04F1B41F5D50C68A1789 /* dotLottieLoader-watchOS-dummy.m in Sources */, 8F569CB52C19EA06D6A9422A30B996A5 /* DotLottieLoader.swift in Sources */, C93F2D36F310D4A22571A9C1155DFA23 /* DotLottieManifest.swift in Sources */, + 6C9D0CDB2683540000BAA5A9 /* DotLottieConfiguration.swift in Sources */, 63636F2A3158789EF86C37967D99CE98 /* DotLottieUtils.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Example/dotLottieLoader/ViewController.swift b/Example/dotLottieLoader/ViewController.swift index 9014e51..4cbd10e 100644 --- a/Example/dotLottieLoader/ViewController.swift +++ b/Example/dotLottieLoader/ViewController.swift @@ -16,21 +16,11 @@ class ViewController: UIViewController { // Do any additional setup after loading the view, typically from a nib. DotLottieUtils.isLogEnabled = true -// DotLottieLoader.dotLottie(fromJsonLottieAt: URL(string: "https://assets7.lottiefiles.com/packages/lf20_6k4jsmai.json")!) { url in -// // file compressed into dotLottie -// guard let url = url else { return } -// DotLottieLoader.load(from: url) { dotLottieFile in -// // file decompressed from dotLottie -// guard let dotLottieFile = dotLottieFile else { -// print("invalid dotLottie file") -// return -// } -// print("dotLottieFile decompressed successfuly with \(dotLottieFile.animations.count) animation\(dotLottieFile.animations.count == 1 ? "" : "s")") -// } -// } - DotLottieLoader.dotLottie(fromJsonLottieAt: URL(string: "https://assets7.lottiefiles.com/private_files/lf30_p25uf33d.json")!, - appearances: [.dark: "https://assets8.lottiefiles.com/private_files/lf30_yiodtvs6.json"]) { url in + var configuration = DotLottieConfiguration(animationUrl: URL(string: "https://assets7.lottiefiles.com/private_files/lf30_p25uf33d.json")!) + configuration.appearances = [.dark: "https://assets8.lottiefiles.com/private_files/lf30_yiodtvs6.json"] + + DotLottieLoader.dotLottie(with: configuration) { url in // file compressed into dotLottie guard let url = url else { return } DotLottieLoader.load(from: url) { dotLottieFile in diff --git a/Sources/dotLottieLoader/DotLottieFile.swift b/Sources/dotLottieLoader/DotLottieFile.swift index dffc0d4..f033ca8 100644 --- a/Sources/dotLottieLoader/DotLottieFile.swift +++ b/Sources/dotLottieLoader/DotLottieFile.swift @@ -100,75 +100,25 @@ public struct DotLottieFile { /// Creates dotLottieFile from animation json /// - Parameters: - /// - url: url of JSON lottie animation - /// - appearances: Array of alternative appearances (dark/light/custom) - /// - directory: directory to save file - /// - loop: loop enabled - /// - themeColor: theme color + /// - configuration: configuration for DotLottie file /// - Returns: URL of .lottie file - static func compress(jsonLottieAt url: URL, appearances: DotLottieAppearance? = nil, in directory: URL = DotLottieUtils.tempDirectoryURL, loop: Bool = true, themeColor: String = "#ffffff") -> URL? { + static func compress(with configuration: DotLottieConfiguration) -> URL? { Zip.addCustomFileExtension(DotLottieUtils.dotLottieExtension) do { - let fileName = url.deletingPathExtension().lastPathComponent - let dotLottieDirectory = directory.appendingPathComponent(fileName) - try FileManager.default.createDirectory(at: dotLottieDirectory, withIntermediateDirectories: true, attributes: nil) + try configuration.createFolders() + try configuration.createAnimation() + try configuration.createManifest() - let animationsDirectory = dotLottieDirectory.appendingPathComponent("animations") - try FileManager.default.createDirectory(at: animationsDirectory, withIntermediateDirectories: true, attributes: nil) - - let animationData = try Data(contentsOf: url) - try animationData.write(to: animationsDirectory.appendingPathComponent(fileName).appendingPathExtension("json")) - - let processedAppearance = processAppearance(forJsonLottieAt: url, appearances: appearances, fileName: fileName, animationsDirectory: animationsDirectory) - - let manifest = DotLottieManifest(animations: [ - DotLottieAnimation(loop: loop, themeColor: themeColor, speed: 1.0, id: fileName) - ], version: "1.0", author: "LottieFiles", generator: "LottieFiles dotLottieLoader-iOS 0.1.4", appearance: processedAppearance) - let manifestUrl = dotLottieDirectory.appendingPathComponent("manifest").appendingPathExtension("json") - let manifestData = try manifest.encode() - try manifestData.write(to: manifestUrl) - - let dotLottieUrl = directory.appendingPathComponent(fileName).appendingPathExtension("lottie") - try Zip.zipFiles(paths: [animationsDirectory, manifestUrl], zipFilePath: dotLottieUrl, password: nil, compression: .DefaultCompression, progress: { progress in + try Zip.zipFiles(paths: [configuration.animationsDirectory, configuration.manifestUrl], zipFilePath: configuration.outputUrl, password: nil, compression: .DefaultCompression, progress: { progress in DotLottieUtils.log("Compressing dotLottie file: \(progress)") }) - return dotLottieUrl + return configuration.outputUrl } catch { DotLottieUtils.log("Extraction of dotLottie archive failed with error: \(error)") return nil } } - - /// Process appearances for animation - /// - Parameters: - /// - jsonUrl: url of JSON lottie animation - /// - appearances: Array of alternative appearances (dark/light/custom) - /// - fileName: name of animation file - /// - animationsDirectory: directory of animations - /// - Returns: DotLottieAppearance - private static func processAppearance(forJsonLottieAt jsonUrl: URL, appearances: DotLottieAppearance?, fileName: String, animationsDirectory: URL) -> DotLottieAppearance { - var dotLottieAppearance: DotLottieAppearance = [.light: fileName] - - appearances?.forEach({ - guard let url = URL(string: $0.value), url.isJsonFile else { - DotLottieUtils.log("Value for appearance \($0.key) is not a valid JSON URL") - return - } - - do { - let appearanceFileName = "\(fileName)-\($0.key.rawValue)" - let apperanceUrl = animationsDirectory.appendingPathComponent(appearanceFileName).appendingPathExtension("json") - let animationData = try Data(contentsOf: url) - try animationData.write(to: apperanceUrl) - - dotLottieAppearance[$0.key] = appearanceFileName - } catch { - DotLottieUtils.log("Could not process value for appearance: \($0.key)") - } - }) - - return dotLottieAppearance - } } + diff --git a/Sources/dotLottieLoader/DotLottieLoader.swift b/Sources/dotLottieLoader/DotLottieLoader.swift index b8904b8..46aee2f 100644 --- a/Sources/dotLottieLoader/DotLottieLoader.swift +++ b/Sources/dotLottieLoader/DotLottieLoader.swift @@ -84,18 +84,15 @@ public class DotLottieLoader { /// Creates .lottie file from a json animation /// - Parameters: - /// - jsonUrl: URL to JSON lottie animation - /// - appearances: Array of alternative appearances (dark/light/custom) - /// - loop: loop enabled - /// - themeColor: theme color in HEX + /// - configuration: configuration file /// - completion: URL to .lottie file - public static func dotLottie(fromJsonLottieAt jsonUrl: URL, appearances: DotLottieAppearance? = nil, loop: Bool = true, themeColor: String = "#ffffff", completion: @escaping (URL?) -> Void) { - guard jsonUrl.isJsonFile else { + public static func dotLottie(with configuration: DotLottieConfiguration, completion: @escaping (URL?) -> Void) { + guard configuration.isLottie else { DotLottieUtils.log("Not a json file") return } - guard let dotLottieUrl = DotLottieFile.compress(jsonLottieAt: jsonUrl, appearances: appearances, loop: loop, themeColor: themeColor) else { + guard let dotLottieUrl = DotLottieFile.compress(with: configuration) else { DotLottieUtils.log("Failed to create dotLottie file") completion(nil) return @@ -104,4 +101,6 @@ public class DotLottieLoader { DotLottieUtils.log("Created dotLottie file at \(dotLottieUrl.absoluteString)") completion(dotLottieUrl) } + + // DotLottieConfiguration } From 8ce13e33b5cdd9cf8f9a40846e5c82c759824684 Mon Sep 17 00:00:00 2001 From: Evandro Date: Mon, 28 Jun 2021 04:54:45 -0300 Subject: [PATCH 04/13] [FEAT] Reorganized theming and DotLottieCreator usage --- DotLottieConfiguration.swift | 102 ------------- DotLottieCreator.swift | 144 ++++++++++++++++++ Example/Pods/Pods.xcodeproj/project.pbxproj | 12 +- Example/dotLottieLoader/ViewController.swift | 41 ++--- README.md | 5 +- Sources/dotLottieLoader/DotLottieFile.swift | 29 +--- Sources/dotLottieLoader/DotLottieLoader.swift | 21 --- .../dotLottieLoader/DotLottieManifest.swift | 53 ++++++- 8 files changed, 223 insertions(+), 184 deletions(-) delete mode 100644 DotLottieConfiguration.swift create mode 100644 DotLottieCreator.swift diff --git a/DotLottieConfiguration.swift b/DotLottieConfiguration.swift deleted file mode 100644 index 3ea19e7..0000000 --- a/DotLottieConfiguration.swift +++ /dev/null @@ -1,102 +0,0 @@ -// -// DotLottieConfiguration.swift -// Pods -// -// Created by Evandro Harrison Hoffmann on 23/06/2021. -// - -import Foundation - -/// Configuration model -public struct DotLottieConfiguration { - /// URL to main animation JSON file - public var url: URL - - /// Loop enabled - Default true - public var loop: Bool = true - - /// Theme color in HEX - Default #ffffff - public var themeColor: String = "#ffffff" - - /// Array of alternative appearances (dark/light/custom) - public var appearances: DotLottieAppearance? - - /// URL to directory where we are saving the files - public var directory: URL = DotLottieUtils.tempDirectoryURL - - public init(animationUrl: URL) { - url = animationUrl - } - - var dotLottieDirectory: URL { - directory.appendingPathComponent(fileName) - } - - var animationsDirectory: URL { - dotLottieDirectory.appendingPathComponent("animations") - } - - var isLottie: Bool { - url.isJsonFile - } - - var fileName: String { - url.deletingPathExtension().lastPathComponent - } - - var animationUrl: URL { - animationsDirectory.appendingPathComponent(fileName).appendingPathExtension("json") - } - - var manifestUrl: URL { - dotLottieDirectory.appendingPathComponent("manifest").appendingPathExtension("json") - } - - var outputUrl: URL { - directory.appendingPathComponent(fileName).appendingPathExtension("lottie") - } - - /// Process appearances for animation - private var processedAppearance: DotLottieAppearance { - var dotLottieAppearance: DotLottieAppearance = [.light: fileName] - - appearances?.forEach({ - guard let url = URL(string: $0.value), url.isJsonFile else { - DotLottieUtils.log("Value for appearance \($0.key) is not a valid JSON URL") - return - } - - do { - let appearanceFileName = "\(fileName)-\($0.key.rawValue)" - let apperanceUrl = animationsDirectory.appendingPathComponent(appearanceFileName).appendingPathExtension("json") - let animationData = try Data(contentsOf: url) - try animationData.write(to: apperanceUrl) - - dotLottieAppearance[$0.key] = appearanceFileName - } catch { - DotLottieUtils.log("Could not process value for appearance: \($0.key)") - } - }) - - return dotLottieAppearance - } - - func createFolders() throws { - try FileManager.default.createDirectory(at: dotLottieDirectory, withIntermediateDirectories: true, attributes: nil) - try FileManager.default.createDirectory(at: animationsDirectory, withIntermediateDirectories: true, attributes: nil) - } - - func createAnimation() throws { - let animationData = try Data(contentsOf: url) - try animationData.write(to: animationUrl) - } - - func createManifest() throws { - let manifest = DotLottieManifest(animations: [ - DotLottieAnimation(loop: loop, themeColor: themeColor, speed: 1.0, id: fileName) - ], version: "1.0", author: "LottieFiles", generator: "LottieFiles dotLottieLoader-iOS 0.1.4", appearance: processedAppearance) - let manifestData = try manifest.encode() - try manifestData.write(to: manifestUrl) - } - -} diff --git a/DotLottieCreator.swift b/DotLottieCreator.swift new file mode 100644 index 0000000..4152adf --- /dev/null +++ b/DotLottieCreator.swift @@ -0,0 +1,144 @@ +// +// DotLottieConfiguration.swift +// Pods +// +// Created by Evandro Harrison Hoffmann on 23/06/2021. +// + +import Foundation +import Zip + +/// Configuration model +public struct DotLottieCreator { + /// URL to main animation JSON file + public var url: URL + + /// Loop enabled - Default true + public var loop: Bool = true + + /// Theme color in HEX - Default #ffffff + public var themeColor: String = "#ffffff" + + /// Array of alternative appearances (dark/light/custom) + public var themes: [DotLottieTheme]? + + /// URL to directory where we are saving the files + public var directory: URL = DotLottieUtils.tempDirectoryURL + + public init(animationUrl: URL) { + url = animationUrl + } + + /// directory for dotLottie + private var dotLottieDirectory: URL { + directory.appendingPathComponent(fileName) + } + + /// Animations directory + private var animationsDirectory: URL { + dotLottieDirectory.appendingPathComponent("animations") + } + + /// checks if is a lottie file + private var isLottie: Bool { + url.isJsonFile + } + + /// Filename + private var fileName: String { + url.deletingPathExtension().lastPathComponent + } + + /// URL for main animation + private var animationUrl: URL { + animationsDirectory.appendingPathComponent(fileName).appendingPathExtension("json") + } + + /// URL for manifest file + private var manifestUrl: URL { + dotLottieDirectory.appendingPathComponent("manifest").appendingPathExtension("json") + } + + /// URL for output + private var outputUrl: URL { + directory.appendingPathComponent(fileName).appendingPathExtension("lottie") + } + + /// Process appearances for animation + private var processedThemes: [DotLottieTheme] { + var dotLottieAppearance: [DotLottieThemeType: DotLottieTheme] = [.light: DotLottieTheme(.light, animation: fileName)] + + themes?.forEach({ + guard let url = URL(string: $0.animation), url.isJsonFile else { + DotLottieUtils.log("Value for theme \($0.theme) is not a valid JSON URL") + return + } + + do { + let fileName = url.deletingPathExtension().lastPathComponent + let appearanceFileName = "\(fileName)-\($0.theme.rawValue)" + let apperanceUrl = animationsDirectory.appendingPathComponent(appearanceFileName).appendingPathExtension("json") + let animationData = try Data(contentsOf: url) + try animationData.write(to: apperanceUrl) + + dotLottieAppearance[$0.theme] = DotLottieTheme($0.theme, animation: fileName, colors: $0.colors) + } catch { + DotLottieUtils.log("Could not process value for theme: \($0.theme)") + } + }) + + return dotLottieAppearance.map({ $0.value }) + } + + /// Creates folders File + /// - Throws: Error + private func createFolders() throws { + try FileManager.default.createDirectory(at: dotLottieDirectory, withIntermediateDirectories: true, attributes: nil) + try FileManager.default.createDirectory(at: animationsDirectory, withIntermediateDirectories: true, attributes: nil) + } + + /// Creates main animation File + /// - Throws: Error + private func createAnimation() throws { + let animationData = try Data(contentsOf: url) + try animationData.write(to: animationUrl) + } + + /// Creates manifest File + /// - Throws: Error + private func createManifest() throws { + let manifest = DotLottieManifest(animations: [ + DotLottieAnimation(loop: loop, themeColor: themeColor, speed: 1.0, id: fileName) + ], version: "1.0", author: "LottieFiles", generator: "LottieFiles dotLottieLoader-iOS 0.1.4", themes: processedThemes) + let manifestData = try manifest.encode() + try manifestData.write(to: manifestUrl) + } + + /// Creates dotLottieFile with given configurations + /// - Parameters: + /// - configuration: configuration for DotLottie file + /// - Returns: URL of .lottie file + public func create() -> URL? { + guard isLottie else { + DotLottieUtils.log("Not a json file") + return nil + } + + do { + try createFolders() + try createAnimation() + try createManifest() + + Zip.addCustomFileExtension(DotLottieUtils.dotLottieExtension) + try Zip.zipFiles(paths: [animationsDirectory, manifestUrl], zipFilePath: outputUrl, password: nil, compression: .DefaultCompression, progress: { progress in + DotLottieUtils.log("Compressing dotLottie file: \(progress)") + }) + + DotLottieUtils.log("Created dotLottie file at \(outputUrl)") + return outputUrl + } catch { + DotLottieUtils.log("Failed to create dotLottie file \(error)") + return nil + } + } +} diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 68f0228..a9951bc 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -32,8 +32,8 @@ 63636F2A3158789EF86C37967D99CE98 /* DotLottieUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC167FC21DEB21FA3EBFFF34E9BD1EC8 /* DotLottieUtils.swift */; }; 6ACEE2E7B99A4E1ADDDA21F9886DD833 /* ioapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 045E96CC34EEC8345457CEA214262ECE /* ioapi.h */; settings = {ATTRIBUTES = (Project, ); }; }; 6AD52FD945993536B98EE5A3C385608B /* zip.h in Headers */ = {isa = PBXBuildFile; fileRef = D798C1CF43C9E7BB81DFE49408335C1E /* zip.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 6C9D0CDA2683540000BAA5A9 /* DotLottieConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C9D0CD92683540000BAA5A9 /* DotLottieConfiguration.swift */; }; - 6C9D0CDB2683540000BAA5A9 /* DotLottieConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C9D0CD92683540000BAA5A9 /* DotLottieConfiguration.swift */; }; + 6C9D0CDA2683540000BAA5A9 /* DotLottieCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C9D0CD92683540000BAA5A9 /* DotLottieCreator.swift */; }; + 6C9D0CDB2683540000BAA5A9 /* DotLottieCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C9D0CD92683540000BAA5A9 /* DotLottieCreator.swift */; }; 70F87507873628BCC20217481C8F1DFA /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 0DE99ECA8C10E925D64451BC9B2D8CB1 /* ioapi.c */; }; 72BBDC69E80CC91B382D7058D00DF634 /* dotLottieLoader-iOS-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A29D83E8A884C427D03E5D50AFA362E8 /* dotLottieLoader-iOS-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 76B42F2A73659CB866C43133F3276187 /* crypt.h in Headers */ = {isa = PBXBuildFile; fileRef = F68E17F98966D0A1C0F94B93EB282CA9 /* crypt.h */; settings = {ATTRIBUTES = (Project, ); }; }; @@ -154,7 +154,7 @@ 5EFF315BEE48371B60C5A5569A4BD29C /* Pods-dotLottieLoader_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-dotLottieLoader_Example-frameworks.sh"; sourceTree = ""; }; 6509E8C84824B4846ED72833CE18A1B5 /* DotLottieFile.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DotLottieFile.swift; path = Sources/dotLottieLoader/DotLottieFile.swift; sourceTree = ""; }; 68A086C42F5FF6DD7C896F9FE2BB81FC /* Pods-dotLottieLoader_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-dotLottieLoader_Example.debug.xcconfig"; sourceTree = ""; }; - 6C9D0CD92683540000BAA5A9 /* DotLottieConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotLottieConfiguration.swift; sourceTree = ""; }; + 6C9D0CD92683540000BAA5A9 /* DotLottieCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotLottieCreator.swift; sourceTree = ""; }; 6F5BE91CF8B7927A645868E309E74793 /* Pods_dotLottieLoader_watchos_Extension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_dotLottieLoader_watchos_Extension.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 712A0E0C1C0C98A05E7D38560C8538B2 /* Pods_dotLottieLoader_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_dotLottieLoader_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 714C9CD9CD39C1F2ACEDB01DB3D0B5C7 /* dotLottieLoader-watchOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "dotLottieLoader-watchOS.release.xcconfig"; path = "../dotLottieLoader-watchOS/dotLottieLoader-watchOS.release.xcconfig"; sourceTree = ""; }; @@ -474,7 +474,7 @@ children = ( C1E12DEA275754C83548A211D728E45F /* DotLottieCache.swift */, 6509E8C84824B4846ED72833CE18A1B5 /* DotLottieFile.swift */, - 6C9D0CD92683540000BAA5A9 /* DotLottieConfiguration.swift */, + 6C9D0CD92683540000BAA5A9 /* DotLottieCreator.swift */, 24568ACDD338DF0BBD5482C0192F9CD0 /* DotLottieLoader.swift */, C6997F0ACE9F49152C601C2E99294939 /* DotLottieManifest.swift */, BC167FC21DEB21FA3EBFFF34E9BD1EC8 /* DotLottieUtils.swift */, @@ -799,7 +799,7 @@ FF94A034FCBFE01E3AE764E289F7B1F2 /* dotLottieLoader-iOS-dummy.m in Sources */, 215752BC2C637FB4A5137BB85C41E6B7 /* DotLottieLoader.swift in Sources */, EB31105FC0B87C96CCB907262BF7AA93 /* DotLottieManifest.swift in Sources */, - 6C9D0CDA2683540000BAA5A9 /* DotLottieConfiguration.swift in Sources */, + 6C9D0CDA2683540000BAA5A9 /* DotLottieCreator.swift in Sources */, 305EFC8665461DE83A201F16349A7FFA /* DotLottieUtils.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -851,7 +851,7 @@ 5538832A75AC04F1B41F5D50C68A1789 /* dotLottieLoader-watchOS-dummy.m in Sources */, 8F569CB52C19EA06D6A9422A30B996A5 /* DotLottieLoader.swift in Sources */, C93F2D36F310D4A22571A9C1155DFA23 /* DotLottieManifest.swift in Sources */, - 6C9D0CDB2683540000BAA5A9 /* DotLottieConfiguration.swift in Sources */, + 6C9D0CDB2683540000BAA5A9 /* DotLottieCreator.swift in Sources */, 63636F2A3158789EF86C37967D99CE98 /* DotLottieUtils.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Example/dotLottieLoader/ViewController.swift b/Example/dotLottieLoader/ViewController.swift index 4cbd10e..a7a0f71 100644 --- a/Example/dotLottieLoader/ViewController.swift +++ b/Example/dotLottieLoader/ViewController.swift @@ -17,28 +17,29 @@ class ViewController: UIViewController { DotLottieUtils.isLogEnabled = true - var configuration = DotLottieConfiguration(animationUrl: URL(string: "https://assets7.lottiefiles.com/private_files/lf30_p25uf33d.json")!) - configuration.appearances = [.dark: "https://assets8.lottiefiles.com/private_files/lf30_yiodtvs6.json"] + var creator = DotLottieCreator(animationUrl: URL(string: "https://assets7.lottiefiles.com/private_files/lf30_p25uf33d.json")!) +// configuration.appearances = [.dark: .layerColor([ +// DotLottieLayerColor(layer: "Love 2.Heart Outlines 2.Group 1.Stroke 1.Color", color: "#fafafa") +// ])] - DotLottieLoader.dotLottie(with: configuration) { url in - // file compressed into dotLottie - guard let url = url else { return } - DotLottieLoader.load(from: url) { dotLottieFile in - // file decompressed from dotLottie - guard let dotLottieFile = dotLottieFile else { - print("invalid dotLottie file") - return - } - - print(""" - dotLottieFile decompressed successfuly with: - - \(dotLottieFile.animations.count) animations - - \(dotLottieFile.images.count) images - - \(dotLottieFile.manifest?.appearance?.count ?? 0) appearances - - Light theme: \(dotLottieFile.animationURL(for: .light)?.absoluteString ?? "not defined") - - Dark theme: \(dotLottieFile.animationURL(for: .dark)?.absoluteString ?? "not defined") - """) + creator.themes = [DotLottieTheme(.dark, animation: "https://assets8.lottiefiles.com/private_files/lf30_yiodtvs6.json")] + + guard let url = creator.create() else { return } + DotLottieLoader.load(from: url) { dotLottieFile in + // file decompressed from dotLottie + guard let dotLottieFile = dotLottieFile else { + print("invalid dotLottie file") + return } + + print(""" + dotLottieFile decompressed successfuly with: + - \(dotLottieFile.animations.count) animations + - \(dotLottieFile.images.count) images + - \(dotLottieFile.manifest?.themes?.count ?? 0) appearances + - Light theme: \(dotLottieFile.animationURL(for: .light)?.absoluteString ?? "not defined") + - Dark theme: \(dotLottieFile.animationURL(for: .dark)?.absoluteString ?? "not defined") + """) } } diff --git a/README.md b/README.md index 8bc7f0d..9b872cc 100644 --- a/README.md +++ b/README.md @@ -77,9 +77,8 @@ DotLottieLoader.load(from: URL(string:"https://dotlottie.io/sample_files/animati ##### Creating .lottie file from JSON animation file ```swift -DotLottieLoader.dotLottie(fromJsonLottieAt: URL(string: "https://assets7.lottiefiles.com/packages/lf20_6k4jsmai.json")!) { dotLottieFileUrl in - // share or play `dotLottieFileUrl` using [DotLottie library](https://github.com/dotlottie/dotlottie-ios) -} +var creator = DotLottieCreator(animationUrl: URL(string: "https://assets7.lottiefiles.com/private_files/lf30_p25uf33d.json")!) +let urlToDotLottie = creator.create() ``` ## Author diff --git a/Sources/dotLottieLoader/DotLottieFile.swift b/Sources/dotLottieLoader/DotLottieFile.swift index f033ca8..39fab72 100644 --- a/Sources/dotLottieLoader/DotLottieFile.swift +++ b/Sources/dotLottieLoader/DotLottieFile.swift @@ -32,10 +32,10 @@ public struct DotLottieFile { } /// Animation for specified appearance - /// - Parameter appearance: appearance (dark/light/custom) + /// - Parameter theme: theme (dark/light/custom) /// - Returns: URL to animation - public func animationURL(for appearance: DotLottieAppearanceType) -> URL? { - guard let animationId = manifest?.appearance?[appearance] else { return nil } + public func animationURL(for theme: DotLottieThemeType) -> URL? { + guard let animationId = manifest?.themes?.first(where: { $0.theme == theme })?.animation else { return nil } let dotLottieJson = "\(DotLottieFile.animationsFolderName)/\(animationId).json" return localUrl.appendingPathComponent(dotLottieJson) } @@ -97,28 +97,5 @@ public struct DotLottieFile { return false } } - - /// Creates dotLottieFile from animation json - /// - Parameters: - /// - configuration: configuration for DotLottie file - /// - Returns: URL of .lottie file - static func compress(with configuration: DotLottieConfiguration) -> URL? { - Zip.addCustomFileExtension(DotLottieUtils.dotLottieExtension) - - do { - try configuration.createFolders() - try configuration.createAnimation() - try configuration.createManifest() - - try Zip.zipFiles(paths: [configuration.animationsDirectory, configuration.manifestUrl], zipFilePath: configuration.outputUrl, password: nil, compression: .DefaultCompression, progress: { progress in - DotLottieUtils.log("Compressing dotLottie file: \(progress)") - }) - - return configuration.outputUrl - } catch { - DotLottieUtils.log("Extraction of dotLottie archive failed with error: \(error)") - return nil - } - } } diff --git a/Sources/dotLottieLoader/DotLottieLoader.swift b/Sources/dotLottieLoader/DotLottieLoader.swift index 46aee2f..b810645 100644 --- a/Sources/dotLottieLoader/DotLottieLoader.swift +++ b/Sources/dotLottieLoader/DotLottieLoader.swift @@ -82,25 +82,4 @@ public class DotLottieLoader { }).resume() } - /// Creates .lottie file from a json animation - /// - Parameters: - /// - configuration: configuration file - /// - completion: URL to .lottie file - public static func dotLottie(with configuration: DotLottieConfiguration, completion: @escaping (URL?) -> Void) { - guard configuration.isLottie else { - DotLottieUtils.log("Not a json file") - return - } - - guard let dotLottieUrl = DotLottieFile.compress(with: configuration) else { - DotLottieUtils.log("Failed to create dotLottie file") - completion(nil) - return - } - - DotLottieUtils.log("Created dotLottie file at \(dotLottieUrl.absoluteString)") - completion(dotLottieUrl) - } - - // DotLottieConfiguration } diff --git a/Sources/dotLottieLoader/DotLottieManifest.swift b/Sources/dotLottieLoader/DotLottieManifest.swift index 57be7b9..5b1bc8e 100644 --- a/Sources/dotLottieLoader/DotLottieManifest.swift +++ b/Sources/dotLottieLoader/DotLottieManifest.swift @@ -14,7 +14,7 @@ public struct DotLottieManifest: Codable { public var version: String public var author: String public var generator: String - public var appearance: DotLottieAppearance? + public var themes: [DotLottieTheme]? /// Decodes data to Manifest model /// - Parameter data: Data to decode @@ -50,11 +50,52 @@ public struct DotLottieAnimation: Codable { public var id: String } -/// Theme model for .lottie File -public typealias DotLottieAppearance = [DotLottieAppearanceType: String] +/* + { + "animations":[ + {"id":"lf30_p25uf33d","speed":1,"loop":true,"themeColor":"#ffffff"} + ], + "author":"LottieFiles", + "generator":"LottieFiles dotLottieLoader-iOS 0.1.4", + "version":"1.0", + "themes":{ + "light": { + "animation": "lf30_p25uf33d", + "colorSettings": [ + { + "layer": ["Love 2", "Heart Outlines 2", "Group 1", "Stroke 1", "Color"], + "color": "#fafafa" + } + ] + } + } + } + */ + +public struct DotLottieTheme: Codable { + public var theme: DotLottieThemeType + public var animation: String + public var colors: [DotLottieColorConfiguration]? + + public init(_ theme: DotLottieThemeType, animation: String, colors: [DotLottieColorConfiguration]? = nil) { + self.theme = theme + self.animation = animation + self.colors = colors + } +} + +public struct DotLottieColorConfiguration: Codable { + public var layer: [String] + public var color: String + + public init(layer: [String], color: String) { + self.layer = layer + self.color = color + } +} -/// Type of Appearance -public enum DotLottieAppearanceType: RawRepresentable, Equatable, Hashable, Codable { +/// Type of Theme +public enum DotLottieThemeType: RawRepresentable, Equatable, Hashable, Codable { case dark case light case custom(String) @@ -77,7 +118,7 @@ public enum DotLottieAppearanceType: RawRepresentable, Equatable, Hashable, Coda } } - public static func == (lhs: DotLottieAppearanceType, rhs: DotLottieAppearanceType) -> Bool { + public static func == (lhs: DotLottieThemeType, rhs: DotLottieThemeType) -> Bool { lhs.rawValue == rhs.rawValue } From 5946089d6f728040f0a1f12976f6dfe1d0e067f1 Mon Sep 17 00:00:00 2001 From: Evandro Date: Mon, 28 Jun 2021 04:55:07 -0300 Subject: [PATCH 05/13] [CHORE] cleaned up test --- Example/dotLottieLoader/ViewController.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Example/dotLottieLoader/ViewController.swift b/Example/dotLottieLoader/ViewController.swift index a7a0f71..6aef0b5 100644 --- a/Example/dotLottieLoader/ViewController.swift +++ b/Example/dotLottieLoader/ViewController.swift @@ -18,11 +18,11 @@ class ViewController: UIViewController { DotLottieUtils.isLogEnabled = true var creator = DotLottieCreator(animationUrl: URL(string: "https://assets7.lottiefiles.com/private_files/lf30_p25uf33d.json")!) -// configuration.appearances = [.dark: .layerColor([ -// DotLottieLayerColor(layer: "Love 2.Heart Outlines 2.Group 1.Stroke 1.Color", color: "#fafafa") -// ])] - creator.themes = [DotLottieTheme(.dark, animation: "https://assets8.lottiefiles.com/private_files/lf30_yiodtvs6.json")] + creator.themes = [ + DotLottieTheme(.dark, animation: "https://assets8.lottiefiles.com/private_files/lf30_yiodtvs6.json"), + DotLottieTheme(.custom("alternative"), animation: "https://assets8.lottiefiles.com/private_files/lf30_yiodtvs6.json", colors: [.init(layer: ["Love 2", "Heart Outlines 2", "Group 1", "Stroke 1", "Color"], color: "#fafafa")]) + ] guard let url = creator.create() else { return } DotLottieLoader.load(from: url) { dotLottieFile in @@ -36,7 +36,7 @@ class ViewController: UIViewController { dotLottieFile decompressed successfuly with: - \(dotLottieFile.animations.count) animations - \(dotLottieFile.images.count) images - - \(dotLottieFile.manifest?.themes?.count ?? 0) appearances + - \(dotLottieFile.manifest?.themes?.count ?? 0) themes - Light theme: \(dotLottieFile.animationURL(for: .light)?.absoluteString ?? "not defined") - Dark theme: \(dotLottieFile.animationURL(for: .dark)?.absoluteString ?? "not defined") """) From 4998fc22ff2853ee68477e90932e696d0f3681d5 Mon Sep 17 00:00:00 2001 From: Evandro Date: Mon, 28 Jun 2021 09:02:05 -0300 Subject: [PATCH 06/13] [CHORE] Organized structure in files --- DotLottieAnimation.swift | 22 ++++++ DotLottieAppearance.swift | 25 +++++++ DotLottieColor.swift | 26 +++++++ DotLottieCreator.swift | 18 ++--- DotLottieTheme.swift | 40 +++++++++++ Example/Pods/Pods.xcodeproj/project.pbxproj | 24 +++++++ Example/dotLottieLoader/ViewController.swift | 12 ++-- Sources/dotLottieLoader/DotLottieFile.swift | 6 +- .../dotLottieLoader/DotLottieManifest.swift | 69 +------------------ 9 files changed, 158 insertions(+), 84 deletions(-) create mode 100644 DotLottieAnimation.swift create mode 100644 DotLottieAppearance.swift create mode 100644 DotLottieColor.swift create mode 100644 DotLottieTheme.swift diff --git a/DotLottieAnimation.swift b/DotLottieAnimation.swift new file mode 100644 index 0000000..70568fa --- /dev/null +++ b/DotLottieAnimation.swift @@ -0,0 +1,22 @@ +// +// DotLottieAnimation.swift +// Pods +// +// Created by Evandro Harrison Hoffmann on 28/06/2021. +// + +import Foundation + +public struct DotLottieAnimation: Codable { + /// Loop enabled + public var loop: Bool + + // appearance color in HEX + public var themeColor: String + + /// Animation Playback Speed + public var speed: Float + + /// Id of Animation + public var id: String +} diff --git a/DotLottieAppearance.swift b/DotLottieAppearance.swift new file mode 100644 index 0000000..729994a --- /dev/null +++ b/DotLottieAppearance.swift @@ -0,0 +1,25 @@ +// +// DotLottieAppearance.swift +// Pods +// +// Created by Evandro Harrison Hoffmann on 28/06/2021. +// + +import Foundation + +public struct DotLottieAppearance: Codable { + /// Theme - Dark/Light/Custom + public var theme: DotLottieTheme + + /// Animation name / url + public var animation: String + + /// Color configuration for custom settings + public var colors: [DotLottieColor]? + + public init(_ theme: DotLottieTheme, animation: String, colors: [DotLottieColor]? = nil) { + self.theme = theme + self.animation = animation + self.colors = colors + } +} diff --git a/DotLottieColor.swift b/DotLottieColor.swift new file mode 100644 index 0000000..d6d0328 --- /dev/null +++ b/DotLottieColor.swift @@ -0,0 +1,26 @@ +// +// DotLottieColor.swift +// Pods +// +// Created by Evandro Harrison Hoffmann on 28/06/2021. +// + +import Foundation + +public struct DotLottieColor: Codable { + /// Layer tree + public var layer: [String] + + /// Color in HEX + public var color: String + + public init(layer: [String], color: String) { + self.layer = layer + self.color = color + } + + /// Layer key path + public var layerKeyPath: String { + layer.joined(separator: ".") + } +} diff --git a/DotLottieCreator.swift b/DotLottieCreator.swift index 4152adf..b127eb8 100644 --- a/DotLottieCreator.swift +++ b/DotLottieCreator.swift @@ -16,11 +16,11 @@ public struct DotLottieCreator { /// Loop enabled - Default true public var loop: Bool = true - /// Theme color in HEX - Default #ffffff + /// appearance color in HEX - Default #ffffff public var themeColor: String = "#ffffff" /// Array of alternative appearances (dark/light/custom) - public var themes: [DotLottieTheme]? + public var appearance: [DotLottieAppearance]? /// URL to directory where we are saving the files public var directory: URL = DotLottieUtils.tempDirectoryURL @@ -65,12 +65,12 @@ public struct DotLottieCreator { } /// Process appearances for animation - private var processedThemes: [DotLottieTheme] { - var dotLottieAppearance: [DotLottieThemeType: DotLottieTheme] = [.light: DotLottieTheme(.light, animation: fileName)] + private var processedappearances: [DotLottieAppearance] { + var dotLottieAppearance: [DotLottieTheme: DotLottieAppearance] = [.light: DotLottieAppearance(.light, animation: fileName)] - themes?.forEach({ + appearance?.forEach({ guard let url = URL(string: $0.animation), url.isJsonFile else { - DotLottieUtils.log("Value for theme \($0.theme) is not a valid JSON URL") + DotLottieUtils.log("Value for appearance \($0.theme) is not a valid JSON URL") return } @@ -81,9 +81,9 @@ public struct DotLottieCreator { let animationData = try Data(contentsOf: url) try animationData.write(to: apperanceUrl) - dotLottieAppearance[$0.theme] = DotLottieTheme($0.theme, animation: fileName, colors: $0.colors) + dotLottieAppearance[$0.theme] = DotLottieAppearance($0.theme, animation: fileName, colors: $0.colors) } catch { - DotLottieUtils.log("Could not process value for theme: \($0.theme)") + DotLottieUtils.log("Could not process value for appearance: \($0.theme)") } }) @@ -109,7 +109,7 @@ public struct DotLottieCreator { private func createManifest() throws { let manifest = DotLottieManifest(animations: [ DotLottieAnimation(loop: loop, themeColor: themeColor, speed: 1.0, id: fileName) - ], version: "1.0", author: "LottieFiles", generator: "LottieFiles dotLottieLoader-iOS 0.1.4", themes: processedThemes) + ], version: "1.0", author: "LottieFiles", generator: "LottieFiles dotLottieLoader-iOS 0.1.4", appearance: processedappearances) let manifestData = try manifest.encode() try manifestData.write(to: manifestUrl) } diff --git a/DotLottieTheme.swift b/DotLottieTheme.swift new file mode 100644 index 0000000..3c5ad3d --- /dev/null +++ b/DotLottieTheme.swift @@ -0,0 +1,40 @@ +// +// DotLottieTheme.swift +// Pods +// +// Created by Evandro Harrison Hoffmann on 28/06/2021. +// + +import Foundation + +public enum DotLottieTheme: RawRepresentable, Equatable, Hashable, Codable { + case dark + case light + case custom(String) + + public typealias RawValue = String + + public init?(rawValue: RawValue) { + switch rawValue { + case "dark": self = .dark + case "light": self = .light + case (let value): self = .custom(value) + } + } + + public var rawValue: RawValue { + switch self { + case .dark: return "dark" + case .light: return "light" + case .custom(let value): return value + } + } + + public static func == (lhs: DotLottieTheme, rhs: DotLottieTheme) -> Bool { + lhs.rawValue == rhs.rawValue + } + + public var hashValue: Int { + rawValue.hashValue + } +} diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index a9951bc..bc9d06f 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -34,6 +34,14 @@ 6AD52FD945993536B98EE5A3C385608B /* zip.h in Headers */ = {isa = PBXBuildFile; fileRef = D798C1CF43C9E7BB81DFE49408335C1E /* zip.h */; settings = {ATTRIBUTES = (Project, ); }; }; 6C9D0CDA2683540000BAA5A9 /* DotLottieCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C9D0CD92683540000BAA5A9 /* DotLottieCreator.swift */; }; 6C9D0CDB2683540000BAA5A9 /* DotLottieCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C9D0CD92683540000BAA5A9 /* DotLottieCreator.swift */; }; + 6CD060522689EB4A00B8D25F /* DotLottieAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD060512689EB4A00B8D25F /* DotLottieAnimation.swift */; }; + 6CD060532689EB4A00B8D25F /* DotLottieAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD060512689EB4A00B8D25F /* DotLottieAnimation.swift */; }; + 6CD060552689EF4900B8D25F /* DotLottieTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD060542689EF4900B8D25F /* DotLottieTheme.swift */; }; + 6CD060562689EF4900B8D25F /* DotLottieTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD060542689EF4900B8D25F /* DotLottieTheme.swift */; }; + 6CD060582689EF6400B8D25F /* DotLottieAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD060572689EF6400B8D25F /* DotLottieAppearance.swift */; }; + 6CD060592689EF6400B8D25F /* DotLottieAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD060572689EF6400B8D25F /* DotLottieAppearance.swift */; }; + 6CD0605B2689F01C00B8D25F /* DotLottieColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0605A2689F01C00B8D25F /* DotLottieColor.swift */; }; + 6CD0605C2689F01C00B8D25F /* DotLottieColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0605A2689F01C00B8D25F /* DotLottieColor.swift */; }; 70F87507873628BCC20217481C8F1DFA /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 0DE99ECA8C10E925D64451BC9B2D8CB1 /* ioapi.c */; }; 72BBDC69E80CC91B382D7058D00DF634 /* dotLottieLoader-iOS-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A29D83E8A884C427D03E5D50AFA362E8 /* dotLottieLoader-iOS-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 76B42F2A73659CB866C43133F3276187 /* crypt.h in Headers */ = {isa = PBXBuildFile; fileRef = F68E17F98966D0A1C0F94B93EB282CA9 /* crypt.h */; settings = {ATTRIBUTES = (Project, ); }; }; @@ -155,6 +163,10 @@ 6509E8C84824B4846ED72833CE18A1B5 /* DotLottieFile.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DotLottieFile.swift; path = Sources/dotLottieLoader/DotLottieFile.swift; sourceTree = ""; }; 68A086C42F5FF6DD7C896F9FE2BB81FC /* Pods-dotLottieLoader_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-dotLottieLoader_Example.debug.xcconfig"; sourceTree = ""; }; 6C9D0CD92683540000BAA5A9 /* DotLottieCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotLottieCreator.swift; sourceTree = ""; }; + 6CD060512689EB4A00B8D25F /* DotLottieAnimation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotLottieAnimation.swift; sourceTree = ""; }; + 6CD060542689EF4900B8D25F /* DotLottieTheme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotLottieTheme.swift; sourceTree = ""; }; + 6CD060572689EF6400B8D25F /* DotLottieAppearance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotLottieAppearance.swift; sourceTree = ""; }; + 6CD0605A2689F01C00B8D25F /* DotLottieColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotLottieColor.swift; sourceTree = ""; }; 6F5BE91CF8B7927A645868E309E74793 /* Pods_dotLottieLoader_watchos_Extension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_dotLottieLoader_watchos_Extension.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 712A0E0C1C0C98A05E7D38560C8538B2 /* Pods_dotLottieLoader_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_dotLottieLoader_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 714C9CD9CD39C1F2ACEDB01DB3D0B5C7 /* dotLottieLoader-watchOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "dotLottieLoader-watchOS.release.xcconfig"; path = "../dotLottieLoader-watchOS/dotLottieLoader-watchOS.release.xcconfig"; sourceTree = ""; }; @@ -477,6 +489,10 @@ 6C9D0CD92683540000BAA5A9 /* DotLottieCreator.swift */, 24568ACDD338DF0BBD5482C0192F9CD0 /* DotLottieLoader.swift */, C6997F0ACE9F49152C601C2E99294939 /* DotLottieManifest.swift */, + 6CD060572689EF6400B8D25F /* DotLottieAppearance.swift */, + 6CD060542689EF4900B8D25F /* DotLottieTheme.swift */, + 6CD0605A2689F01C00B8D25F /* DotLottieColor.swift */, + 6CD060512689EB4A00B8D25F /* DotLottieAnimation.swift */, BC167FC21DEB21FA3EBFFF34E9BD1EC8 /* DotLottieUtils.swift */, 958A6E3898066CC5E34B027DB32AFA36 /* Pod */, 23BFF5E77379214D97EF8548574DA95F /* Support Files */, @@ -797,7 +813,11 @@ 08CF1BEC7460217FF073A951F6B222F8 /* DotLottieCache.swift in Sources */, 8C1802A2B62166C48DDCF18A961DB846 /* DotLottieFile.swift in Sources */, FF94A034FCBFE01E3AE764E289F7B1F2 /* dotLottieLoader-iOS-dummy.m in Sources */, + 6CD060552689EF4900B8D25F /* DotLottieTheme.swift in Sources */, + 6CD060522689EB4A00B8D25F /* DotLottieAnimation.swift in Sources */, + 6CD0605B2689F01C00B8D25F /* DotLottieColor.swift in Sources */, 215752BC2C637FB4A5137BB85C41E6B7 /* DotLottieLoader.swift in Sources */, + 6CD060582689EF6400B8D25F /* DotLottieAppearance.swift in Sources */, EB31105FC0B87C96CCB907262BF7AA93 /* DotLottieManifest.swift in Sources */, 6C9D0CDA2683540000BAA5A9 /* DotLottieCreator.swift in Sources */, 305EFC8665461DE83A201F16349A7FFA /* DotLottieUtils.swift in Sources */, @@ -849,7 +869,11 @@ AD90F83857D771BB0CEE486046EC04B2 /* DotLottieCache.swift in Sources */, BE834D2E5C60A1A5A5059829E241019A /* DotLottieFile.swift in Sources */, 5538832A75AC04F1B41F5D50C68A1789 /* dotLottieLoader-watchOS-dummy.m in Sources */, + 6CD060562689EF4900B8D25F /* DotLottieTheme.swift in Sources */, + 6CD060532689EB4A00B8D25F /* DotLottieAnimation.swift in Sources */, + 6CD0605C2689F01C00B8D25F /* DotLottieColor.swift in Sources */, 8F569CB52C19EA06D6A9422A30B996A5 /* DotLottieLoader.swift in Sources */, + 6CD060592689EF6400B8D25F /* DotLottieAppearance.swift in Sources */, C93F2D36F310D4A22571A9C1155DFA23 /* DotLottieManifest.swift in Sources */, 6C9D0CDB2683540000BAA5A9 /* DotLottieCreator.swift in Sources */, 63636F2A3158789EF86C37967D99CE98 /* DotLottieUtils.swift in Sources */, diff --git a/Example/dotLottieLoader/ViewController.swift b/Example/dotLottieLoader/ViewController.swift index 6aef0b5..7e1d09b 100644 --- a/Example/dotLottieLoader/ViewController.swift +++ b/Example/dotLottieLoader/ViewController.swift @@ -19,9 +19,9 @@ class ViewController: UIViewController { var creator = DotLottieCreator(animationUrl: URL(string: "https://assets7.lottiefiles.com/private_files/lf30_p25uf33d.json")!) - creator.themes = [ - DotLottieTheme(.dark, animation: "https://assets8.lottiefiles.com/private_files/lf30_yiodtvs6.json"), - DotLottieTheme(.custom("alternative"), animation: "https://assets8.lottiefiles.com/private_files/lf30_yiodtvs6.json", colors: [.init(layer: ["Love 2", "Heart Outlines 2", "Group 1", "Stroke 1", "Color"], color: "#fafafa")]) + creator.appearance = [ + .init(.dark, animation: "https://assets8.lottiefiles.com/private_files/lf30_yiodtvs6.json"), + .init(.custom("alternative"), animation: "https://assets8.lottiefiles.com/private_files/lf30_yiodtvs6.json", colors: [.init(layer: ["Love 2", "Heart Outlines 2", "Group 1", "Stroke 1", "Color"], color: "#fafafa")]) ] guard let url = creator.create() else { return } @@ -36,9 +36,9 @@ class ViewController: UIViewController { dotLottieFile decompressed successfuly with: - \(dotLottieFile.animations.count) animations - \(dotLottieFile.images.count) images - - \(dotLottieFile.manifest?.themes?.count ?? 0) themes - - Light theme: \(dotLottieFile.animationURL(for: .light)?.absoluteString ?? "not defined") - - Dark theme: \(dotLottieFile.animationURL(for: .dark)?.absoluteString ?? "not defined") + - \(dotLottieFile.manifest?.appearance?.count ?? 0) appearances + - Light appearance: \(dotLottieFile.animationURL(for: .light)?.absoluteString ?? "not defined") + - Dark appearance: \(dotLottieFile.animationURL(for: .dark)?.absoluteString ?? "not defined") """) } } diff --git a/Sources/dotLottieLoader/DotLottieFile.swift b/Sources/dotLottieLoader/DotLottieFile.swift index 39fab72..5d1bc85 100644 --- a/Sources/dotLottieLoader/DotLottieFile.swift +++ b/Sources/dotLottieLoader/DotLottieFile.swift @@ -31,11 +31,11 @@ public struct DotLottieFile { return localUrl.appendingPathComponent(dotLottieJson) } - /// Animation for specified appearance + /// Animation for specified theme /// - Parameter theme: theme (dark/light/custom) /// - Returns: URL to animation - public func animationURL(for theme: DotLottieThemeType) -> URL? { - guard let animationId = manifest?.themes?.first(where: { $0.theme == theme })?.animation else { return nil } + public func animationURL(for theme: DotLottieTheme) -> URL? { + guard let animationId = manifest?.appearance?.first(where: { $0.theme == theme })?.animation else { return nil } let dotLottieJson = "\(DotLottieFile.animationsFolderName)/\(animationId).json" return localUrl.appendingPathComponent(dotLottieJson) } diff --git a/Sources/dotLottieLoader/DotLottieManifest.swift b/Sources/dotLottieLoader/DotLottieManifest.swift index 5b1bc8e..54368b1 100644 --- a/Sources/dotLottieLoader/DotLottieManifest.swift +++ b/Sources/dotLottieLoader/DotLottieManifest.swift @@ -14,7 +14,7 @@ public struct DotLottieManifest: Codable { public var version: String public var author: String public var generator: String - public var themes: [DotLottieTheme]? + public var appearance: [DotLottieAppearance]? /// Decodes data to Manifest model /// - Parameter data: Data to decode @@ -42,14 +42,6 @@ public struct DotLottieManifest: Codable { } -/// Animation model for .lottie File -public struct DotLottieAnimation: Codable { - public var loop: Bool - public var themeColor: String - public var speed: Float - public var id: String -} - /* { "animations":[ @@ -58,10 +50,10 @@ public struct DotLottieAnimation: Codable { "author":"LottieFiles", "generator":"LottieFiles dotLottieLoader-iOS 0.1.4", "version":"1.0", - "themes":{ + "appearance":{ "light": { "animation": "lf30_p25uf33d", - "colorSettings": [ + "color": [ { "layer": ["Love 2", "Heart Outlines 2", "Group 1", "Stroke 1", "Color"], "color": "#fafafa" @@ -71,58 +63,3 @@ public struct DotLottieAnimation: Codable { } } */ - -public struct DotLottieTheme: Codable { - public var theme: DotLottieThemeType - public var animation: String - public var colors: [DotLottieColorConfiguration]? - - public init(_ theme: DotLottieThemeType, animation: String, colors: [DotLottieColorConfiguration]? = nil) { - self.theme = theme - self.animation = animation - self.colors = colors - } -} - -public struct DotLottieColorConfiguration: Codable { - public var layer: [String] - public var color: String - - public init(layer: [String], color: String) { - self.layer = layer - self.color = color - } -} - -/// Type of Theme -public enum DotLottieThemeType: RawRepresentable, Equatable, Hashable, Codable { - case dark - case light - case custom(String) - - public typealias RawValue = String - - public init?(rawValue: RawValue) { - switch rawValue { - case "dark": self = .dark - case "light": self = .light - case (let value): self = .custom(value) - } - } - - public var rawValue: RawValue { - switch self { - case .dark: return "dark" - case .light: return "light" - case .custom(let value): return value - } - } - - public static func == (lhs: DotLottieThemeType, rhs: DotLottieThemeType) -> Bool { - lhs.rawValue == rhs.rawValue - } - - public var hashValue: Int { - rawValue.hashValue - } -} From 0fffddb1811fcd896f8dc8ddc21f9e1de1fac211 Mon Sep 17 00:00:00 2001 From: Evandro Date: Mon, 28 Jun 2021 09:36:46 -0300 Subject: [PATCH 07/13] [CHORE] Put files in Source folder --- Example/Pods/Pods.xcodeproj/project.pbxproj | 60 +++++++++---------- .../dotLottieLoader/DotLottieAnimation.swift | 0 .../dotLottieLoader/DotLottieAppearance.swift | 0 .../dotLottieLoader/DotLottieColor.swift | 0 .../dotLottieLoader/DotLottieCreator.swift | 0 .../dotLottieLoader/DotLottieTheme.swift | 0 6 files changed, 30 insertions(+), 30 deletions(-) rename DotLottieAnimation.swift => Sources/dotLottieLoader/DotLottieAnimation.swift (100%) rename DotLottieAppearance.swift => Sources/dotLottieLoader/DotLottieAppearance.swift (100%) rename DotLottieColor.swift => Sources/dotLottieLoader/DotLottieColor.swift (100%) rename DotLottieCreator.swift => Sources/dotLottieLoader/DotLottieCreator.swift (100%) rename DotLottieTheme.swift => Sources/dotLottieLoader/DotLottieTheme.swift (100%) diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index bc9d06f..2380dfc 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -32,16 +32,16 @@ 63636F2A3158789EF86C37967D99CE98 /* DotLottieUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC167FC21DEB21FA3EBFFF34E9BD1EC8 /* DotLottieUtils.swift */; }; 6ACEE2E7B99A4E1ADDDA21F9886DD833 /* ioapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 045E96CC34EEC8345457CEA214262ECE /* ioapi.h */; settings = {ATTRIBUTES = (Project, ); }; }; 6AD52FD945993536B98EE5A3C385608B /* zip.h in Headers */ = {isa = PBXBuildFile; fileRef = D798C1CF43C9E7BB81DFE49408335C1E /* zip.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 6C9D0CDA2683540000BAA5A9 /* DotLottieCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C9D0CD92683540000BAA5A9 /* DotLottieCreator.swift */; }; - 6C9D0CDB2683540000BAA5A9 /* DotLottieCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C9D0CD92683540000BAA5A9 /* DotLottieCreator.swift */; }; - 6CD060522689EB4A00B8D25F /* DotLottieAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD060512689EB4A00B8D25F /* DotLottieAnimation.swift */; }; - 6CD060532689EB4A00B8D25F /* DotLottieAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD060512689EB4A00B8D25F /* DotLottieAnimation.swift */; }; - 6CD060552689EF4900B8D25F /* DotLottieTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD060542689EF4900B8D25F /* DotLottieTheme.swift */; }; - 6CD060562689EF4900B8D25F /* DotLottieTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD060542689EF4900B8D25F /* DotLottieTheme.swift */; }; - 6CD060582689EF6400B8D25F /* DotLottieAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD060572689EF6400B8D25F /* DotLottieAppearance.swift */; }; - 6CD060592689EF6400B8D25F /* DotLottieAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD060572689EF6400B8D25F /* DotLottieAppearance.swift */; }; - 6CD0605B2689F01C00B8D25F /* DotLottieColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0605A2689F01C00B8D25F /* DotLottieColor.swift */; }; - 6CD0605C2689F01C00B8D25F /* DotLottieColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0605A2689F01C00B8D25F /* DotLottieColor.swift */; }; + 6CD060622689F70900B8D25F /* DotLottieAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0605D2689F70800B8D25F /* DotLottieAppearance.swift */; }; + 6CD060632689F70900B8D25F /* DotLottieAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0605D2689F70800B8D25F /* DotLottieAppearance.swift */; }; + 6CD060642689F70900B8D25F /* DotLottieAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0605E2689F70800B8D25F /* DotLottieAnimation.swift */; }; + 6CD060652689F70900B8D25F /* DotLottieAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0605E2689F70800B8D25F /* DotLottieAnimation.swift */; }; + 6CD060662689F70900B8D25F /* DotLottieCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0605F2689F70800B8D25F /* DotLottieCreator.swift */; }; + 6CD060672689F70900B8D25F /* DotLottieCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0605F2689F70800B8D25F /* DotLottieCreator.swift */; }; + 6CD060682689F70900B8D25F /* DotLottieTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD060602689F70800B8D25F /* DotLottieTheme.swift */; }; + 6CD060692689F70900B8D25F /* DotLottieTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD060602689F70800B8D25F /* DotLottieTheme.swift */; }; + 6CD0606A2689F70900B8D25F /* DotLottieColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD060612689F70900B8D25F /* DotLottieColor.swift */; }; + 6CD0606B2689F70900B8D25F /* DotLottieColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD060612689F70900B8D25F /* DotLottieColor.swift */; }; 70F87507873628BCC20217481C8F1DFA /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 0DE99ECA8C10E925D64451BC9B2D8CB1 /* ioapi.c */; }; 72BBDC69E80CC91B382D7058D00DF634 /* dotLottieLoader-iOS-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A29D83E8A884C427D03E5D50AFA362E8 /* dotLottieLoader-iOS-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 76B42F2A73659CB866C43133F3276187 /* crypt.h in Headers */ = {isa = PBXBuildFile; fileRef = F68E17F98966D0A1C0F94B93EB282CA9 /* crypt.h */; settings = {ATTRIBUTES = (Project, ); }; }; @@ -162,11 +162,11 @@ 5EFF315BEE48371B60C5A5569A4BD29C /* Pods-dotLottieLoader_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-dotLottieLoader_Example-frameworks.sh"; sourceTree = ""; }; 6509E8C84824B4846ED72833CE18A1B5 /* DotLottieFile.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DotLottieFile.swift; path = Sources/dotLottieLoader/DotLottieFile.swift; sourceTree = ""; }; 68A086C42F5FF6DD7C896F9FE2BB81FC /* Pods-dotLottieLoader_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-dotLottieLoader_Example.debug.xcconfig"; sourceTree = ""; }; - 6C9D0CD92683540000BAA5A9 /* DotLottieCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotLottieCreator.swift; sourceTree = ""; }; - 6CD060512689EB4A00B8D25F /* DotLottieAnimation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotLottieAnimation.swift; sourceTree = ""; }; - 6CD060542689EF4900B8D25F /* DotLottieTheme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotLottieTheme.swift; sourceTree = ""; }; - 6CD060572689EF6400B8D25F /* DotLottieAppearance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotLottieAppearance.swift; sourceTree = ""; }; - 6CD0605A2689F01C00B8D25F /* DotLottieColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotLottieColor.swift; sourceTree = ""; }; + 6CD0605D2689F70800B8D25F /* DotLottieAppearance.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DotLottieAppearance.swift; path = Sources/dotLottieLoader/DotLottieAppearance.swift; sourceTree = ""; }; + 6CD0605E2689F70800B8D25F /* DotLottieAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DotLottieAnimation.swift; path = Sources/dotLottieLoader/DotLottieAnimation.swift; sourceTree = ""; }; + 6CD0605F2689F70800B8D25F /* DotLottieCreator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DotLottieCreator.swift; path = Sources/dotLottieLoader/DotLottieCreator.swift; sourceTree = ""; }; + 6CD060602689F70800B8D25F /* DotLottieTheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DotLottieTheme.swift; path = Sources/dotLottieLoader/DotLottieTheme.swift; sourceTree = ""; }; + 6CD060612689F70900B8D25F /* DotLottieColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DotLottieColor.swift; path = Sources/dotLottieLoader/DotLottieColor.swift; sourceTree = ""; }; 6F5BE91CF8B7927A645868E309E74793 /* Pods_dotLottieLoader_watchos_Extension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_dotLottieLoader_watchos_Extension.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 712A0E0C1C0C98A05E7D38560C8538B2 /* Pods_dotLottieLoader_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_dotLottieLoader_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 714C9CD9CD39C1F2ACEDB01DB3D0B5C7 /* dotLottieLoader-watchOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "dotLottieLoader-watchOS.release.xcconfig"; path = "../dotLottieLoader-watchOS/dotLottieLoader-watchOS.release.xcconfig"; sourceTree = ""; }; @@ -486,14 +486,14 @@ children = ( C1E12DEA275754C83548A211D728E45F /* DotLottieCache.swift */, 6509E8C84824B4846ED72833CE18A1B5 /* DotLottieFile.swift */, - 6C9D0CD92683540000BAA5A9 /* DotLottieCreator.swift */, 24568ACDD338DF0BBD5482C0192F9CD0 /* DotLottieLoader.swift */, C6997F0ACE9F49152C601C2E99294939 /* DotLottieManifest.swift */, - 6CD060572689EF6400B8D25F /* DotLottieAppearance.swift */, - 6CD060542689EF4900B8D25F /* DotLottieTheme.swift */, - 6CD0605A2689F01C00B8D25F /* DotLottieColor.swift */, - 6CD060512689EB4A00B8D25F /* DotLottieAnimation.swift */, BC167FC21DEB21FA3EBFFF34E9BD1EC8 /* DotLottieUtils.swift */, + 6CD0605E2689F70800B8D25F /* DotLottieAnimation.swift */, + 6CD0605D2689F70800B8D25F /* DotLottieAppearance.swift */, + 6CD060612689F70900B8D25F /* DotLottieColor.swift */, + 6CD0605F2689F70800B8D25F /* DotLottieCreator.swift */, + 6CD060602689F70800B8D25F /* DotLottieTheme.swift */, 958A6E3898066CC5E34B027DB32AFA36 /* Pod */, 23BFF5E77379214D97EF8548574DA95F /* Support Files */, ); @@ -812,15 +812,15 @@ files = ( 08CF1BEC7460217FF073A951F6B222F8 /* DotLottieCache.swift in Sources */, 8C1802A2B62166C48DDCF18A961DB846 /* DotLottieFile.swift in Sources */, + 6CD060682689F70900B8D25F /* DotLottieTheme.swift in Sources */, + 6CD060662689F70900B8D25F /* DotLottieCreator.swift in Sources */, FF94A034FCBFE01E3AE764E289F7B1F2 /* dotLottieLoader-iOS-dummy.m in Sources */, - 6CD060552689EF4900B8D25F /* DotLottieTheme.swift in Sources */, - 6CD060522689EB4A00B8D25F /* DotLottieAnimation.swift in Sources */, - 6CD0605B2689F01C00B8D25F /* DotLottieColor.swift in Sources */, + 6CD0606A2689F70900B8D25F /* DotLottieColor.swift in Sources */, + 6CD060642689F70900B8D25F /* DotLottieAnimation.swift in Sources */, 215752BC2C637FB4A5137BB85C41E6B7 /* DotLottieLoader.swift in Sources */, - 6CD060582689EF6400B8D25F /* DotLottieAppearance.swift in Sources */, EB31105FC0B87C96CCB907262BF7AA93 /* DotLottieManifest.swift in Sources */, - 6C9D0CDA2683540000BAA5A9 /* DotLottieCreator.swift in Sources */, 305EFC8665461DE83A201F16349A7FFA /* DotLottieUtils.swift in Sources */, + 6CD060622689F70900B8D25F /* DotLottieAppearance.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -868,15 +868,15 @@ files = ( AD90F83857D771BB0CEE486046EC04B2 /* DotLottieCache.swift in Sources */, BE834D2E5C60A1A5A5059829E241019A /* DotLottieFile.swift in Sources */, + 6CD060692689F70900B8D25F /* DotLottieTheme.swift in Sources */, + 6CD060672689F70900B8D25F /* DotLottieCreator.swift in Sources */, 5538832A75AC04F1B41F5D50C68A1789 /* dotLottieLoader-watchOS-dummy.m in Sources */, - 6CD060562689EF4900B8D25F /* DotLottieTheme.swift in Sources */, - 6CD060532689EB4A00B8D25F /* DotLottieAnimation.swift in Sources */, - 6CD0605C2689F01C00B8D25F /* DotLottieColor.swift in Sources */, + 6CD0606B2689F70900B8D25F /* DotLottieColor.swift in Sources */, + 6CD060652689F70900B8D25F /* DotLottieAnimation.swift in Sources */, 8F569CB52C19EA06D6A9422A30B996A5 /* DotLottieLoader.swift in Sources */, - 6CD060592689EF6400B8D25F /* DotLottieAppearance.swift in Sources */, C93F2D36F310D4A22571A9C1155DFA23 /* DotLottieManifest.swift in Sources */, - 6C9D0CDB2683540000BAA5A9 /* DotLottieCreator.swift in Sources */, 63636F2A3158789EF86C37967D99CE98 /* DotLottieUtils.swift in Sources */, + 6CD060632689F70900B8D25F /* DotLottieAppearance.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/DotLottieAnimation.swift b/Sources/dotLottieLoader/DotLottieAnimation.swift similarity index 100% rename from DotLottieAnimation.swift rename to Sources/dotLottieLoader/DotLottieAnimation.swift diff --git a/DotLottieAppearance.swift b/Sources/dotLottieLoader/DotLottieAppearance.swift similarity index 100% rename from DotLottieAppearance.swift rename to Sources/dotLottieLoader/DotLottieAppearance.swift diff --git a/DotLottieColor.swift b/Sources/dotLottieLoader/DotLottieColor.swift similarity index 100% rename from DotLottieColor.swift rename to Sources/dotLottieLoader/DotLottieColor.swift diff --git a/DotLottieCreator.swift b/Sources/dotLottieLoader/DotLottieCreator.swift similarity index 100% rename from DotLottieCreator.swift rename to Sources/dotLottieLoader/DotLottieCreator.swift diff --git a/DotLottieTheme.swift b/Sources/dotLottieLoader/DotLottieTheme.swift similarity index 100% rename from DotLottieTheme.swift rename to Sources/dotLottieLoader/DotLottieTheme.swift From 7010cb07db65f4d0dc80524a9e9c02a3f6cbb5ec Mon Sep 17 00:00:00 2001 From: Evandro Date: Mon, 28 Jun 2021 09:58:40 -0300 Subject: [PATCH 08/13] [FIX] Fixed path for appearance animations --- Example/dotLottieLoader/ViewController.swift | 1 + Sources/dotLottieLoader/DotLottieCreator.swift | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Example/dotLottieLoader/ViewController.swift b/Example/dotLottieLoader/ViewController.swift index 7e1d09b..f101c65 100644 --- a/Example/dotLottieLoader/ViewController.swift +++ b/Example/dotLottieLoader/ViewController.swift @@ -37,6 +37,7 @@ class ViewController: UIViewController { - \(dotLottieFile.animations.count) animations - \(dotLottieFile.images.count) images - \(dotLottieFile.manifest?.appearance?.count ?? 0) appearances + - Default animation: \(dotLottieFile.animationUrl?.absoluteString ?? "not defined") - Light appearance: \(dotLottieFile.animationURL(for: .light)?.absoluteString ?? "not defined") - Dark appearance: \(dotLottieFile.animationURL(for: .dark)?.absoluteString ?? "not defined") """) diff --git a/Sources/dotLottieLoader/DotLottieCreator.swift b/Sources/dotLottieLoader/DotLottieCreator.swift index b127eb8..279b1b8 100644 --- a/Sources/dotLottieLoader/DotLottieCreator.swift +++ b/Sources/dotLottieLoader/DotLottieCreator.swift @@ -75,9 +75,8 @@ public struct DotLottieCreator { } do { - let fileName = url.deletingPathExtension().lastPathComponent - let appearanceFileName = "\(fileName)-\($0.theme.rawValue)" - let apperanceUrl = animationsDirectory.appendingPathComponent(appearanceFileName).appendingPathExtension("json") + let fileName = "\(url.deletingPathExtension().lastPathComponent)-\($0.theme.rawValue)" + let apperanceUrl = animationsDirectory.appendingPathComponent(fileName).appendingPathExtension("json") let animationData = try Data(contentsOf: url) try animationData.write(to: apperanceUrl) From 70a52f7f03e08927a3b7adf0cc8185e0dd9ef7ee Mon Sep 17 00:00:00 2001 From: Evandro Date: Mon, 28 Jun 2021 14:50:05 -0300 Subject: [PATCH 09/13] [FEAT] Loads json files in async data tasks --- Example/dotLottieLoader/ViewController.swift | 34 ++--- README.md | 4 +- .../dotLottieLoader/DotLottieCreator.swift | 124 ++++++++++++------ Sources/dotLottieLoader/DotLottieLoader.swift | 1 - 4 files changed, 107 insertions(+), 56 deletions(-) diff --git a/Example/dotLottieLoader/ViewController.swift b/Example/dotLottieLoader/ViewController.swift index f101c65..e62afd0 100644 --- a/Example/dotLottieLoader/ViewController.swift +++ b/Example/dotLottieLoader/ViewController.swift @@ -24,23 +24,25 @@ class ViewController: UIViewController { .init(.custom("alternative"), animation: "https://assets8.lottiefiles.com/private_files/lf30_yiodtvs6.json", colors: [.init(layer: ["Love 2", "Heart Outlines 2", "Group 1", "Stroke 1", "Color"], color: "#fafafa")]) ] - guard let url = creator.create() else { return } - DotLottieLoader.load(from: url) { dotLottieFile in - // file decompressed from dotLottie - guard let dotLottieFile = dotLottieFile else { - print("invalid dotLottie file") - return + creator.create { url in + guard let url = url else { return } + DotLottieLoader.load(from: url) { dotLottieFile in + // file decompressed from dotLottie + guard let dotLottieFile = dotLottieFile else { + print("invalid dotLottie file") + return + } + + print(""" + dotLottieFile decompressed successfuly with: + - \(dotLottieFile.animations.count) animations + - \(dotLottieFile.images.count) images + - \(dotLottieFile.manifest?.appearance?.count ?? 0) appearances + - Default animation: \(dotLottieFile.animationUrl?.absoluteString ?? "not defined") + - Light appearance: \(dotLottieFile.animationURL(for: .light)?.absoluteString ?? "not defined") + - Dark appearance: \(dotLottieFile.animationURL(for: .dark)?.absoluteString ?? "not defined") + """) } - - print(""" - dotLottieFile decompressed successfuly with: - - \(dotLottieFile.animations.count) animations - - \(dotLottieFile.images.count) images - - \(dotLottieFile.manifest?.appearance?.count ?? 0) appearances - - Default animation: \(dotLottieFile.animationUrl?.absoluteString ?? "not defined") - - Light appearance: \(dotLottieFile.animationURL(for: .light)?.absoluteString ?? "not defined") - - Dark appearance: \(dotLottieFile.animationURL(for: .dark)?.absoluteString ?? "not defined") - """) } } diff --git a/README.md b/README.md index 9b872cc..7e59457 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,9 @@ DotLottieLoader.load(from: URL(string:"https://dotlottie.io/sample_files/animati ```swift var creator = DotLottieCreator(animationUrl: URL(string: "https://assets7.lottiefiles.com/private_files/lf30_p25uf33d.json")!) -let urlToDotLottie = creator.create() +creator.create { url in + // use url to dotLottie +} ``` ## Author diff --git a/Sources/dotLottieLoader/DotLottieCreator.swift b/Sources/dotLottieLoader/DotLottieCreator.swift index 279b1b8..4f57db1 100644 --- a/Sources/dotLottieLoader/DotLottieCreator.swift +++ b/Sources/dotLottieLoader/DotLottieCreator.swift @@ -65,28 +65,60 @@ public struct DotLottieCreator { } /// Process appearances for animation - private var processedappearances: [DotLottieAppearance] { - var dotLottieAppearance: [DotLottieTheme: DotLottieAppearance] = [.light: DotLottieAppearance(.light, animation: fileName)] + private func processAppearances(_ completion: @escaping ([DotLottieAppearance]) -> Void) { + var appearances: [DotLottieTheme: DotLottieAppearance] = [.light: DotLottieAppearance(.light, animation: fileName)] - appearance?.forEach({ - guard let url = URL(string: $0.animation), url.isJsonFile else { - DotLottieUtils.log("Value for appearance \($0.theme) is not a valid JSON URL") + let dispatchGroup = DispatchGroup() + + appearance?.forEach({ appearance in + guard let url = URL(string: appearance.animation), url.isJsonFile else { + DotLottieUtils.log("Value for theme \(appearance.theme) is not a valid JSON URL") return } - do { - let fileName = "\(url.deletingPathExtension().lastPathComponent)-\($0.theme.rawValue)" - let apperanceUrl = animationsDirectory.appendingPathComponent(fileName).appendingPathExtension("json") - let animationData = try Data(contentsOf: url) - try animationData.write(to: apperanceUrl) - - dotLottieAppearance[$0.theme] = DotLottieAppearance($0.theme, animation: fileName, colors: $0.colors) - } catch { - DotLottieUtils.log("Could not process value for appearance: \($0.theme)") + let fileName = "\(url.deletingPathExtension().lastPathComponent)-\(appearance.theme.rawValue)" + let apperanceUrl = animationsDirectory.appendingPathComponent(fileName).appendingPathExtension("json") + + dispatchGroup.enter() + Self.download(from: url, to: apperanceUrl) { localUrl in + appearances[appearance.theme] = DotLottieAppearance(appearance.theme, animation: fileName, colors: appearance.colors) + dispatchGroup.leave() } }) - return dotLottieAppearance.map({ $0.value }) + dispatchGroup.notify(queue: .main) { + completion(appearances.map({ $0.value })) + } + } + + /// Downloads file from URL and returns local URL + /// - Parameters: + /// - url: Remote file URL + /// - saveUrl: Local file URL to persist + /// - completion: Local URL + private static func download(from url: URL, to saveUrl: URL, completion: @escaping (Bool) -> Void) { + // file is not remote, so just return + guard url.isRemoteFile else { + completion(true) + return + } + + DotLottieUtils.log("Downloading from url: \(url.path)") + URLSession.shared.dataTask(with: url, completionHandler: { data, response, error in + guard let data = data else { + DotLottieUtils.log("Failed to download data: \(error?.localizedDescription ?? "no description")") + completion(false) + return + } + + do { + try data.write(to: saveUrl) + completion(true) + } catch { + DotLottieUtils.log("Failed to save downloaded data: \(error.localizedDescription)") + completion(false) + } + }).resume() } /// Creates folders File @@ -97,47 +129,63 @@ public struct DotLottieCreator { } /// Creates main animation File - /// - Throws: Error - private func createAnimation() throws { - let animationData = try Data(contentsOf: url) - try animationData.write(to: animationUrl) + private func createAnimation(completion: @escaping (Bool) -> Void) { + Self.download(from: url, to: animationUrl, completion: completion) } /// Creates manifest File /// - Throws: Error - private func createManifest() throws { - let manifest = DotLottieManifest(animations: [ - DotLottieAnimation(loop: loop, themeColor: themeColor, speed: 1.0, id: fileName) - ], version: "1.0", author: "LottieFiles", generator: "LottieFiles dotLottieLoader-iOS 0.1.4", appearance: processedappearances) - let manifestData = try manifest.encode() - try manifestData.write(to: manifestUrl) + private func createManifest(completed: @escaping (Bool) -> Void) { + processAppearances { processedAppearances in + let manifest = DotLottieManifest(animations: [ + DotLottieAnimation(loop: loop, themeColor: themeColor, speed: 1.0, id: fileName) + ], version: "1.0", author: "LottieFiles", generator: "LottieFiles dotLottieLoader-iOS 0.1.4", appearance: processedAppearances) + + do { + let manifestData = try manifest.encode() + try manifestData.write(to: manifestUrl) + completed(true) + } catch { + completed(false) + } + } } /// Creates dotLottieFile with given configurations /// - Parameters: /// - configuration: configuration for DotLottie file /// - Returns: URL of .lottie file - public func create() -> URL? { + public func create(completion: @escaping (URL?) -> Void) { guard isLottie else { DotLottieUtils.log("Not a json file") - return nil + completion(nil) + return } do { try createFolders() - try createAnimation() - try createManifest() - - Zip.addCustomFileExtension(DotLottieUtils.dotLottieExtension) - try Zip.zipFiles(paths: [animationsDirectory, manifestUrl], zipFilePath: outputUrl, password: nil, compression: .DefaultCompression, progress: { progress in - DotLottieUtils.log("Compressing dotLottie file: \(progress)") - }) - - DotLottieUtils.log("Created dotLottie file at \(outputUrl)") - return outputUrl + createAnimation { success in + guard success else { return } + + createManifest { success in + guard success else { return } + + do { + Zip.addCustomFileExtension(DotLottieUtils.dotLottieExtension) + try Zip.zipFiles(paths: [animationsDirectory, manifestUrl], zipFilePath: outputUrl, password: nil, compression: .DefaultCompression, progress: { progress in + DotLottieUtils.log("Compressing dotLottie file: \(progress)") + }) + + DotLottieUtils.log("Created dotLottie file at \(outputUrl)") + completion(outputUrl) + } catch { + completion(nil) + } + } + } } catch { DotLottieUtils.log("Failed to create dotLottie file \(error)") - return nil + completion(nil) } } } diff --git a/Sources/dotLottieLoader/DotLottieLoader.swift b/Sources/dotLottieLoader/DotLottieLoader.swift index b810645..bf7a3af 100644 --- a/Sources/dotLottieLoader/DotLottieLoader.swift +++ b/Sources/dotLottieLoader/DotLottieLoader.swift @@ -81,5 +81,4 @@ public class DotLottieLoader { } }).resume() } - } From 3cac4065eff7e321a1b7e3826f5db9d2e08174ff Mon Sep 17 00:00:00 2001 From: Evandro Date: Tue, 6 Jul 2021 15:20:01 -0300 Subject: [PATCH 10/13] [CHORE] Allow decompressing on top of cache --- Sources/dotLottieLoader/DotLottieFile.swift | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Sources/dotLottieLoader/DotLottieFile.swift b/Sources/dotLottieLoader/DotLottieFile.swift index 5d1bc85..a4f3b8c 100644 --- a/Sources/dotLottieLoader/DotLottieFile.swift +++ b/Sources/dotLottieLoader/DotLottieFile.swift @@ -80,15 +80,9 @@ public struct DotLottieFile { /// - cache: Cache type /// - Returns: success true/false private func decompress(from url: URL, in directory: URL, cache: DotLottieCache) -> Bool { - guard cache.shouldDecompress(from: url) else { - DotLottieUtils.log("File already decompressed at \(directory.path)") - return true - } - - Zip.addCustomFileExtension(DotLottieUtils.dotLottieExtension) - do { try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true, attributes: nil) + Zip.addCustomFileExtension(DotLottieUtils.dotLottieExtension) try Zip.unzipFile(url, destination: directory, overwrite: true, password: nil) DotLottieUtils.log("File decompressed to \(directory.path)") return true From 4e988a66ee88ecb15067d2e517370ebc5d29a569 Mon Sep 17 00:00:00 2001 From: Leonardo Kaminski Ferreira Date: Mon, 18 Oct 2021 09:56:57 -0300 Subject: [PATCH 11/13] [FEAT] Add first test to local animations --- Sources/dotLottieLoader/DotLottieCreator.swift | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Sources/dotLottieLoader/DotLottieCreator.swift b/Sources/dotLottieLoader/DotLottieCreator.swift index 4f57db1..71529d1 100644 --- a/Sources/dotLottieLoader/DotLottieCreator.swift +++ b/Sources/dotLottieLoader/DotLottieCreator.swift @@ -99,8 +99,16 @@ public struct DotLottieCreator { private static func download(from url: URL, to saveUrl: URL, completion: @escaping (Bool) -> Void) { // file is not remote, so just return guard url.isRemoteFile else { - completion(true) - return + let animationData = try? Data(contentsOf: url) + do { + try animationData?.write(to: saveUrl) + completion(true) + return + } catch { + DotLottieUtils.log("Failed to save downloaded data: \(error.localizedDescription)") + completion(false) + return + } } DotLottieUtils.log("Downloading from url: \(url.path)") From f37879154909207f18b5169a963600abe6995818 Mon Sep 17 00:00:00 2001 From: Leonardo Kaminski Ferreira Date: Mon, 18 Oct 2021 10:05:44 -0300 Subject: [PATCH 12/13] [DOCS] Update documentation --- Sources/dotLottieLoader/DotLottieCreator.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/dotLottieLoader/DotLottieCreator.swift b/Sources/dotLottieLoader/DotLottieCreator.swift index 71529d1..35b5e19 100644 --- a/Sources/dotLottieLoader/DotLottieCreator.swift +++ b/Sources/dotLottieLoader/DotLottieCreator.swift @@ -97,7 +97,7 @@ public struct DotLottieCreator { /// - saveUrl: Local file URL to persist /// - completion: Local URL private static func download(from url: URL, to saveUrl: URL, completion: @escaping (Bool) -> Void) { - // file is not remote, so just return + /// file is not remote, save the animation content to the proper same URL and return guard url.isRemoteFile else { let animationData = try? Data(contentsOf: url) do { @@ -105,7 +105,7 @@ public struct DotLottieCreator { completion(true) return } catch { - DotLottieUtils.log("Failed to save downloaded data: \(error.localizedDescription)") + DotLottieUtils.log("Failed to save animation data: \(error.localizedDescription)") completion(false) return } From 839e6c918bdf389c1f207c65d9faf03637908483 Mon Sep 17 00:00:00 2001 From: Evandro Date: Wed, 20 Oct 2021 08:54:38 +0800 Subject: [PATCH 13/13] [CHORE] Removed Themes and appearance configuration --- Example/Pods/Pods.xcodeproj/project.pbxproj | 12 ----- Example/dotLottieLoader/ViewController.swift | 10 +--- .../dotLottieLoader/DotLottieAppearance.swift | 25 --------- .../dotLottieLoader/DotLottieCreator.swift | 52 ++++--------------- Sources/dotLottieLoader/DotLottieFile.swift | 9 ---- .../dotLottieLoader/DotLottieManifest.swift | 14 +---- Sources/dotLottieLoader/DotLottieTheme.swift | 40 -------------- 7 files changed, 12 insertions(+), 150 deletions(-) delete mode 100644 Sources/dotLottieLoader/DotLottieAppearance.swift delete mode 100644 Sources/dotLottieLoader/DotLottieTheme.swift diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 2380dfc..c3fed50 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -32,14 +32,10 @@ 63636F2A3158789EF86C37967D99CE98 /* DotLottieUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC167FC21DEB21FA3EBFFF34E9BD1EC8 /* DotLottieUtils.swift */; }; 6ACEE2E7B99A4E1ADDDA21F9886DD833 /* ioapi.h in Headers */ = {isa = PBXBuildFile; fileRef = 045E96CC34EEC8345457CEA214262ECE /* ioapi.h */; settings = {ATTRIBUTES = (Project, ); }; }; 6AD52FD945993536B98EE5A3C385608B /* zip.h in Headers */ = {isa = PBXBuildFile; fileRef = D798C1CF43C9E7BB81DFE49408335C1E /* zip.h */; settings = {ATTRIBUTES = (Project, ); }; }; - 6CD060622689F70900B8D25F /* DotLottieAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0605D2689F70800B8D25F /* DotLottieAppearance.swift */; }; - 6CD060632689F70900B8D25F /* DotLottieAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0605D2689F70800B8D25F /* DotLottieAppearance.swift */; }; 6CD060642689F70900B8D25F /* DotLottieAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0605E2689F70800B8D25F /* DotLottieAnimation.swift */; }; 6CD060652689F70900B8D25F /* DotLottieAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0605E2689F70800B8D25F /* DotLottieAnimation.swift */; }; 6CD060662689F70900B8D25F /* DotLottieCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0605F2689F70800B8D25F /* DotLottieCreator.swift */; }; 6CD060672689F70900B8D25F /* DotLottieCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD0605F2689F70800B8D25F /* DotLottieCreator.swift */; }; - 6CD060682689F70900B8D25F /* DotLottieTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD060602689F70800B8D25F /* DotLottieTheme.swift */; }; - 6CD060692689F70900B8D25F /* DotLottieTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD060602689F70800B8D25F /* DotLottieTheme.swift */; }; 6CD0606A2689F70900B8D25F /* DotLottieColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD060612689F70900B8D25F /* DotLottieColor.swift */; }; 6CD0606B2689F70900B8D25F /* DotLottieColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CD060612689F70900B8D25F /* DotLottieColor.swift */; }; 70F87507873628BCC20217481C8F1DFA /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 0DE99ECA8C10E925D64451BC9B2D8CB1 /* ioapi.c */; }; @@ -162,10 +158,8 @@ 5EFF315BEE48371B60C5A5569A4BD29C /* Pods-dotLottieLoader_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-dotLottieLoader_Example-frameworks.sh"; sourceTree = ""; }; 6509E8C84824B4846ED72833CE18A1B5 /* DotLottieFile.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DotLottieFile.swift; path = Sources/dotLottieLoader/DotLottieFile.swift; sourceTree = ""; }; 68A086C42F5FF6DD7C896F9FE2BB81FC /* Pods-dotLottieLoader_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-dotLottieLoader_Example.debug.xcconfig"; sourceTree = ""; }; - 6CD0605D2689F70800B8D25F /* DotLottieAppearance.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DotLottieAppearance.swift; path = Sources/dotLottieLoader/DotLottieAppearance.swift; sourceTree = ""; }; 6CD0605E2689F70800B8D25F /* DotLottieAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DotLottieAnimation.swift; path = Sources/dotLottieLoader/DotLottieAnimation.swift; sourceTree = ""; }; 6CD0605F2689F70800B8D25F /* DotLottieCreator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DotLottieCreator.swift; path = Sources/dotLottieLoader/DotLottieCreator.swift; sourceTree = ""; }; - 6CD060602689F70800B8D25F /* DotLottieTheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DotLottieTheme.swift; path = Sources/dotLottieLoader/DotLottieTheme.swift; sourceTree = ""; }; 6CD060612689F70900B8D25F /* DotLottieColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DotLottieColor.swift; path = Sources/dotLottieLoader/DotLottieColor.swift; sourceTree = ""; }; 6F5BE91CF8B7927A645868E309E74793 /* Pods_dotLottieLoader_watchos_Extension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_dotLottieLoader_watchos_Extension.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 712A0E0C1C0C98A05E7D38560C8538B2 /* Pods_dotLottieLoader_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_dotLottieLoader_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -490,10 +484,8 @@ C6997F0ACE9F49152C601C2E99294939 /* DotLottieManifest.swift */, BC167FC21DEB21FA3EBFFF34E9BD1EC8 /* DotLottieUtils.swift */, 6CD0605E2689F70800B8D25F /* DotLottieAnimation.swift */, - 6CD0605D2689F70800B8D25F /* DotLottieAppearance.swift */, 6CD060612689F70900B8D25F /* DotLottieColor.swift */, 6CD0605F2689F70800B8D25F /* DotLottieCreator.swift */, - 6CD060602689F70800B8D25F /* DotLottieTheme.swift */, 958A6E3898066CC5E34B027DB32AFA36 /* Pod */, 23BFF5E77379214D97EF8548574DA95F /* Support Files */, ); @@ -812,7 +804,6 @@ files = ( 08CF1BEC7460217FF073A951F6B222F8 /* DotLottieCache.swift in Sources */, 8C1802A2B62166C48DDCF18A961DB846 /* DotLottieFile.swift in Sources */, - 6CD060682689F70900B8D25F /* DotLottieTheme.swift in Sources */, 6CD060662689F70900B8D25F /* DotLottieCreator.swift in Sources */, FF94A034FCBFE01E3AE764E289F7B1F2 /* dotLottieLoader-iOS-dummy.m in Sources */, 6CD0606A2689F70900B8D25F /* DotLottieColor.swift in Sources */, @@ -820,7 +811,6 @@ 215752BC2C637FB4A5137BB85C41E6B7 /* DotLottieLoader.swift in Sources */, EB31105FC0B87C96CCB907262BF7AA93 /* DotLottieManifest.swift in Sources */, 305EFC8665461DE83A201F16349A7FFA /* DotLottieUtils.swift in Sources */, - 6CD060622689F70900B8D25F /* DotLottieAppearance.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -868,7 +858,6 @@ files = ( AD90F83857D771BB0CEE486046EC04B2 /* DotLottieCache.swift in Sources */, BE834D2E5C60A1A5A5059829E241019A /* DotLottieFile.swift in Sources */, - 6CD060692689F70900B8D25F /* DotLottieTheme.swift in Sources */, 6CD060672689F70900B8D25F /* DotLottieCreator.swift in Sources */, 5538832A75AC04F1B41F5D50C68A1789 /* dotLottieLoader-watchOS-dummy.m in Sources */, 6CD0606B2689F70900B8D25F /* DotLottieColor.swift in Sources */, @@ -876,7 +865,6 @@ 8F569CB52C19EA06D6A9422A30B996A5 /* DotLottieLoader.swift in Sources */, C93F2D36F310D4A22571A9C1155DFA23 /* DotLottieManifest.swift in Sources */, 63636F2A3158789EF86C37967D99CE98 /* DotLottieUtils.swift in Sources */, - 6CD060632689F70900B8D25F /* DotLottieAppearance.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Example/dotLottieLoader/ViewController.swift b/Example/dotLottieLoader/ViewController.swift index e62afd0..cad2cf5 100644 --- a/Example/dotLottieLoader/ViewController.swift +++ b/Example/dotLottieLoader/ViewController.swift @@ -17,12 +17,7 @@ class ViewController: UIViewController { DotLottieUtils.isLogEnabled = true - var creator = DotLottieCreator(animationUrl: URL(string: "https://assets7.lottiefiles.com/private_files/lf30_p25uf33d.json")!) - - creator.appearance = [ - .init(.dark, animation: "https://assets8.lottiefiles.com/private_files/lf30_yiodtvs6.json"), - .init(.custom("alternative"), animation: "https://assets8.lottiefiles.com/private_files/lf30_yiodtvs6.json", colors: [.init(layer: ["Love 2", "Heart Outlines 2", "Group 1", "Stroke 1", "Color"], color: "#fafafa")]) - ] + let creator = DotLottieCreator(animationUrl: URL(string: "https://assets7.lottiefiles.com/private_files/lf30_p25uf33d.json")!) creator.create { url in guard let url = url else { return } @@ -37,10 +32,7 @@ class ViewController: UIViewController { dotLottieFile decompressed successfuly with: - \(dotLottieFile.animations.count) animations - \(dotLottieFile.images.count) images - - \(dotLottieFile.manifest?.appearance?.count ?? 0) appearances - Default animation: \(dotLottieFile.animationUrl?.absoluteString ?? "not defined") - - Light appearance: \(dotLottieFile.animationURL(for: .light)?.absoluteString ?? "not defined") - - Dark appearance: \(dotLottieFile.animationURL(for: .dark)?.absoluteString ?? "not defined") """) } } diff --git a/Sources/dotLottieLoader/DotLottieAppearance.swift b/Sources/dotLottieLoader/DotLottieAppearance.swift deleted file mode 100644 index 729994a..0000000 --- a/Sources/dotLottieLoader/DotLottieAppearance.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// DotLottieAppearance.swift -// Pods -// -// Created by Evandro Harrison Hoffmann on 28/06/2021. -// - -import Foundation - -public struct DotLottieAppearance: Codable { - /// Theme - Dark/Light/Custom - public var theme: DotLottieTheme - - /// Animation name / url - public var animation: String - - /// Color configuration for custom settings - public var colors: [DotLottieColor]? - - public init(_ theme: DotLottieTheme, animation: String, colors: [DotLottieColor]? = nil) { - self.theme = theme - self.animation = animation - self.colors = colors - } -} diff --git a/Sources/dotLottieLoader/DotLottieCreator.swift b/Sources/dotLottieLoader/DotLottieCreator.swift index 35b5e19..3d50345 100644 --- a/Sources/dotLottieLoader/DotLottieCreator.swift +++ b/Sources/dotLottieLoader/DotLottieCreator.swift @@ -18,9 +18,6 @@ public struct DotLottieCreator { /// appearance color in HEX - Default #ffffff public var themeColor: String = "#ffffff" - - /// Array of alternative appearances (dark/light/custom) - public var appearance: [DotLottieAppearance]? /// URL to directory where we are saving the files public var directory: URL = DotLottieUtils.tempDirectoryURL @@ -64,33 +61,6 @@ public struct DotLottieCreator { directory.appendingPathComponent(fileName).appendingPathExtension("lottie") } - /// Process appearances for animation - private func processAppearances(_ completion: @escaping ([DotLottieAppearance]) -> Void) { - var appearances: [DotLottieTheme: DotLottieAppearance] = [.light: DotLottieAppearance(.light, animation: fileName)] - - let dispatchGroup = DispatchGroup() - - appearance?.forEach({ appearance in - guard let url = URL(string: appearance.animation), url.isJsonFile else { - DotLottieUtils.log("Value for theme \(appearance.theme) is not a valid JSON URL") - return - } - - let fileName = "\(url.deletingPathExtension().lastPathComponent)-\(appearance.theme.rawValue)" - let apperanceUrl = animationsDirectory.appendingPathComponent(fileName).appendingPathExtension("json") - - dispatchGroup.enter() - Self.download(from: url, to: apperanceUrl) { localUrl in - appearances[appearance.theme] = DotLottieAppearance(appearance.theme, animation: fileName, colors: appearance.colors) - dispatchGroup.leave() - } - }) - - dispatchGroup.notify(queue: .main) { - completion(appearances.map({ $0.value })) - } - } - /// Downloads file from URL and returns local URL /// - Parameters: /// - url: Remote file URL @@ -144,18 +114,16 @@ public struct DotLottieCreator { /// Creates manifest File /// - Throws: Error private func createManifest(completed: @escaping (Bool) -> Void) { - processAppearances { processedAppearances in - let manifest = DotLottieManifest(animations: [ - DotLottieAnimation(loop: loop, themeColor: themeColor, speed: 1.0, id: fileName) - ], version: "1.0", author: "LottieFiles", generator: "LottieFiles dotLottieLoader-iOS 0.1.4", appearance: processedAppearances) - - do { - let manifestData = try manifest.encode() - try manifestData.write(to: manifestUrl) - completed(true) - } catch { - completed(false) - } + let manifest = DotLottieManifest(animations: [ + DotLottieAnimation(loop: loop, themeColor: themeColor, speed: 1.0, id: fileName) + ], version: "1.0", author: "LottieFiles", generator: "LottieFiles dotLottieLoader-iOS 0.1.4") + + do { + let manifestData = try manifest.encode() + try manifestData.write(to: manifestUrl) + completed(true) + } catch { + completed(false) } } diff --git a/Sources/dotLottieLoader/DotLottieFile.swift b/Sources/dotLottieLoader/DotLottieFile.swift index a4f3b8c..53ac1b5 100644 --- a/Sources/dotLottieLoader/DotLottieFile.swift +++ b/Sources/dotLottieLoader/DotLottieFile.swift @@ -31,15 +31,6 @@ public struct DotLottieFile { return localUrl.appendingPathComponent(dotLottieJson) } - /// Animation for specified theme - /// - Parameter theme: theme (dark/light/custom) - /// - Returns: URL to animation - public func animationURL(for theme: DotLottieTheme) -> URL? { - guard let animationId = manifest?.appearance?.first(where: { $0.theme == theme })?.animation else { return nil } - let dotLottieJson = "\(DotLottieFile.animationsFolderName)/\(animationId).json" - return localUrl.appendingPathComponent(dotLottieJson) - } - /// Animations folder url public var animationsUrl: URL { localUrl.appendingPathComponent("\(DotLottieFile.animationsFolderName)") diff --git a/Sources/dotLottieLoader/DotLottieManifest.swift b/Sources/dotLottieLoader/DotLottieManifest.swift index 54368b1..1979503 100644 --- a/Sources/dotLottieLoader/DotLottieManifest.swift +++ b/Sources/dotLottieLoader/DotLottieManifest.swift @@ -14,7 +14,6 @@ public struct DotLottieManifest: Codable { public var version: String public var author: String public var generator: String - public var appearance: [DotLottieAppearance]? /// Decodes data to Manifest model /// - Parameter data: Data to decode @@ -49,17 +48,6 @@ public struct DotLottieManifest: Codable { ], "author":"LottieFiles", "generator":"LottieFiles dotLottieLoader-iOS 0.1.4", - "version":"1.0", - "appearance":{ - "light": { - "animation": "lf30_p25uf33d", - "color": [ - { - "layer": ["Love 2", "Heart Outlines 2", "Group 1", "Stroke 1", "Color"], - "color": "#fafafa" - } - ] - } - } + "version":"1.0" } */ diff --git a/Sources/dotLottieLoader/DotLottieTheme.swift b/Sources/dotLottieLoader/DotLottieTheme.swift deleted file mode 100644 index 3c5ad3d..0000000 --- a/Sources/dotLottieLoader/DotLottieTheme.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// DotLottieTheme.swift -// Pods -// -// Created by Evandro Harrison Hoffmann on 28/06/2021. -// - -import Foundation - -public enum DotLottieTheme: RawRepresentable, Equatable, Hashable, Codable { - case dark - case light - case custom(String) - - public typealias RawValue = String - - public init?(rawValue: RawValue) { - switch rawValue { - case "dark": self = .dark - case "light": self = .light - case (let value): self = .custom(value) - } - } - - public var rawValue: RawValue { - switch self { - case .dark: return "dark" - case .light: return "light" - case .custom(let value): return value - } - } - - public static func == (lhs: DotLottieTheme, rhs: DotLottieTheme) -> Bool { - lhs.rawValue == rhs.rawValue - } - - public var hashValue: Int { - rawValue.hashValue - } -}