Files
macos-stats/Stats/AppDelegate.swift
Serhiy Mytrovtsiy 8296acb5e9 - fix updater.sh for macOS Mojave (10.14)
- fix notification that new version installed (not showing only if the new version is higher than previous one)

- small fix
2020-07-09 19:11:58 +02:00

218 lines
8.6 KiB
Swift
Executable File

//
// AppDelegate.swift
// Stats
//
// Created by Serhiy Mytrovtsiy on 28.05.2019.
// Copyright © 2019 Serhiy Mytrovtsiy. All rights reserved.
//
import Cocoa
import os.log
import StatsKit
import ModuleKit
import CPU
import Memory
import Disk
import Net
import Battery
import Sensors
var store: Store = Store()
let updater = macAppUpdater(user: "exelban", repo: "stats")
let systemKit: SystemKit = SystemKit()
var smc: SMCService = SMCService()
var modules: [Module] = [Battery(&store), Network(&store), Sensors(&store, &smc), Disk(&store), Memory(&store), CPU(&store, &smc)].reversed()
var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "Stats")
class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDelegate {
private let settingsWindow: SettingsWindow = SettingsWindow()
private let updateWindow: UpdateWindow = UpdateWindow()
private let updateNotification = NSUserNotification()
private let updateActivity = NSBackgroundActivityScheduler(identifier: "eu.exelban.Stats.updateCheck")
func applicationDidFinishLaunching(_ aNotification: Notification) {
let startingPoint = Date()
self.parseArguments()
NotificationCenter.default.addObserver(self, selector: #selector(toggleSettingsHandler), name: .toggleSettings, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(checkForNewVersion), name: .checkForUpdates, object: nil)
modules.forEach{ $0.mount() }
self.settingsWindow.setModules()
self.setVersion()
self.defaultValues()
self.updateCron()
os_log(.info, log: log, "Stats started in %.4f seconds", startingPoint.timeIntervalSinceNow * -1)
}
func userNotificationCenter(_ center: NSUserNotificationCenter, didActivate notification: NSUserNotification) {
if let uri = notification.userInfo?["url"] as? String {
os_log(.error, log: log, "Downloading new version of app...")
if let url = URL(string: uri) {
updater.download(url)
}
}
NSUserNotificationCenter.default.removeDeliveredNotification(self.updateNotification)
}
func applicationWillTerminate(_ aNotification: Notification) {
modules.forEach{ $0.terminate() }
_ = smc.close()
NotificationCenter.default.removeObserver(self)
self.updateActivity.invalidate()
}
func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
if flag {
self.settingsWindow.makeKeyAndOrderFront(self)
} else {
self.settingsWindow.setIsVisible(true)
}
return true
}
@objc private func toggleSettingsHandler(_ notification: Notification) {
if !self.settingsWindow.isVisible {
self.settingsWindow.setIsVisible(true)
self.settingsWindow.makeKeyAndOrderFront(nil)
}
if let name = notification.userInfo?["module"] as? String {
self.settingsWindow.openMenu(name)
}
}
private func setVersion() {
let key = "version"
let currentVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
if !store.exist(key: key) {
store.reset()
os_log(.info, log: log, "Previous version not detected. Current version (%s) set", currentVersion)
} else {
let prevVersion = store.string(key: key, defaultValue: "")
if prevVersion == currentVersion {
return
}
if IsNewestVersion(currentVersion: prevVersion, latestVersion: currentVersion) {
let notification = NSUserNotification()
notification.identifier = UUID().uuidString
notification.title = "Successfully updated"
notification.subtitle = "Stats was updated to the v\(currentVersion)"
notification.soundName = NSUserNotificationDefaultSoundName
notification.hasActionButton = false
NSUserNotificationCenter.default.deliver(notification)
}
os_log(.info, log: log, "Detected previous version %s. Current version (%s) set", prevVersion, currentVersion)
}
store.set(key: key, value: currentVersion)
}
private func parseArguments() {
let args = CommandLine.arguments
if args.contains("--reset") {
os_log(.info, log: log, "Receive --reset argument. Reseting store (UserDefaults)...")
store.reset()
}
if let disableIndex = args.firstIndex(of: "--disable") {
if args.indices.contains(disableIndex+1) {
let disableModules = args[disableIndex+1].split(separator: ",")
disableModules.forEach { (moduleName: Substring) in
if let module = modules.first(where: { $0.config.name.lowercased() == moduleName.lowercased()}) {
module.unmount()
}
}
}
}
if let dmgIndex = args.firstIndex(of: "--dmg") {
if args.indices.contains(dmgIndex+1) {
let dmgPath = args[dmgIndex+1]
let pwd = Bundle.main.bundleURL.absoluteString.replacingOccurrences(of: "file://", with: "").replacingOccurrences(of: "Stats.app/", with: "")
asyncShell("sh \(pwd)/Stats.app/Contents/Resources/Scripts/updater.sh --step 3 --dmg \(dmgPath)")
}
}
}
private func defaultValues() {
if !store.exist(key: "runAtLoginInitialized") {
store.set(key: "runAtLoginInitialized", value: true)
LaunchAtLogin.isEnabled = true
}
if store.exist(key: "dockIcon") {
let dockIconStatus = store.bool(key: "dockIcon", defaultValue: false) ? NSApplication.ActivationPolicy.regular : NSApplication.ActivationPolicy.accessory
NSApp.setActivationPolicy(dockIconStatus)
}
}
@objc private func checkForNewVersion(_ window: Bool = false) {
updater.check() { result, error in
if error != nil {
os_log(.error, log: log, "error updater.check(): %s", "\(error!.localizedDescription)")
return
}
guard error == nil, let version: version = result else {
os_log(.error, log: log, "download error(): %s", "\(error!.localizedDescription)")
return
}
DispatchQueue.main.async(execute: {
if window {
os_log(.error, log: log, "open update window: %s", "\(version.latest)")
self.updateWindow.open(version)
return
}
if version.newest {
os_log(.error, log: log, "show update window because new version of app found: %s", "\(version.latest)")
self.updateNotification.identifier = UUID().uuidString
self.updateNotification.title = "New version available"
self.updateNotification.subtitle = "Click to install the new version of Stats"
self.updateNotification.soundName = NSUserNotificationDefaultSoundName
self.updateNotification.hasActionButton = true
self.updateNotification.actionButtonTitle = "Install"
self.updateNotification.userInfo = ["url": version.url]
NSUserNotificationCenter.default.delegate = self
NSUserNotificationCenter.default.deliver(self.updateNotification)
}
})
}
}
private func updateCron() {
self.updateActivity.repeats = true
self.updateActivity.interval = 60 * 60 * 12 // once in 12 hour
if store.bool(key: "checkUpdatesOnLogin", defaultValue: true) {
self.checkForNewVersion(false)
}
self.updateActivity.schedule { (completion: @escaping NSBackgroundActivityScheduler.CompletionHandler) in
if !store.bool(key: "checkUpdatesOnLogin", defaultValue: true) {
completion(NSBackgroundActivityScheduler.Result.finished)
return
}
self.checkForNewVersion(false)
completion(NSBackgroundActivityScheduler.Result.finished)
}
}
}