import SwiftUI import MetalKit struct ChartWheelView: NSViewRepresentable { let positions: [PlanetaryPosition]
func updateMenubarText() let now = Date() let moonPhase = getMoonPhase(date: now) statusItem?.button?.title = "🌙 \(moonPhase) ☉ Io"
@objc func togglePopover() if popover == nil popover = NSPopover() popover?.contentViewController = NSHostingController(rootView: QuickWidgetView()) if let popover = popover, let button = statusItem?.button if popover.isShown popover.performClose(nil) else popover.show(relativeTo: button.bounds, of: button, preferredEdge: .minY) io astrology software for mac
func applicationDidFinishLaunching(_ notification: Notification) statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) if let button = statusItem?.button button.title = "☉ Io" button.action = #selector(togglePopover) // Update planetary hour every minute Timer.scheduledTimer(withTimeInterval: 60, repeats: true) _ in self.updateMenubarText() updateMenubarText()
enum HouseSystem: String, CaseIterable case placidus = "Placidus" case koch = "Koch" case wholeSign = "Whole Sign" var popover: NSPopover
func getMoonPhase(date: Date) -> String // Simplified lunar cycle let lunarMonth: Double = 29.53058867 let referenceNewMoon = Date(timeIntervalSince1970: 946684800) // Jan 1 2000 let daysSince = date.timeIntervalSince(referenceNewMoon) / 86400 let phase = daysSince.truncatingRemainder(dividingBy: lunarMonth) / lunarMonth switch phase case 0..<0.125: return "🌑 New" case 0.125..<0.25: return "🌒 Waxing" case 0.25..<0.375: return "🌓 First Q" case 0.375..<0.5: return "🌔 Gibbous" case 0.5..<0.625: return "🌕 Full" case 0.625..<0.75: return "🌖 Waning" case 0.75..<0.875: return "🌗 Last Q" default: return "🌘 Balsamic"
var formattedPosition: String let degrees = Int(degreeInSign) let minutes = Int((degreeInSign.truncatingRemainder(dividingBy: 1)) * 60) return "\(zodiacSign) \(degrees)°\(minutes)'" var popover: NSPopover?
let item = CSSearchableItem(uniqueIdentifier: birthData.id.uuidString, domainIdentifier: "io.astrology.charts", attributeSet: attributeSet) CSSearchableIndex.default().indexSearchableItems([item]) error in if let error = error print("Index error: \(error)")
/// Approximate heliocentric longitude (for demo). Replace with Swiss Ephemeris. static func approximatePosition(planet: Planet, date: Date) -> Double let julianDay = date.timeIntervalSince1970 / 86400 + 2440587.5 let centuries = (julianDay - 2451545.0) / 36525.0 switch planet case .sun: return (280.46646 + 36000.76983 * centuries + 0.0003032 * centuries * centuries) .truncatingRemainder(dividingBy: 360) case .moon: return (218.316 + 13.176396 * (julianDay - 2451545)) .truncatingRemainder(dividingBy: 360) default: return Double.random(in: 0...360) // placeholder
class AppDelegate: NSObject, NSApplicationDelegate var statusItem: NSStatusItem? var popover: NSPopover?