Files
Pearcleaner/Pearcleaner/Windows/MenuBarItem.swift
T
2024-03-19 16:21:01 -06:00

88 lines
2.7 KiB
Swift

//
// MenuBarItem.swift
// Pearcleaner
//
// Created by Alin Lupascu on 3/16/24.
//
import AppKit
import SwiftUI
class MenuBarExtraManager {
static let shared = MenuBarExtraManager()
private var statusItem: NSStatusItem?
private var popover = NSPopover()
// Store the last view and icon for restart
private var lastView: (() -> AnyView)?
private var lastIcon: String?
func addMenuBarExtra<V: View>(withView view: @escaping () -> V, icon: String) {
guard statusItem == nil else { return }
// Remember the last view and icon
lastView = { AnyView(view()) }
lastIcon = icon
// Initialize the status item
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
// Set up the status item's button
if let button = statusItem?.button{
if NSImage(systemSymbolName: icon, accessibilityDescription: nil) != nil {
button.image = NSImage(systemSymbolName: icon, accessibilityDescription: "Pearcleaner")
} else {
button.image = NSImage(named: icon)
}
button.action = #selector(togglePopover(_:))
button.target = self
button.sendAction(on: [.leftMouseDown, .rightMouseDown])
}
// Set up the popover
popover.contentSize = NSSize(width: 300, height: 370)
popover.behavior = .transient
popover.contentViewController = NSHostingController(rootView: view())
}
func removeMenuBarExtra() {
if let item = statusItem {
NSStatusBar.system.removeStatusItem(item)
statusItem = nil
}
}
func swapMenuBarIcon(icon: String) {
guard let button = statusItem?.button else { return }
if let image = NSImage(systemSymbolName: icon, accessibilityDescription: nil) {
button.image = image
} else {
button.image = NSImage(named: icon)
}
}
func restartMenuBarExtra() {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.removeMenuBarExtra()
// Ensure the last view and icon are available before re-adding
if let lastView = self.lastView, let lastIcon = self.lastIcon {
self.addMenuBarExtra(withView: lastView, icon: lastIcon)
}
}
}
@objc func togglePopover(_ sender: AnyObject?) {
if let button = statusItem?.button {
if popover.isShown {
popover.performClose(sender)
} else {
popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY)
}
}
}
}