Plugins: Add option to use YAML for lists
YAML is a modern configuration format which is human readable and supports more conventions than JSON. However, some people may still prefer to write in JSON, so add the option for users to write legacy JSON if they want to and to provide backwards compatability with older plugins. Signed-off-by: kingbri <bdashore3@proton.me>
This commit is contained in:
parent
c8c7732575
commit
22bec5da52
3 changed files with 54 additions and 8 deletions
|
|
@ -72,6 +72,7 @@
|
|||
0C70E40228C3CE9C00A5C72D /* ConditionalContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C70E40128C3CE9C00A5C72D /* ConditionalContextMenu.swift */; };
|
||||
0C70E40628C40C4E00A5C72D /* NotificationCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C70E40528C40C4E00A5C72D /* NotificationCenter.swift */; };
|
||||
0C733287289C4C820058D1FE /* SourceSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C733286289C4C820058D1FE /* SourceSettingsView.swift */; };
|
||||
0C748EDA29D9256D0049B8BE /* Yams in Frameworks */ = {isa = PBXBuildFile; productRef = 0C748ED929D9256D0049B8BE /* Yams */; };
|
||||
0C7506D728B1AC9A008BEE38 /* SwiftyJSON in Frameworks */ = {isa = PBXBuildFile; productRef = 0C7506D628B1AC9A008BEE38 /* SwiftyJSON */; };
|
||||
0C750744289B003E004B3906 /* SourceRssParser+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C750742289B003E004B3906 /* SourceRssParser+CoreDataClass.swift */; };
|
||||
0C750745289B003E004B3906 /* SourceRssParser+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C750743289B003E004B3906 /* SourceRssParser+CoreDataProperties.swift */; };
|
||||
|
|
@ -299,6 +300,7 @@
|
|||
0C4CFC462897030D00AD9FAD /* Regex in Frameworks */,
|
||||
0C64A4B7288903880079976D /* KeychainSwift in Frameworks */,
|
||||
0CAF1C7B286F5C8600296F86 /* SwiftSoup in Frameworks */,
|
||||
0C748EDA29D9256D0049B8BE /* Yams in Frameworks */,
|
||||
0CDDDE052935235E006810B1 /* BetterSafariView in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
@ -688,6 +690,7 @@
|
|||
0C7506D628B1AC9A008BEE38 /* SwiftyJSON */,
|
||||
0CDDDE042935235E006810B1 /* BetterSafariView */,
|
||||
0C448BE829A135F100F4E266 /* Introspect-Static */,
|
||||
0C748ED929D9256D0049B8BE /* Yams */,
|
||||
);
|
||||
productName = Torrenter;
|
||||
productReference = 0CAF1C68286F5C0E00296F86 /* Ferrite.app */;
|
||||
|
|
@ -725,6 +728,7 @@
|
|||
0C7506D528B1AC9A008BEE38 /* XCRemoteSwiftPackageReference "SwiftyJSON" */,
|
||||
0CDDDE032935235E006810B1 /* XCRemoteSwiftPackageReference "BetterSafariView" */,
|
||||
0C448BE729A135F100F4E266 /* XCRemoteSwiftPackageReference "SwiftUI-Introspect" */,
|
||||
0C748ED829D9256D0049B8BE /* XCRemoteSwiftPackageReference "Yams" */,
|
||||
);
|
||||
productRefGroup = 0CAF1C69286F5C0E00296F86 /* Products */;
|
||||
projectDirPath = "";
|
||||
|
|
@ -1152,6 +1156,14 @@
|
|||
kind = branch;
|
||||
};
|
||||
};
|
||||
0C748ED829D9256D0049B8BE /* XCRemoteSwiftPackageReference "Yams" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/jpsim/Yams";
|
||||
requirement = {
|
||||
kind = upToNextMinorVersion;
|
||||
minimumVersion = 5.0.5;
|
||||
};
|
||||
};
|
||||
0C7506D528B1AC9A008BEE38 /* XCRemoteSwiftPackageReference "SwiftyJSON" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/SwiftyJSON/SwiftyJSON";
|
||||
|
|
@ -1199,6 +1211,11 @@
|
|||
package = 0C64A4B5288903880079976D /* XCRemoteSwiftPackageReference "keychain-swift" */;
|
||||
productName = KeychainSwift;
|
||||
};
|
||||
0C748ED929D9256D0049B8BE /* Yams */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 0C748ED829D9256D0049B8BE /* XCRemoteSwiftPackageReference "Yams" */;
|
||||
productName = Yams;
|
||||
};
|
||||
0C7506D628B1AC9A008BEE38 /* SwiftyJSON */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 0C7506D528B1AC9A008BEE38 /* XCRemoteSwiftPackageReference "SwiftyJSON" */;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ extension PluginManager {
|
|||
enum PluginManagerError: Error {
|
||||
case ListAddition(description: String)
|
||||
case ActionAddition(description: String)
|
||||
case PluginFetch(description: String)
|
||||
}
|
||||
|
||||
struct AvailablePlugins {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import Yams
|
||||
|
||||
public class PluginManager: ObservableObject {
|
||||
var logManager: LoggingManager?
|
||||
|
|
@ -102,7 +103,18 @@ public class PluginManager: ObservableObject {
|
|||
let request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData)
|
||||
|
||||
let (data, _) = try await URLSession.shared.data(for: request)
|
||||
let pluginResponse = try JSONDecoder().decode(PluginListJson.self, from: data)
|
||||
let pluginResponse: PluginListJson?
|
||||
|
||||
// If the URL is a yaml file, decode as such. Otherwise assume legacy JSON
|
||||
if url.pathExtension == "yaml" || url.pathExtension == "yml" {
|
||||
pluginResponse = try YAMLDecoder().decode(PluginListJson.self, from: data)
|
||||
} else {
|
||||
pluginResponse = try JSONDecoder().decode(PluginListJson.self, from: data)
|
||||
}
|
||||
|
||||
guard let pluginResponse else {
|
||||
throw PluginManagerError.PluginFetch(description: "Could not decode plugin list data")
|
||||
}
|
||||
|
||||
if let sources = pluginResponse.sources {
|
||||
// Faster and more performant to map instead of a for loop
|
||||
|
|
@ -748,25 +760,41 @@ public class PluginManager: ObservableObject {
|
|||
|
||||
// Adds a plugin list
|
||||
// Can move this to PersistenceController if needed
|
||||
public func addPluginList(_ url: String, isSheet: Bool = false, existingPluginList: PluginList? = nil) async throws {
|
||||
public func addPluginList(_ urlString: String, isSheet: Bool = false, existingPluginList: PluginList? = nil) async throws {
|
||||
let backgroundContext = PersistenceController.shared.backgroundContext
|
||||
|
||||
if url.isEmpty || !url.starts(with: "https://") && !url.starts(with: "http://") {
|
||||
if urlString.isEmpty || !urlString.starts(with: "https://") && !urlString.starts(with: "http://") {
|
||||
throw PluginManagerError.ListAddition(description: "The provided source list is invalid. Please check if the URL is formatted properly.")
|
||||
}
|
||||
|
||||
let (data, _) = try await URLSession.shared.data(for: URLRequest(url: URL(string: url)!))
|
||||
let rawResponse = try JSONDecoder().decode(PluginListJson.self, from: data)
|
||||
guard let url = URL(string: urlString) else {
|
||||
throw PluginManagerError.ListAddition(description: "The provided source list is invalid. Please check if the URL is formatted properly.")
|
||||
}
|
||||
|
||||
let (data, _) = try await URLSession.shared.data(for: URLRequest(url: url))
|
||||
|
||||
let rawResponse: PluginListJson?
|
||||
|
||||
// If the URL is a yaml file, decode as such. Otherwise assume legacy JSON
|
||||
if url.pathExtension == "yaml" || url.pathExtension == "yml" {
|
||||
rawResponse = try YAMLDecoder().decode(PluginListJson.self, from: data)
|
||||
} else {
|
||||
rawResponse = try JSONDecoder().decode(PluginListJson.self, from: data)
|
||||
}
|
||||
|
||||
guard let rawResponse else {
|
||||
throw PluginManagerError.ListAddition(description: "Could not decode the plugin list from URL \(urlString)")
|
||||
}
|
||||
|
||||
if let existingPluginList {
|
||||
existingPluginList.urlString = url
|
||||
existingPluginList.urlString = urlString
|
||||
existingPluginList.name = rawResponse.name
|
||||
existingPluginList.author = rawResponse.author
|
||||
|
||||
try PersistenceController.shared.container.viewContext.save()
|
||||
} else {
|
||||
let pluginListRequest = PluginList.fetchRequest()
|
||||
let urlPredicate = NSPredicate(format: "urlString == %@", url)
|
||||
let urlPredicate = NSPredicate(format: "urlString == %@", urlString)
|
||||
let infoPredicate = NSPredicate(format: "author == %@ AND name == %@", rawResponse.author, rawResponse.name)
|
||||
pluginListRequest.predicate = NSCompoundPredicate(type: .or, subpredicates: [urlPredicate, infoPredicate])
|
||||
pluginListRequest.fetchLimit = 1
|
||||
|
|
@ -779,7 +807,7 @@ public class PluginManager: ObservableObject {
|
|||
|
||||
let newPluginList = PluginList(context: backgroundContext)
|
||||
newPluginList.id = UUID()
|
||||
newPluginList.urlString = url
|
||||
newPluginList.urlString = urlString
|
||||
newPluginList.name = rawResponse.name
|
||||
newPluginList.author = rawResponse.author
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue