2015-08-21 13:02:36 +00:00
|
|
|
//
|
2015-08-24 18:45:54 +00:00
|
|
|
// PurchaseDownloadObserver.swift
|
2015-08-21 13:02:36 +00:00
|
|
|
// 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
|
2015-08-21 13:02:36 +00:00
|
|
|
}
|
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 {
|
2018-04-06 03:29:15 +00:00
|
|
|
progress(status.progressState)
|
2015-09-03 23:13:47 +00:00
|
|
|
}
|
2015-08-21 13:02:36 +00:00
|
|
|
}
|
2019-01-12 01:06:02 +00:00
|
|
|
|
2016-10-21 21:59:33 +00:00
|
|
|
func downloadQueue(_ queue: 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
|
|
|
}
|
2015-09-20 18:10:13 +00:00
|
|
|
clearLine()
|
2016-09-25 21:13:23 +00:00
|
|
|
printInfo("Downloading \(download.metadata.title)")
|
2015-08-21 13:02:36 +00:00
|
|
|
}
|
2019-01-12 01:06:02 +00:00
|
|
|
|
2016-10-21 21:59:33 +00:00
|
|
|
func downloadQueue(_ queue: CKDownloadQueue, changedWithRemoval download: SSDownload) {
|
2016-09-17 12:58:38 +00:00
|
|
|
guard download.metadata.itemIdentifier == purchase.itemIdentifier,
|
|
|
|
let status = download.status else {
|
|
|
|
return
|
|
|
|
}
|
2019-01-12 01:06:02 +00:00
|
|
|
|
2015-09-03 23:13:47 +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)")
|
2015-09-03 23:13:47 +00:00
|
|
|
completionHandler?()
|
2015-08-24 18:45:54 +00:00
|
|
|
}
|
2015-08-21 13:02:36 +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) {
|
2015-08-21 18:11:36 +00:00
|
|
|
// 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 {
|
2015-08-21 18:11:36 +00:00
|
|
|
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-12 01:06:02 +00:00
|
|
|
for index in 0..<barLength {
|
|
|
|
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 += "-"
|
|
|
|
}
|
|
|
|
}
|
2015-09-03 23:13:47 +00:00
|
|
|
clearLine()
|
2015-09-14 08:51:09 +00:00
|
|
|
print("\(bar) \(state.percentage) \(state.phase)", terminator: "")
|
2015-08-21 18:14:37 +00:00
|
|
|
fflush(stdout)
|
2015-08-21 18:01:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
extension SSDownloadStatus {
|
2018-04-06 03:29:15 +00:00
|
|
|
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
|
|
|
}
|