mas/MasKit/AppStore/PurchaseDownloadObserver.swift

109 lines
2.9 KiB
Swift
Raw Normal View History

//
2015-08-24 18:45:54 +00:00
// PurchaseDownloadObserver.swift
// mas-cli
//
// Created by Andrew Naylor on 21/08/2015.
// Copyright (c) 2015 Andrew Naylor. All rights reserved.
//
2018-10-14 19:41:19 +00:00
import CommerceKit
import StoreFoundation
2015-09-14 08:51:09 +00:00
@objc class PurchaseDownloadObserver: NSObject, CKDownloadQueueObserver {
2015-08-24 18:45:54 +00:00
let purchase: SSPurchase
2019-01-12 01:06:02 +00:00
var completionHandler: (() -> Void)?
var errorHandler: ((MASError) -> Void)?
2015-08-24 18:45:54 +00:00
init(purchase: SSPurchase) {
self.purchase = purchase
}
2019-01-12 01:06:02 +00:00
2016-10-21 21:59:33 +00:00
func downloadQueue(_ queue: CKDownloadQueue, statusChangedFor download: SSDownload) {
2016-09-17 12:58:38 +00:00
guard download.metadata.itemIdentifier == purchase.itemIdentifier,
let status = download.status else {
2015-08-21 18:01:56 +00:00
return
}
2019-01-12 01:06:02 +00:00
2016-09-17 12:58:38 +00:00
if status.isFailed || status.isCancelled {
queue.removeDownload(withItemIdentifier: download.metadata.itemIdentifier)
2019-01-12 01:06:02 +00:00
} else {
progress(status.progressState)
}
}
2019-01-12 01:06:02 +00:00
2019-01-30 06:15:24 +00:00
func downloadQueue(_: CKDownloadQueue, changedWithAddition download: SSDownload) {
2016-09-17 12:58:38 +00:00
guard download.metadata.itemIdentifier == purchase.itemIdentifier else {
2016-10-21 21:59:33 +00:00
return
2016-09-17 12:58:38 +00:00
}
clearLine()
2016-09-25 21:13:23 +00:00
printInfo("Downloading \(download.metadata.title)")
}
2019-01-12 01:06:02 +00:00
2019-01-30 06:15:24 +00:00
func downloadQueue(_: CKDownloadQueue, changedWithRemoval download: SSDownload) {
2016-09-17 12:58:38 +00:00
guard download.metadata.itemIdentifier == purchase.itemIdentifier,
2019-01-30 06:15:24 +00:00
let status = download.status else {
2016-09-17 12:58:38 +00:00
return
}
2019-01-12 01:06:02 +00:00
clearLine()
2016-09-17 12:58:38 +00:00
if status.isFailed {
2016-09-25 21:13:23 +00:00
errorHandler?(.downloadFailed(error: status.error as NSError?))
2019-01-12 01:06:02 +00:00
} else if status.isCancelled {
2016-09-25 21:13:23 +00:00
errorHandler?(.cancelled)
2019-01-12 01:06:02 +00:00
} else {
2016-09-25 21:13:23 +00:00
printInfo("Installed \(download.metadata.title)")
completionHandler?()
2015-08-24 18:45:54 +00:00
}
}
2015-08-21 18:01:56 +00:00
}
struct ProgressState {
let percentComplete: Float
let phase: String
2019-01-12 01:06:02 +00:00
2015-08-21 18:01:56 +00:00
var percentage: String {
return String(format: "%.1f%%", arguments: [floor(percentComplete * 100)])
}
}
2016-09-17 12:58:38 +00:00
func progress(_ state: ProgressState) {
// Don't display the progress bar if we're not on a terminal
2015-09-20 21:58:58 +00:00
guard isatty(fileno(stdout)) != 0 else {
return
}
2019-01-12 01:06:02 +00:00
2015-08-21 18:01:56 +00:00
let barLength = 60
2019-01-12 01:06:02 +00:00
2015-08-21 18:01:56 +00:00
let completeLength = Int(state.percentComplete * Float(barLength))
var bar = ""
2019-01-30 06:15:24 +00:00
for index in 0 ..< barLength {
2019-01-12 01:06:02 +00:00
if index < completeLength {
2015-08-21 18:01:56 +00:00
bar += "#"
2019-01-12 01:06:02 +00:00
} else {
2015-08-21 18:01:56 +00:00
bar += "-"
}
}
clearLine()
2015-09-14 08:51:09 +00:00
print("\(bar) \(state.percentage) \(state.phase)", terminator: "")
fflush(stdout)
2015-08-21 18:01:56 +00:00
}
extension SSDownloadStatus {
var progressState: ProgressState {
return ProgressState(percentComplete: percentComplete, phase: activePhase.phaseDescription)
2015-08-21 18:01:56 +00:00
}
}
extension SSDownloadPhase {
var phaseDescription: String {
switch phaseType {
case 0:
return "Downloading"
case 1:
return "Installing"
default:
return "Waiting"
}
}
2016-09-17 12:58:38 +00:00
}