Refine macOS menu bar drop target icon
This commit is contained in:
@@ -81,22 +81,28 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
func updateIcon(config: SyncConfig) {
|
||||
guard controller.uploadProgress == nil else { return }
|
||||
let iconName = config.iconName
|
||||
let image = NSImage(systemSymbolName: iconName, accessibilityDescription: "Cairnquire")
|
||||
?? NSImage(systemSymbolName: "tray.circle.fill", accessibilityDescription: "Cairnquire")
|
||||
dropButton.image = image
|
||||
dropButton.image = makeMenuBarIcon(named: iconName, accessibilityDescription: "Cairnquire")
|
||||
dropButton.setDropTargetActive(false)
|
||||
}
|
||||
|
||||
private func updateIconForUpload(progress: Double?) {
|
||||
if progress != nil {
|
||||
// During upload: show tray.circle (outline)
|
||||
let image = NSImage(systemSymbolName: "tray.circle", accessibilityDescription: "Uploading")
|
||||
dropButton.image = image
|
||||
dropButton.image = makeMenuBarIcon(named: "tray.circle", accessibilityDescription: "Uploading")
|
||||
dropButton.setDropTargetActive(false)
|
||||
} else {
|
||||
// Upload complete: restore normal icon
|
||||
updateIcon(config: controller.config)
|
||||
}
|
||||
}
|
||||
|
||||
private func makeMenuBarIcon(named iconName: String, accessibilityDescription: String) -> NSImage? {
|
||||
let image = NSImage(systemSymbolName: iconName, accessibilityDescription: accessibilityDescription)
|
||||
?? NSImage(systemSymbolName: "tray.circle.fill", accessibilityDescription: accessibilityDescription)
|
||||
image?.isTemplate = true
|
||||
return image
|
||||
}
|
||||
|
||||
func bounceIcon() {
|
||||
guard let button = dropButton else { return }
|
||||
|
||||
@@ -325,19 +331,32 @@ class DropStatusButton: NSButton {
|
||||
}
|
||||
|
||||
private func setup() {
|
||||
isBordered = false
|
||||
bezelStyle = .regularSquare
|
||||
imageScaling = .scaleProportionallyDown
|
||||
registerForDraggedTypes([.fileURL])
|
||||
}
|
||||
|
||||
func setDropTargetActive(_ isActive: Bool) {
|
||||
isBordered = isActive
|
||||
contentTintColor = isActive ? .systemBlue : nil
|
||||
needsDisplay = true
|
||||
}
|
||||
|
||||
override func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation {
|
||||
// Tint icon slightly to indicate drop zone is active
|
||||
if let image = self.image {
|
||||
self.image = image.tinted(with: .systemBlue)
|
||||
let pasteboard = sender.draggingPasteboard
|
||||
guard pasteboard.canReadObject(forClasses: [NSURL.self], options: nil) else {
|
||||
setDropTargetActive(false)
|
||||
return []
|
||||
}
|
||||
|
||||
// Show the button frame only while the menu bar icon is a valid drop target.
|
||||
setDropTargetActive(true)
|
||||
return .copy
|
||||
}
|
||||
|
||||
override func draggingExited(_ sender: NSDraggingInfo?) {
|
||||
// Restore original icon
|
||||
setDropTargetActive(false)
|
||||
if let appDelegate = appDelegate {
|
||||
appDelegate.updateIcon(config: appDelegate.controller.config)
|
||||
}
|
||||
@@ -347,9 +366,11 @@ class DropStatusButton: NSButton {
|
||||
let pasteboard = sender.draggingPasteboard
|
||||
guard let urls = pasteboard.readObjects(forClasses: [NSURL.self], options: nil) as? [URL],
|
||||
!urls.isEmpty else {
|
||||
setDropTargetActive(false)
|
||||
return false
|
||||
}
|
||||
|
||||
setDropTargetActive(false)
|
||||
appDelegate?.bounceIcon()
|
||||
|
||||
Task { @MainActor in
|
||||
@@ -359,18 +380,3 @@ class DropStatusButton: NSButton {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension NSImage {
|
||||
func tinted(with color: NSColor) -> NSImage {
|
||||
let image = self.copy() as! NSImage
|
||||
image.isTemplate = false
|
||||
|
||||
let rect = NSRect(origin: .zero, size: image.size)
|
||||
image.lockFocus()
|
||||
color.set()
|
||||
rect.fill(using: .sourceAtop)
|
||||
image.unlockFocus()
|
||||
|
||||
return image
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user