|
|
|
//
|
|
|
|
// AppDelegate.swift
|
|
|
|
// LunaMac
|
|
|
|
//
|
|
|
|
// Created by Claire Davis on 9/21/22.
|
|
|
|
// Copyright © 2022 A Better Geek. All rights reserved.
|
|
|
|
//
|
|
|
|
/*
|
|
|
|
====== TO DO =======
|
|
|
|
* auto-update at a set interval
|
|
|
|
* make help menu item work (show the window)
|
|
|
|
*/
|
|
|
|
|
|
|
|
import Cocoa
|
|
|
|
import Foundation
|
|
|
|
import CoreFoundation
|
|
|
|
|
|
|
|
@NSApplicationMain
|
|
|
|
class AppDelegate: NSObject, NSApplicationDelegate {
|
|
|
|
|
|
|
|
// make sure applet stays in memory
|
|
|
|
var statusBarItem: NSStatusItem?
|
|
|
|
|
|
|
|
// static array of possible lunar values
|
|
|
|
let phaseArray:[String:[String:NSString]] = [
|
|
|
|
"new" : [
|
|
|
|
"nice" : "New Moon",
|
|
|
|
"start" : "0",
|
|
|
|
"end" : "1",
|
|
|
|
"icon" : "🌑"
|
|
|
|
],
|
|
|
|
"waxc" : [
|
|
|
|
"nice" : "Waxing Crescent",
|
|
|
|
"start" : "1",
|
|
|
|
"end" : "6.38264692644",
|
|
|
|
"icon" : "🌒"
|
|
|
|
],
|
|
|
|
"firstq" : [
|
|
|
|
"nice" : "First Quarter",
|
|
|
|
"start" : "6.38264692644",
|
|
|
|
"end" : "8.38264692644",
|
|
|
|
"icon" : "🌓"
|
|
|
|
],
|
|
|
|
"waxg" : [
|
|
|
|
"nice" : "Waxing Gibbous",
|
|
|
|
"start" : "8.38264692644",
|
|
|
|
"end" : "13.76529385288",
|
|
|
|
"icon" : "🌔"
|
|
|
|
],
|
|
|
|
"full" : [
|
|
|
|
"nice" : "Full Moon",
|
|
|
|
"start" : "13.76529385288",
|
|
|
|
"end" : "15.76529385288",
|
|
|
|
"icon" : "🌕"
|
|
|
|
],
|
|
|
|
"wang" : [
|
|
|
|
"nice" : "Waning Gibbous",
|
|
|
|
"start" : "15.76529385288",
|
|
|
|
"end" : "21.14794077932",
|
|
|
|
"icon" : "🌖"
|
|
|
|
],
|
|
|
|
"lastq" : [
|
|
|
|
"nice" : "Last Quarter",
|
|
|
|
"start" : "21.14794077932",
|
|
|
|
"end" : "23.14794077932",
|
|
|
|
"icon" : "🌗"
|
|
|
|
],
|
|
|
|
"wanc" : [
|
|
|
|
"nice" : "Waning Crescent",
|
|
|
|
"start" : "23.14794077932",
|
|
|
|
"end" : "28.53058770576",
|
|
|
|
"icon" : "🌘"
|
|
|
|
],
|
|
|
|
"new2" : [
|
|
|
|
"nice" : "New Moon",
|
|
|
|
"start" : "28.53058770576",
|
|
|
|
"end" : "29.53058770576",
|
|
|
|
"icon" : "🌑"
|
|
|
|
],
|
|
|
|
"default" : [
|
|
|
|
"nice" : "Failed to calculate.",
|
|
|
|
"icon" : "🌙"
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
|
|
|
updateIcon()
|
|
|
|
|
|
|
|
// try showing the xib dialog
|
|
|
|
var x = NSWindowController(windowNibName: "InfoBox")
|
|
|
|
x.loadWindow()
|
|
|
|
|
|
|
|
var m = NSWindowController(windowNibName: "MainMenu")
|
|
|
|
m.loadWindow()
|
|
|
|
}
|
|
|
|
|
|
|
|
@objc func buildMenu(key: String = "default") {
|
|
|
|
// get system-wide menu bar
|
|
|
|
let statusBar = NSStatusBar.system
|
|
|
|
|
|
|
|
// set icon size to square
|
|
|
|
statusBarItem = statusBar.statusItem(withLength: NSStatusItem.squareLength)
|
|
|
|
|
|
|
|
// set icon using emoji
|
|
|
|
statusBarItem?.button?.title = phaseArray[key]?["icon"] as String? ?? "🌙"
|
|
|
|
|
|
|
|
// create a menu for the icon
|
|
|
|
let statusBarMenu = NSMenu(title: "LunaMac Menu")
|
|
|
|
|
|
|
|
// add the menu to the menu bar icon
|
|
|
|
statusBarItem?.menu = statusBarMenu
|
|
|
|
|
|
|
|
let topTxt = phaseArray["default"]?["nice"] as String? ?? ""
|
|
|
|
|
|
|
|
// add menu items to the menu
|
|
|
|
if (!topTxt.isEmpty) {
|
|
|
|
statusBarMenu.addItem(
|
|
|
|
withTitle: phaseArray[key]?["nice"] as String? ?? topTxt,
|
|
|
|
action: nil,
|
|
|
|
keyEquivalent: ""
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
statusBarMenu.addItem(
|
|
|
|
withTitle: "Update moon phase",
|
|
|
|
action: #selector(AppDelegate.updateIcon),
|
|
|
|
keyEquivalent: ""
|
|
|
|
)
|
|
|
|
|
|
|
|
statusBarMenu.addItem(
|
|
|
|
withTitle: "Quit LunaMac",
|
|
|
|
action: #selector(AppDelegate.quitApp),
|
|
|
|
keyEquivalent: ""
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// update menu bar icon
|
|
|
|
@objc func updateIcon() {
|
|
|
|
// current system time in UTC
|
|
|
|
let sysDate = Date()
|
|
|
|
// get baseline date
|
|
|
|
// let baseDateStr = "2000-01-06 18:14:00 +0000"
|
|
|
|
|
|
|
|
// create date object from baseDate
|
|
|
|
// date components
|
|
|
|
var bdc = DateComponents()
|
|
|
|
bdc.year = 2000
|
|
|
|
bdc.month = 1
|
|
|
|
bdc.day = 6
|
|
|
|
bdc.hour = 18
|
|
|
|
bdc.minute = 14
|
|
|
|
// create date object
|
|
|
|
let ucal = Calendar(identifier: .gregorian)
|
|
|
|
let baseDate = ucal.date(from: bdc)
|
|
|
|
|
|
|
|
// days in a lunar cycle
|
|
|
|
let lunarDays = 29.53058770576
|
|
|
|
// seconds in a lunar cycle
|
|
|
|
let lunarSecs = lunarDays * (24 * 60 * 60)
|
|
|
|
|
|
|
|
// calculate seconds between sysDate and baseDate
|
|
|
|
// if baseDate is nil, default to current system time
|
|
|
|
let totalSecs = sysDate.timeIntervalSince(baseDate ?? Date())
|
|
|
|
|
|
|
|
if (totalSecs.sign != .minus) {
|
|
|
|
// a positive number is valid
|
|
|
|
// % calculates seconds of current cycle
|
|
|
|
let currSecs = totalSecs.truncatingRemainder(dividingBy: lunarSecs)
|
|
|
|
let currFrac = currSecs / lunarSecs
|
|
|
|
let currDays = currFrac * lunarDays
|
|
|
|
|
|
|
|
var newArr = [String:[String:NSString]]()
|
|
|
|
|
|
|
|
newArr = phaseArray.filter{findPhase(key: $0.key, val: $0.value, start: $0.value["start"]?.doubleValue ?? 0, end: $0.value["end"]?.doubleValue ?? 0, curr: currDays)}
|
|
|
|
|
|
|
|
// we want newArr[0].value which is [String:NSString]
|
|
|
|
let theKey = newArr.first!.key
|
|
|
|
buildMenu(key: theKey)
|
|
|
|
} else {
|
|
|
|
// if dateDiff is negative, something went wrong.
|
|
|
|
buildMenu()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@objc func findPhase(key: String, val: [String:NSString], start: Double, end: Double, curr: Double) -> Bool {
|
|
|
|
|
|
|
|
if ((curr >= start) && (curr <= end)) {
|
|
|
|
return true
|
|
|
|
} else {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// quit application
|
|
|
|
@objc func quitApp() {
|
|
|
|
NSApp.terminate(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
func applicationWillTerminate(_ aNotification: Notification) {
|
|
|
|
// Insert code here to tear down your application
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|