mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-13 12:19:25 +00:00
98 lines
3.6 KiB
Swift
98 lines
3.6 KiB
Swift
//
|
|
// Queries+PackageVersion.swift
|
|
// KeymanEngine
|
|
//
|
|
// Created by Joshua Horton on 6/25/20.
|
|
// Copyright © 2020 SIL International. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
extension Queries {
|
|
class PackageVersion {
|
|
class ResultComponent {}
|
|
|
|
class ResultEntry: ResultComponent, Decodable {
|
|
let version: String
|
|
let packageURL: String
|
|
|
|
enum CodingKeys: String, CodingKey {
|
|
case version
|
|
case packageURL = "kmp"
|
|
}
|
|
}
|
|
|
|
class ResultError: ResultComponent, Decodable {
|
|
let error: String
|
|
|
|
enum CodingKeys: String, CodingKey {
|
|
case error
|
|
}
|
|
}
|
|
|
|
struct Result: Decodable {
|
|
let keyboards: [String : ResultComponent]?
|
|
let models: [String : ResultComponent]?
|
|
|
|
enum CodingKeys: String, CodingKey {
|
|
case keyboards
|
|
case models
|
|
}
|
|
|
|
init(from decoder: Decoder) throws {
|
|
let rootValues = try decoder.container(keyedBy: CodingKeys.self)
|
|
|
|
func dictionaryReducer(container: KeyedDecodingContainer<Queries.IDCodingKey>, category: String) -> ([String: ResultComponent], Queries.IDCodingKey) throws -> [String: ResultComponent] {
|
|
return { (dict, id) -> [String: ResultComponent] in
|
|
var dict = dict
|
|
if let entry = try? container.decode(ResultEntry.self, forKey: id) {
|
|
dict[id.stringValue] = entry
|
|
} else if let error = try? container.decode(ResultError.self, forKey: id) {
|
|
dict[id.stringValue] = error
|
|
} else {
|
|
throw NSError(domain: "Keyman", code: 0, userInfo: [NSLocalizedDescriptionKey: "Unexpected value contained during \(category) decoding, id \(id.stringValue)"])
|
|
}
|
|
return dict
|
|
}
|
|
}
|
|
|
|
let keyboardValueSet = try rootValues.nestedContainer(keyedBy: IDCodingKey.self, forKey: .keyboards)
|
|
keyboards = try keyboardValueSet.allKeys.reduce([String: ResultComponent](), dictionaryReducer(container: keyboardValueSet, category: "keyboard"))
|
|
|
|
let modelValueSet = try rootValues.nestedContainer(keyedBy: IDCodingKey.self, forKey: .models)
|
|
models = try modelValueSet.allKeys.reduce([String: ResultComponent](), dictionaryReducer(container: modelValueSet, category: "lexical model"))
|
|
}
|
|
}
|
|
|
|
private static let PACKAGE_VERSION_ENDPOINT = URLComponents(string: "https://api.keyman.com/package-version")!
|
|
|
|
public static func fetch(for fullIDs: [AnyLanguageResourceFullID],
|
|
withSession session: URLSession = .shared,
|
|
fetchCompletion: @escaping JSONQueryCompletionBlock<Result>) {
|
|
// Step 1: build the query
|
|
var urlComponents = PACKAGE_VERSION_ENDPOINT
|
|
|
|
let queryItems: [URLQueryItem] = fullIDs.map { fullID in
|
|
var resourceField: String
|
|
switch(fullID.type) {
|
|
case .keyboard:
|
|
resourceField = "keyboard"
|
|
case .lexicalModel:
|
|
resourceField = "model"
|
|
}
|
|
|
|
return URLQueryItem(name: resourceField, value: fullID.id)
|
|
}
|
|
|
|
urlComponents.queryItems = queryItems + [URLQueryItem(name: "platform", value: "ios")]
|
|
log.info("Querying package versions through API endpoint: \(urlComponents.url!)")
|
|
|
|
// Step 2: configure the completion closure.
|
|
let completionClosure = Queries.jsonDataTaskCompletionAdapter(resultType: Result.self, completionBlock: fetchCompletion)
|
|
|
|
// Step 3: run the actual query, letting the prepared completion closure take care of the rest.
|
|
let task = session.dataTask(with: urlComponents.url!, completionHandler: completionClosure)
|
|
task.resume()
|
|
}
|
|
}
|
|
}
|