You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
5.4 KiB
159 lines
5.4 KiB
4 years ago
|
// Copyright © 2015 Abhishek Banthia
|
||
|
|
||
|
import Cocoa
|
||
|
|
||
|
class VersionUpdateHandler: NSObject {
|
||
|
enum VersionUpdateHandlerPriority {
|
||
|
case defaultPri
|
||
|
case low
|
||
|
case medium
|
||
|
case high
|
||
|
}
|
||
|
|
||
|
static let kSecondsInDay: Double = 86400.0
|
||
|
static let kMacAppStoreRefreshDelay: Double = 5.0
|
||
|
static let kMacRequestTimeout: Double = 60.0
|
||
|
static let kVersionCheckLastVersionKey = "VersionCheckLastVersionKey"
|
||
|
static let kVersionIgnoreVersionKey = "VersionCheckIgnoreVersionKey"
|
||
|
|
||
|
private var appStoreCountry: String!
|
||
|
private var applicationVersion: String!
|
||
|
private var applicationBundleID: String = Bundle.main.bundleIdentifier ?? "N/A"
|
||
|
private var updatePriority: VersionUpdateHandlerPriority = VersionUpdateHandlerPriority.defaultPri
|
||
|
private var useAllAvailableLanguages: Bool = true
|
||
|
private var onlyPromptIfMainWindowIsAvailable: Bool = true
|
||
|
private var checkAtLaunch: Bool = true
|
||
|
private var checkPeriod: Float = 0.0
|
||
|
private var remindPeriod: Float = 1.0
|
||
|
private var verboseLogging: Bool = true
|
||
|
|
||
|
private var showOnFirstLaunch: Bool = false
|
||
|
public var previewMode: Bool = false
|
||
|
private var versionDetails: String?
|
||
|
|
||
|
override init() {
|
||
|
// Setup App Store Country
|
||
|
appStoreCountry = Locale.current.regionCode
|
||
|
if appStoreCountry == "150" {
|
||
|
appStoreCountry = "eu"
|
||
|
} else if appStoreCountry.replacingOccurrences(of: "[A-Za-z]{2}", with: "", options: .regularExpression, range: appStoreCountry.startIndex ..< appStoreCountry.endIndex).count > 0 {
|
||
|
appStoreCountry = "us"
|
||
|
}
|
||
|
|
||
|
// Setup App Version
|
||
|
var appVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String
|
||
|
if appVersion == nil {
|
||
|
appVersion = Bundle.main.object(forInfoDictionaryKey: kCFBundleVersionKey as String) as? String
|
||
|
}
|
||
|
|
||
|
applicationVersion = appVersion ?? "N/A"
|
||
|
|
||
|
// Bundle Identifier
|
||
|
|
||
|
super.init()
|
||
|
}
|
||
|
|
||
|
private func shouldCheckForNewVersion() -> Bool {
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
private func applicationLaunched() {
|
||
|
if checkAtLaunch {
|
||
|
checkIfNewVersion()
|
||
|
} else if verboseLogging {
|
||
|
print("iVersion will not check for updatess because checkAtLaunch option is disabled")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private func lastVersion() -> String {
|
||
|
return UserDefaults.standard.object(forKey: VersionUpdateHandler.kVersionCheckLastVersionKey) as? String ?? ""
|
||
|
}
|
||
|
|
||
|
private func setLastReminded(_ date: Date?) {
|
||
|
UserDefaults.standard.set(date, forKey: VersionUpdateHandler.kVersionIgnoreVersionKey)
|
||
|
}
|
||
|
|
||
|
private func versionDetails(_ version: String, _ dict: [String: Any]) -> String? {
|
||
|
if let versionData = dict[version] as? String {
|
||
|
return versionData
|
||
|
} else if let versionDataArray = dict[version] as? NSArray {
|
||
|
return versionDataArray.componentsJoined(by: "\n")
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
private func setViewedVersionDetails(_ viewed: Bool) {
|
||
|
UserDefaults.standard.set(viewed ? applicationVersion : nil, forKey: VersionUpdateHandler.kVersionCheckLastVersionKey)
|
||
|
}
|
||
|
|
||
|
private func viewedVersionDetails() -> Bool {
|
||
|
let lastVersionKey = UserDefaults.standard.object(forKey: VersionUpdateHandler.kVersionCheckLastVersionKey) as? String ?? ""
|
||
|
return lastVersionKey == applicationVersion
|
||
|
}
|
||
|
|
||
|
private func localVersionsDict() -> [String: Any] {
|
||
|
return [String: Any]()
|
||
|
}
|
||
|
|
||
|
private func versionDetailsString() -> String {
|
||
|
if versionDetails == nil {
|
||
|
if viewedVersionDetails() {
|
||
|
versionDetails = versionDetails(applicationVersion, localVersionsDict())
|
||
|
}
|
||
|
} else {
|
||
|
versionDetails = versionDetails(lastVersion(), localVersionsDict())
|
||
|
}
|
||
|
|
||
|
return versionDetails!
|
||
|
}
|
||
|
|
||
|
private func checkIfNewVersion() {
|
||
|
if onlyPromptIfMainWindowIsAvailable {
|
||
|
guard NSApplication.shared.mainWindow != nil else {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
_ = Repeater(interval: .seconds(5), mode: .infinite) { _ in
|
||
|
OperationQueue.main.addOperation { [weak self] in
|
||
|
guard let self = self else {
|
||
|
return
|
||
|
}
|
||
|
self.checkIfNewVersion()
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let lastVersionString = lastVersion()
|
||
|
if lastVersionString.count > 0 || showOnFirstLaunch || previewMode {
|
||
|
if applicationVersion.compareVersion(lastVersionString) == ComparisonResult.orderedDescending || previewMode {
|
||
|
// Clear Reminder
|
||
|
setLastReminded(nil)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
extension String {
|
||
|
func compareVersion(_ version: String) -> ComparisonResult {
|
||
|
return compare(version,
|
||
|
options: CompareOptions.numeric,
|
||
|
range: nil,
|
||
|
locale: nil)
|
||
|
}
|
||
|
|
||
|
func compareVersionDescending(_ version: String) -> ComparisonResult {
|
||
|
let comparsionResult = (0 - compareVersion(version).rawValue)
|
||
|
switch comparsionResult {
|
||
|
case -1:
|
||
|
return ComparisonResult.orderedAscending
|
||
|
case 0:
|
||
|
return ComparisonResult.orderedSame
|
||
|
case 1:
|
||
|
return ComparisonResult.orderedDescending
|
||
|
default:
|
||
|
assertionFailure("Invalid Comparison Result")
|
||
|
return .orderedSame
|
||
|
}
|
||
|
}
|
||
|
}
|