mirror of
https://github.com/Aminark/legado-ios.git
synced 2026-10-24 04:41:23 +08:00
feat: open-source 小浣熊阅读 for iOS
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import Foundation
|
||||
|
||||
public struct ExploreKind: Codable, Hashable, Identifiable, Sendable {
|
||||
public var title: String
|
||||
public var url: String?
|
||||
public var type: String
|
||||
public var action: String?
|
||||
public var chars: [String?]?
|
||||
public var defaultValue: String?
|
||||
|
||||
public var id: String { "\(title)\u{0}\(url ?? "")" }
|
||||
|
||||
public var navigableURL: String? {
|
||||
guard type.caseInsensitiveCompare("url") == .orderedSame,
|
||||
let value = url?.trimmingCharacters(in: .whitespacesAndNewlines),
|
||||
!value.isEmpty else { return nil }
|
||||
return value
|
||||
}
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case title, url, type, action, chars
|
||||
case defaultValue = "default"
|
||||
}
|
||||
|
||||
public init(
|
||||
title: String,
|
||||
url: String? = nil,
|
||||
type: String = "url",
|
||||
action: String? = nil,
|
||||
chars: [String?]? = nil,
|
||||
defaultValue: String? = nil
|
||||
) {
|
||||
self.title = title
|
||||
self.url = url
|
||||
self.type = type
|
||||
self.action = action
|
||||
self.chars = chars
|
||||
self.defaultValue = defaultValue
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
title = values.lossyString(forKey: .title) ?? ""
|
||||
url = values.lossyString(forKey: .url)
|
||||
type = values.lossyString(forKey: .type) ?? "url"
|
||||
action = values.lossyString(forKey: .action)
|
||||
defaultValue = values.lossyString(forKey: .defaultValue)
|
||||
if let decoded = try? values.decodeIfPresent([JSONValue].self, forKey: .chars) {
|
||||
chars = decoded.map { value in
|
||||
if case .null = value { return nil }
|
||||
return value.stringValue
|
||||
}
|
||||
} else if let scalar = values.lossyString(forKey: .chars) {
|
||||
chars = [scalar]
|
||||
} else {
|
||||
chars = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension KeyedDecodingContainer where Key == ExploreKind.CodingKeys {
|
||||
func lossyString(forKey key: Key) -> String? {
|
||||
guard contains(key), (try? decodeNil(forKey: key)) != true else { return nil }
|
||||
if let value = try? decode(String.self, forKey: key) { return value }
|
||||
if let value = try? decode(Bool.self, forKey: key) { return String(value) }
|
||||
if let value = try? decode(Int64.self, forKey: key) { return String(value) }
|
||||
if let value = try? decode(Double.self, forKey: key) {
|
||||
return value.rounded() == value ? String(format: "%.0f", value) : String(value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public struct ExploreKindsReport: Sendable {
|
||||
public var kinds: [ExploreKind]
|
||||
public var diagnostics: [RuleDiagnostic]
|
||||
|
||||
public init(kinds: [ExploreKind] = [], diagnostics: [RuleDiagnostic] = []) {
|
||||
self.kinds = kinds
|
||||
self.diagnostics = diagnostics
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user