mirror of
https://github.com/XcodesOrg/XcodesApp.git
synced 2026-03-25 08:55:46 +00:00
Convert XcodeList to Combine
This commit is contained in:
parent
e3687eacc6
commit
4ef8428151
3 changed files with 45 additions and 52 deletions
|
|
@ -2,7 +2,6 @@ import AppKit
|
|||
import AppleAPI
|
||||
import Combine
|
||||
import Path
|
||||
import PromiseKit
|
||||
import LegibleError
|
||||
import KeychainAccess
|
||||
|
||||
|
|
@ -173,22 +172,15 @@ class AppState: ObservableObject {
|
|||
public func update() -> AnyPublisher<[Xcode], Never> {
|
||||
signInIfNeeded()
|
||||
.flatMap {
|
||||
// Wrap the Promise API in a Publisher for now
|
||||
Deferred {
|
||||
Future { promise in
|
||||
self.list.update()
|
||||
.done { promise(.success($0)) }
|
||||
.catch { promise(.failure($0)) }
|
||||
self.list.update()
|
||||
}
|
||||
.handleEvents(
|
||||
receiveCompletion: { completion in
|
||||
if case let .failure(error) = completion {
|
||||
self.error = AlertContent(title: "Update Error", message: error.legibleLocalizedDescription)
|
||||
}
|
||||
}
|
||||
.handleEvents(
|
||||
receiveCompletion: { completion in
|
||||
if case let .failure(error) = completion {
|
||||
self.error = AlertContent(title: "Update Error", message: error.legibleLocalizedDescription)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
.catch { _ in
|
||||
Just(self.list.availableXcodes)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,10 +111,10 @@ private func _installedXcodes(destination: Path) -> [InstalledXcode] {
|
|||
|
||||
public struct Network {
|
||||
private static let client = AppleAPI.Client()
|
||||
|
||||
public var dataTask: (URLRequestConvertible) -> Promise<(data: Data, response: URLResponse)> = { AppleAPI.Current.network.session.dataTask(.promise, with: $0) }
|
||||
public func dataTask(with convertible: URLRequestConvertible) -> Promise<(data: Data, response: URLResponse)> {
|
||||
dataTask(convertible)
|
||||
|
||||
public var dataTask: (URLRequest) -> URLSession.DataTaskPublisher = { AppleAPI.Current.network.session.dataTaskPublisher(for: $0) }
|
||||
public func dataTask(with request: URLRequest) -> URLSession.DataTaskPublisher {
|
||||
dataTask(request)
|
||||
}
|
||||
|
||||
public var downloadTask: (URLRequestConvertible, URL, Data?) -> (Progress, Promise<(saveLocation: URL, response: URLResponse)>) = { AppleAPI.Current.network.session.downloadTask(with: $0, to: $1, resumingWith: $2) }
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import Combine
|
||||
import Foundation
|
||||
import Path
|
||||
import Version
|
||||
import PromiseKit
|
||||
import SwiftSoup
|
||||
|
||||
/// Provides lists of available and installed Xcodes
|
||||
/// Provides lists of available Xcodes
|
||||
public final class XcodeList {
|
||||
public init() {
|
||||
try? loadCachedAvailableXcodes()
|
||||
|
|
@ -16,8 +16,9 @@ public final class XcodeList {
|
|||
return availableXcodes.isEmpty
|
||||
}
|
||||
|
||||
public func update() -> Promise<[Xcode]> {
|
||||
return when(fulfilled: releasedXcodes(), prereleaseXcodes())
|
||||
public func update() -> AnyPublisher<[Xcode], Error> {
|
||||
releasedXcodes().combineLatest(prereleaseXcodes())
|
||||
.receive(on: DispatchQueue.main)
|
||||
.map { releasedXcodes, prereleaseXcodes in
|
||||
// Starting with Xcode 11 beta 6, developer.apple.com/download and developer.apple.com/download/more both list some pre-release versions of Xcode.
|
||||
// Previously pre-release versions only appeared on developer.apple.com/download.
|
||||
|
|
@ -30,6 +31,7 @@ public final class XcodeList {
|
|||
try? self.cacheAvailableXcodes(xcodes)
|
||||
return xcodes
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -49,38 +51,37 @@ extension XcodeList {
|
|||
}
|
||||
|
||||
extension XcodeList {
|
||||
private func releasedXcodes() -> Promise<[Xcode]> {
|
||||
return firstly { () -> Promise<(data: Data, response: URLResponse)> in
|
||||
Current.network.dataTask(with: URLRequest.downloads)
|
||||
}
|
||||
.map { (data, response) -> [Xcode] in
|
||||
let decoder = JSONDecoder()
|
||||
decoder.dateDecodingStrategy = .formatted(.downloadsDateModified)
|
||||
let downloads = try decoder.decode(Downloads.self, from: data)
|
||||
let xcodes = downloads
|
||||
.downloads
|
||||
.filter { $0.name.range(of: "^Xcode [0-9]", options: .regularExpression) != nil }
|
||||
.compactMap { download -> Xcode? in
|
||||
let urlPrefix = URL(string: "https://download.developer.apple.com/")!
|
||||
guard
|
||||
let xcodeFile = download.files.first(where: { $0.remotePath.hasSuffix("dmg") || $0.remotePath.hasSuffix("xip") }),
|
||||
let version = Version(xcodeVersion: download.name)
|
||||
else { return nil }
|
||||
private func releasedXcodes() -> AnyPublisher<[Xcode], Error> {
|
||||
Current.network.dataTask(with: URLRequest.downloads)
|
||||
.map(\.data)
|
||||
.decode(type: Downloads.self, decoder: configure(JSONDecoder()) {
|
||||
$0.dateDecodingStrategy = .formatted(.downloadsDateModified)
|
||||
})
|
||||
.map { downloads -> [Xcode] in
|
||||
let xcodes = downloads
|
||||
.downloads
|
||||
.filter { $0.name.range(of: "^Xcode [0-9]", options: .regularExpression) != nil }
|
||||
.compactMap { download -> Xcode? in
|
||||
let urlPrefix = URL(string: "https://download.developer.apple.com/")!
|
||||
guard
|
||||
let xcodeFile = download.files.first(where: { $0.remotePath.hasSuffix("dmg") || $0.remotePath.hasSuffix("xip") }),
|
||||
let version = Version(xcodeVersion: download.name)
|
||||
else { return nil }
|
||||
|
||||
let url = urlPrefix.appendingPathComponent(xcodeFile.remotePath)
|
||||
return Xcode(version: version, url: url, filename: String(xcodeFile.remotePath.suffix(fromLast: "/")), releaseDate: download.dateModified)
|
||||
}
|
||||
return xcodes
|
||||
}
|
||||
let url = urlPrefix.appendingPathComponent(xcodeFile.remotePath)
|
||||
return Xcode(version: version, url: url, filename: String(xcodeFile.remotePath.suffix(fromLast: "/")), releaseDate: download.dateModified)
|
||||
}
|
||||
return xcodes
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
private func prereleaseXcodes() -> Promise<[Xcode]> {
|
||||
return firstly { () -> Promise<(data: Data, response: URLResponse)> in
|
||||
Current.network.dataTask(with: URLRequest.download)
|
||||
}
|
||||
.map { (data, _) -> [Xcode] in
|
||||
try self.parsePrereleaseXcodes(from: data)
|
||||
}
|
||||
private func prereleaseXcodes() -> AnyPublisher<[Xcode], Error> {
|
||||
Current.network.dataTask(with: URLRequest.download)
|
||||
.tryMap { (data, _) -> [Xcode] in
|
||||
try self.parsePrereleaseXcodes(from: data)
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func parsePrereleaseXcodes(from data: Data) throws -> [Xcode] {
|
||||
|
|
|
|||
Loading…
Reference in a new issue