CloverBootloader/CloverApp/Clover/AppDelegate.swift
vectorsigma72 6aac20b758 Clover.app v1.22
Improved Clover installer with better detailed log.
2020-05-13 19:09:30 +02:00

225 lines
8.2 KiB
Swift

//
// AppDelegate.swift
// Clover
//
// Created by vector sigma on 19/10/2019.
// Copyright © 2019 CloverHackyColor. All rights reserved.
//
import Cocoa
// MARK: NSApplication shared delegate
let AppSD = NSApplication.shared.delegate as! AppDelegate
let localeBundle = Bundle(path: Bundle.main.sharedSupportPath! + "/Lang.bundle")
@NSApplicationMain
final class AppDelegate: NSObject, NSApplicationDelegate, NSPopoverDelegate {
var canDrawConcurrently : Bool = false
var documentsPaths : [String] = [String]()
var havefinishLaunching : Bool = false
let CloverRevision : Int = Int(findCloverRevision() ?? "0") ?? 0
var isInstalling : Bool = false
var isInstallerOpen : Bool = false
var themeUser = UDs.string(forKey: kThemeUserKey) ?? kDefaultThemeUser
var themeRepo = UDs.string(forKey: kThemeRepoKey) ?? kDefaultThemeRepo
var themes : [String] = [String]()
var installedThemes : [String] = [String]()
var popover : NSPopover?
let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
var settingsWC: SettingsWindowController? = nil
var installerWC : InstallerWindowController? = nil
var installerOutWC : InstallerOutWindowController? = nil
var themeManagerWC : ThemeManagerWC?
var daSession : DASession? = nil
var daContext : UnsafeMutablePointer<Int> = UnsafeMutablePointer<Int>.allocate(capacity: 1)
//MARK: deinit
deinit {
if (self.daSession != nil) {
DASessionUnscheduleFromRunLoop(self.daSession!,
CFRunLoopGetCurrent(),
CFRunLoopMode.defaultMode.rawValue)
}
self.daContext.deallocate()
}
//MARK: Applicatin Delegate
func applicationDidBecomeActive(_ notification: Notification) {
// print("applicationDidBecomeActive")
}
func applicationWillFinishLaunching(_ notification: Notification) {
/*
do not activate the following code: is for debug only
.. it delete stored preferences in the User Default dictionary
if let domain = Bundle.main.bundleIdentifier {
UDs.removePersistentDomain(forName: domain)
UDs.synchronize()
}
the following is to dump info about all disk in the System
let diskLog = "- getAlldisks() -----------------\n\(getAlldisks())\n- getAllESPs() ------------------\n\(getAllESPs())\n---------------------------------"
try? diskLog.write(toFile: NSHomeDirectory().addPath("Desktop/diskLog.txt"), atomically: true, encoding: .utf8)
*/
let pi = NSRunningApplication.current.processIdentifier
let runnings =
NSRunningApplication.runningApplications(withBundleIdentifier: Bundle.main.bundleIdentifier!)
for app in runnings {
if app.processIdentifier != pi {
print("App terminated because another instance is already running, which is newer is unknown:")
print("ensure the old version (may be the running one?) is not marked as login item and quit it.")
NSApp.terminate(self)
}
}
}
func applicationDidFinishLaunching(_ aNotification: Notification) {
self.havefinishLaunching = true
let appImage : NSImage? = NSImage(named: "NSApplicationIcon")?.copy() as? NSImage
if #available(OSX 10.10, *) {
let size = self.statusItem.button!.frame.height - 3
appImage?.size = NSMakeSize(size, size)
self.statusItem.button?.image = appImage?.copy() as? NSImage
self.statusItem.button?.image?.isTemplate = true
if let button = self.statusItem.button {
button.target = self
button.action = #selector(self.showPopover(_:))
button.sendAction(on: [.leftMouseUp, .rightMouseUp])
button.imagePosition = .imageLeft
}
} else {
appImage?.size = NSMakeSize(18.0, 18.0);
self.statusItem.image = appImage?.copy() as? NSImage
self.statusItem.target = self
self.statusItem.action = #selector(self.showPopover(_:))
self.statusItem.sendAction(on: [.leftMouseUp, .rightMouseUp])
}
self.settingsWC = SettingsWindowController.loadFromNib()
NotificationCenter.default.addObserver(self,
selector: #selector(self.reFreshDisksList),
name: Notification.Name("DiskDisappeared"),
object: nil)
NSWorkspace.shared.notificationCenter.addObserver(self,
selector: #selector(self.reFreshDisksList),
name: NSWorkspace.didMountNotification,
object: nil)
NSWorkspace.shared.notificationCenter.addObserver(self,
selector: #selector(self.reFreshDisksList),
name: NSWorkspace.didUnmountNotification,
object: nil)
NSWorkspace.shared.notificationCenter.addObserver(self,
selector: #selector(self.reFreshDisksList),
name: NSWorkspace.didRenameVolumeNotification,
object: nil)
self.daSession = DASessionCreate(kCFAllocatorDefault)
if (self.daSession != nil) {
self.daContext.initialize(repeating: 0, count: 1)
DASessionScheduleWithRunLoop(self.daSession!,
CFRunLoopGetCurrent(),
CFRunLoopMode.defaultMode.rawValue)
DARegisterDiskDisappearedCallback(self.daSession!, nil, {
(dis, ctx) -> Void in
if (ctx != nil) {
NotificationCenter.default.post(name: Notification.Name("DiskDisappeared"), object: dis)
}
}, self.daContext)
}
CFRunLoopRun()
}
//MARK: Disks obeservation call back
@objc func reFreshDisksList() {
(self.settingsWC?.contentViewController as? SettingsViewController)?.searchDisks()
(self.settingsWC?.contentViewController as? SettingsViewController)?.searchESPDisks()
(self.installerWC?.contentViewController as? InstallerViewController)?.populateTargets()
(self.installerOutWC?.contentViewController as? InstallerOutViewController)?.populateTargets()
}
//MARK: Documents
func applicationShouldOpenUntitledFile(_ sender: NSApplication) -> Bool {
if !self.havefinishLaunching {
if let files : NSArray = UDs.value(forKey: "Docs") as? NSArray {
for f in files {
loadPlist(at: f as! String)
}
}
}
return false
}
//MARK: Activation Policy
func setActivationPolicy() {
let documents = NSDocumentController.shared.documents
var showDock : Bool = documents.count > 1
if !showDock {
showDock = AppSD.installerWC != nil || AppSD.installerOutWC != nil || AppSD.themeManagerWC != nil
}
NSApp.setActivationPolicy(showDock ? .regular : .accessory)
if showDock {
NSApp.activate(ignoringOtherApps: true)
}
}
//MARK: Popover
@objc func showPopover(_ sender: Any?) {
if (self.popover == nil) {
self.popover = NSPopover()
self.popover?.animates = true
self.popover?.contentViewController = self.settingsWC?.contentViewController
self.popover?.behavior = .transient
self.popover?.delegate = self
}
DispatchQueue.main.async {
(self.popover?.contentViewController as? SettingsViewController)?.setUpInfo()
}
DispatchQueue.main.async {
if #available(OSX 10.10, *) {
if let button = sender as? NSStatusBarButton {
self.popover?.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.maxY)
}
} else {
if let v = sender as? NSView {
self.popover?.show(relativeTo: v.bounds, of: v, preferredEdge: NSRectEdge.maxY)
}
}
}
}
func popoverShouldDetach(_ popover: NSPopover) -> Bool {
return true
}
//MARK: App termination
func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
return self.isInstalling ? .terminateLater : .terminateNow
}
func applicationWillTerminate(_ aNotification: Notification) {
}
}