Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Mergeable theme from multiple files with hot reloading #14

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Example/AppDelegate.swift
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

let url = URL(fileURLWithPath: #file).deletingLastPathComponent().appendingPathComponent("Style.yaml")
Stylist.shared.watch(url: url, animateChanges: true) { error in
let commonURL = URL(fileURLWithPath: #file).deletingLastPathComponent().appendingPathComponent("common.yml")
Stylist.shared.localMergeWatch(urls: [url, commonURL], animateChanges: true) { error in
print("Error loading theme:\n\(error)")
}

Expand Down
5 changes: 5 additions & 0 deletions Example/common.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
variables:
primaryColor: F000FF
styles:
largeFont:
font: title 1
4 changes: 4 additions & 0 deletions Stylist.xcodeproj/project.pbxproj
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
52D6D9871BEFF229002C0205 /* Stylist.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52D6D97C1BEFF229002C0205 /* Stylist.framework */; };
535BD3EF11C3878517DE35E8 /* Pods_Stylist_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C186A7E7F661536D838BB3A0 /* Pods_Stylist_iOS.framework */; };
5CC7AE9BC309934F44DC1CE1 /* Pods_Stylist_tvOS_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9245472812F659E9F0E1973B /* Pods_Stylist_tvOS_Tests.framework */; };
829ED8B321F0B85F00A572A2 /* common.yml in Resources */ = {isa = PBXBuildFile; fileRef = 829ED8B221F0B85F00A572A2 /* common.yml */; };
8933C7851EB5B820000D00A4 /* Stylist.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8933C7841EB5B820000D00A4 /* Stylist.swift */; };
8933C7881EB5B820000D00A4 /* Stylist.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8933C7841EB5B820000D00A4 /* Stylist.swift */; };
8933C78E1EB5B82C000D00A4 /* StylistTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8933C7891EB5B82A000D00A4 /* StylistTests.swift */; };
Expand Down Expand Up @@ -144,6 +145,7 @@
52D6D9F01BEFFFBE002C0205 /* Stylist.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Stylist.framework; sourceTree = BUILT_PRODUCTS_DIR; };
6E17AEA69B829DF29439909B /* Pods_Stylist_macOS_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Stylist_macOS_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
77B3C447D96463E91495C16D /* Pods-Stylist-tvOS Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Stylist-tvOS Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Stylist-tvOS Tests/Pods-Stylist-tvOS Tests.debug.xcconfig"; sourceTree = "<group>"; };
829ED8B221F0B85F00A572A2 /* common.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = common.yml; sourceTree = "<group>"; };
859CDAE0E43DE87EEAF810A4 /* Pods-Stylist-macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Stylist-macOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Stylist-macOS/Pods-Stylist-macOS.debug.xcconfig"; sourceTree = "<group>"; };
8933C7841EB5B820000D00A4 /* Stylist.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stylist.swift; sourceTree = "<group>"; };
8933C7891EB5B82A000D00A4 /* StylistTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StylistTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -371,6 +373,7 @@
CC68ECD01F47A1540063AE1F /* Style.yaml */,
CC0B571E20B568140022E84E /* SectionView.swift */,
CC8C104A20C4F1D1001E593B /* ExampleViewController.swift */,
829ED8B221F0B85F00A572A2 /* common.yml */,
);
path = Example;
sourceTree = "<group>";
Expand Down Expand Up @@ -592,6 +595,7 @@
CC23851B1F478E8A00FB0073 /* LaunchScreen.storyboard in Resources */,
CC2385181F478E8A00FB0073 /* Assets.xcassets in Resources */,
CC2385161F478E8A00FB0073 /* Main.storyboard in Resources */,
829ED8B321F0B85F00A572A2 /* common.yml in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Empty file modified Stylist.xcodeproj/project.xcworkspace/contents.xcworkspacedata
100644 → 100755
Empty file.
Empty file modified Stylist.xcodeproj/xcshareddata/xcschemes/Stylist-iOS.xcscheme
100644 → 100755
Empty file.
Empty file modified Stylist.xcodeproj/xcshareddata/xcschemes/Stylist-tvOS.xcscheme
100644 → 100755
Empty file.
49 changes: 49 additions & 0 deletions Stylist/Stylist.swift
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,55 @@ public class Stylist {
}
return fileWatcher
}

public func localMergeWatch(urls: [URL], animateChanges: Bool = true, parsingError: @escaping (ThemeError) -> Void) -> [FileWatcherProtocol] {
var fileWatchers = [FileWatcherProtocol]()

var hasLoaded = false
func updateThemes() {
let stylist = self
do {
let theme = try Theme(paths: urls.map { $0.path })
self.themes[urls.map { $0.path }.joined()] = theme
stylist.apply(theme: theme, animateChanges: animateChanges && hasLoaded)
hasLoaded = true
} catch let error as ThemeError {
parsingError(error)
} catch {
// unknown error occured
}
}

var fileUpdatedCount = 0
for url in urls {
let fileWatcher: FileWatcherProtocol
if url.isFileURL {
fileWatcher = FileWatcher.Local(path: url.path)
} else {
parsingError(ThemeError.remoteFileWatcherNotSupported)
break
}

do {
try fileWatcher.start { result in
switch result {
case .noChanges:
break
case .updated:
fileUpdatedCount += 1
if fileUpdatedCount >= urls.count {
updateThemes()
}
}
}
} catch {
parsingError(ThemeError.notFound)
}

fileWatchers.append(fileWatcher)
}
return fileWatchers
}
}

struct WeakContainer<T: AnyObject> {
Expand Down
27 changes: 27 additions & 0 deletions Stylist/Theme.swift
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,33 @@ extension Theme {
try self.init(data: data)
}

public init(paths: [String]) throws {

var mergedDictionary = ["variables": [:], "styles": [:]]

for path in paths {
guard let data = FileManager.default.contents(atPath: path) else {
throw ThemeError.notFound
}
guard let string = String(data: data, encoding: .utf8) else {
throw ThemeError.decodingError
}
let yaml = try Yams.load(yaml: string)
guard let dictionary = yaml as? [String: Any] else {
throw ThemeError.decodingError
}
let variables: [String: Any] = dictionary["variables"] as? [String: Any] ?? [:]
let stylesDictionary = (dictionary["styles"] as? [String: Any]) ?? [:]

mergedDictionary["variables"] = (mergedDictionary["variables"] as? [String: Any])?.merging(variables, uniquingKeysWith: { (current, _) in current }) ?? [:]

mergedDictionary["styles"] = (mergedDictionary["styles"] as? [String: Any])?.merging(stylesDictionary, uniquingKeysWith: { (current, _) in current }) ?? [:]

}

try self.init(dictionary: mergedDictionary)
}

public init(data: Data) throws {
guard let string = String(data: data, encoding: .utf8) else {
throw ThemeError.decodingError
Expand Down
1 change: 1 addition & 0 deletions Stylist/ThemeError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ public enum ThemeError: Error, Equatable {
case invalidSizeClass(name: String, sizeClass: String)
case invalidStyleContext(String)
case invalidStyleSelector(String)
case remoteFileWatcherNotSupported
}