diff --git a/Passepartout.xcodeproj/project.pbxproj b/Passepartout.xcodeproj/project.pbxproj index 318b0471..4f5e0e70 100644 --- a/Passepartout.xcodeproj/project.pbxproj +++ b/Passepartout.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 0E05C5DC20D198B9006EE732 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0E05C5DF20D198B9006EE732 /* Localizable.strings */; }; 0E05C5E420D1993C006EE732 /* SwiftGen+Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E05C5E320D1993C006EE732 /* SwiftGen+Strings.swift */; }; 0E05C61D20D27C82006EE732 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E05C61C20D27C82006EE732 /* Theme.swift */; }; + 0E0EABC821DF853C0069DAE7 /* Web in Resources */ = {isa = PBXBuildFile; fileRef = 0E0EABC721DF853C0069DAE7 /* Web */; }; 0E1066C920E0F84A004F98B7 /* Cells.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E1066C820E0F84A004F98B7 /* Cells.swift */; }; 0E158ADA20E11B0B00C85A82 /* EndpointViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E158AD920E11B0B00C85A82 /* EndpointViewController.swift */; }; 0E1D72B2213BFFCF00BA1586 /* ProviderPresetViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E1D72B1213BFFCF00BA1586 /* ProviderPresetViewController.swift */; }; @@ -47,7 +48,6 @@ 0E89DFC8213E8FC500741BA1 /* SessionProxy+Communication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E89DFC7213E8FC500741BA1 /* SessionProxy+Communication.swift */; }; 0E89DFCE213EEDFA00741BA1 /* WizardProviderViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E89DFCD213EEDFA00741BA1 /* WizardProviderViewController.swift */; }; 0E8D97E221388B52006FB4A0 /* InfrastructurePreset.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E8D97E121388B52006FB4A0 /* InfrastructurePreset.swift */; }; - 0E8D97E521389277006FB4A0 /* pia.json in Resources */ = {isa = PBXBuildFile; fileRef = 0E8D97E421389276006FB4A0 /* pia.json */; }; 0EA068F4218475F800C320AD /* ParsingResult+Alerts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA068F3218475F800C320AD /* ParsingResult+Alerts.swift */; }; 0EAAD71920E6669A0088754A /* GroupConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDE8DED20C93E4C004C739C /* GroupConstants.swift */; }; 0EB60FDA2111136E00AD27F3 /* UITextView+Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB60FD92111136E00AD27F3 /* UITextView+Search.swift */; }; @@ -134,6 +134,7 @@ 0E05C5E120D198D6006EE732 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/Main.storyboard; sourceTree = ""; }; 0E05C5E320D1993C006EE732 /* SwiftGen+Strings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SwiftGen+Strings.swift"; sourceTree = ""; }; 0E05C61C20D27C82006EE732 /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = ""; }; + 0E0EABC721DF853C0069DAE7 /* Web */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Web; sourceTree = ""; }; 0E1066C820E0F84A004F98B7 /* Cells.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cells.swift; sourceTree = ""; }; 0E158AD920E11B0B00C85A82 /* EndpointViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EndpointViewController.swift; sourceTree = ""; }; 0E1D72B1213BFFCF00BA1586 /* ProviderPresetViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProviderPresetViewController.swift; sourceTree = ""; }; @@ -170,7 +171,6 @@ 0E89DFC7213E8FC500741BA1 /* SessionProxy+Communication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionProxy+Communication.swift"; sourceTree = ""; }; 0E89DFCD213EEDFA00741BA1 /* WizardProviderViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WizardProviderViewController.swift; sourceTree = ""; }; 0E8D97E121388B52006FB4A0 /* InfrastructurePreset.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfrastructurePreset.swift; sourceTree = ""; }; - 0E8D97E421389276006FB4A0 /* pia.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = pia.json; sourceTree = ""; }; 0EA068F3218475F800C320AD /* ParsingResult+Alerts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ParsingResult+Alerts.swift"; sourceTree = ""; }; 0EB60FD92111136E00AD27F3 /* UITextView+Search.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITextView+Search.swift"; sourceTree = ""; }; 0EB67D6A2184581E00BA6200 /* ImportedHostsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportedHostsViewController.swift; sourceTree = ""; }; @@ -356,14 +356,6 @@ path = Organizer; sourceTree = ""; }; - 0E8D97C621388679006FB4A0 /* Infrastructures */ = { - isa = PBXGroup; - children = ( - 0E8D97E421389276006FB4A0 /* pia.json */, - ); - path = Infrastructures; - sourceTree = ""; - }; 0EBE3AA2213DC1B000BFA2F5 /* Profiles */ = { isa = PBXGroup; children = ( @@ -418,7 +410,7 @@ 0ED31C1C20CF17CC0027975F /* Resources */ = { isa = PBXGroup; children = ( - 0E8D97C621388679006FB4A0 /* Infrastructures */, + 0E0EABC721DF853C0069DAE7 /* Web */, 0E05C5DF20D198B9006EE732 /* Localizable.strings */, ); path = Resources; @@ -658,9 +650,9 @@ 0E05C5DC20D198B9006EE732 /* Localizable.strings in Resources */, 0ED38ADA213F44D00004D387 /* Organizer.storyboard in Resources */, 0E57F64620C83FC7008323CF /* LaunchScreen.storyboard in Resources */, + 0E0EABC821DF853C0069DAE7 /* Web in Resources */, 0E57F64320C83FC7008323CF /* Assets.xcassets in Resources */, 0E57F64120C83FC5008323CF /* Main.storyboard in Resources */, - 0E8D97E521389277006FB4A0 /* pia.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Passepartout/Resources/Infrastructures/pia.json b/Passepartout/Resources/Web/net/pia.json similarity index 100% rename from Passepartout/Resources/Infrastructures/pia.json rename to Passepartout/Resources/Web/net/pia.json diff --git a/Passepartout/Sources/AppConstants.swift b/Passepartout/Sources/AppConstants.swift index 1f486e32..3c4fa534 100644 --- a/Passepartout/Sources/AppConstants.swift +++ b/Passepartout/Sources/AppConstants.swift @@ -35,7 +35,7 @@ class AppConstants { class Store { static let serviceFilename = "ConnectionService.json" - static let infrastructureCacheDirectory = "Infrastructures" + static let webCacheDirectory = "Web" static let providersDirectory = "Providers" diff --git a/Passepartout/Sources/Services/InfrastructureFactory.swift b/Passepartout/Sources/Services/InfrastructureFactory.swift index e2600757..1dcb33ce 100644 --- a/Passepartout/Sources/Services/InfrastructureFactory.swift +++ b/Passepartout/Sources/Services/InfrastructureFactory.swift @@ -30,7 +30,7 @@ private let log = SwiftyBeaver.self class InfrastructureFactory { private static func embedded(withName name: Infrastructure.Name) -> Infrastructure { - guard let url = Bundle.main.url(forResource: name.webName, withExtension: "json") else { + guard let url = name.bundleURL else { fatalError("Cannot find JSON for infrastructure '\(name)'") } do { @@ -44,7 +44,7 @@ class InfrastructureFactory { guard let cacheDate = FileManager.default.modificationDate(of: cachedEntry.path) else { return false } - guard let bundleURL = Bundle.main.url(forResource: name.webName, withExtension: "json") else { + guard let bundleURL = name.bundleURL else { return true } guard let bundleDate = FileManager.default.modificationDate(of: bundleURL.path) else { @@ -53,7 +53,7 @@ class InfrastructureFactory { return cacheDate > bundleDate } - static let shared = InfrastructureFactory(withCacheDirectory: AppConstants.Store.infrastructureCacheDirectory) + static let shared = InfrastructureFactory() let allNames: [Infrastructure.Name] = [ .pia @@ -67,14 +67,14 @@ class InfrastructureFactory { private var lastUpdate: [Infrastructure.Name: Date] - private init(withCacheDirectory cacheDirectory: String) { + private init() { var bundle: [Infrastructure.Name: Infrastructure] = [:] allNames.forEach { bundle[$0] = InfrastructureFactory.embedded(withName: $0) } self.bundle = bundle - cachePath = FileManager.default.userURL(for: .cachesDirectory, appending: cacheDirectory) + cachePath = FileManager.default.userURL(for: .cachesDirectory, appending: nil) cache = [:] lastUpdate = [:] } @@ -207,7 +207,8 @@ class InfrastructureFactory { let fm = FileManager.default let url = cacheURL(for: name) do { - try fm.createDirectory(at: cachePath, withIntermediateDirectories: true, attributes: nil) + let parent = url.deletingLastPathComponent() + try fm.createDirectory(at: parent, withIntermediateDirectories: true, attributes: nil) let data = try JSONEncoder().encode(infrastructure) try data.write(to: url) try fm.setAttributes([.modificationDate: lastModified], ofItemAtPath: url.path) @@ -217,7 +218,7 @@ class InfrastructureFactory { } private func cacheURL(for name: Infrastructure.Name) -> URL { - return cachePath.appendingPathComponent(name.webName).appendingPathExtension("json") + return cachePath.appendingPathComponent(name.bundleRelativePath) } private func cacheModificationDate(for name: Infrastructure.Name) -> Date? { @@ -225,12 +226,26 @@ class InfrastructureFactory { return FileManager.default.modificationDate(of: url.path) } - private func bundleURL(for name: Infrastructure.Name) -> URL { - return Bundle.main.url(forResource: name.webName, withExtension: "json")! - } - private func bundleModificationDate(for name: Infrastructure.Name) -> Date? { - let url = bundleURL(for: name) + guard let url = name.bundleURL else { + return nil + } return FileManager.default.modificationDate(of: url.path) } } + +private extension Infrastructure.Name { + var bundleRelativePath: String { + let endpoint = WebServices.Endpoint.network(self) + + // e.g. "Web", PIA="net/pia" -> "Web/net/pia.json" + return "\(AppConstants.Store.webCacheDirectory)/\(endpoint.path).json" + } + + var bundleURL: URL? { + let endpoint = WebServices.Endpoint.network(self) + + // e.g. "Web", PIA="net/pia" -> "[Bundle]:Web/net/pia.json" + return Bundle.main.url(forResource: "\(AppConstants.Store.webCacheDirectory)/\(endpoint.path)", withExtension: "json") + } +} diff --git a/Passepartout/Sources/Services/WebServices.swift b/Passepartout/Sources/Services/WebServices.swift index 183834fb..60209c9b 100644 --- a/Passepartout/Sources/Services/WebServices.swift +++ b/Passepartout/Sources/Services/WebServices.swift @@ -35,7 +35,7 @@ class WebServices { var path: String { switch self { case .network(let name): - return "net/\(name.webName).json" + return "net/\(name.webName)" } } } @@ -73,7 +73,7 @@ class WebServices { } private func get(_ endpoint: Endpoint) -> URLRequest { - let url = AppConstants.Web.url(path: endpoint.path) + let url = AppConstants.Web.url(path: "\(endpoint.path).json") return URLRequest(url: url, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: AppConstants.Web.timeout) }