Fix menu bar icon
This commit is contained in:
@@ -8,6 +8,8 @@ import Library
|
|||||||
public class StatusBarController: NSObject, NSMenuDelegate {
|
public class StatusBarController: NSObject, NSMenuDelegate {
|
||||||
private var statusItem: NSStatusItem?
|
private var statusItem: NSStatusItem?
|
||||||
private var statusItemView: StatusBarItemView?
|
private var statusItemView: StatusBarItemView?
|
||||||
|
private var menuIcon: NSImage?
|
||||||
|
private var isIconOnlyMode = true
|
||||||
private let environments: ExtensionEnvironments
|
private let environments: ExtensionEnvironments
|
||||||
private var commandClient: CommandClient?
|
private var commandClient: CommandClient?
|
||||||
private var cancellables = Set<AnyCancellable>()
|
private var cancellables = Set<AnyCancellable>()
|
||||||
@@ -60,27 +62,15 @@ public class StatusBarController: NSObject, NSMenuDelegate {
|
|||||||
|
|
||||||
private func createStatusItem() {
|
private func createStatusItem() {
|
||||||
guard statusItem == nil else { return }
|
guard statusItem == nil else { return }
|
||||||
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
|
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)
|
||||||
|
|
||||||
let button = statusItem!.button!
|
let button = statusItem!.button!
|
||||||
button.image = nil
|
|
||||||
button.title = ""
|
|
||||||
let itemView = StatusBarItemView()
|
|
||||||
itemView.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
button.addSubview(itemView)
|
|
||||||
NSLayoutConstraint.activate([
|
|
||||||
itemView.leadingAnchor.constraint(equalTo: button.leadingAnchor),
|
|
||||||
itemView.trailingAnchor.constraint(equalTo: button.trailingAnchor),
|
|
||||||
itemView.topAnchor.constraint(equalTo: button.topAnchor),
|
|
||||||
itemView.bottomAnchor.constraint(equalTo: button.bottomAnchor),
|
|
||||||
])
|
|
||||||
statusItemView = itemView
|
|
||||||
itemView.attach(to: button)
|
|
||||||
if let image = NSImage(named: "MenuIcon") {
|
if let image = NSImage(named: "MenuIcon") {
|
||||||
image.isTemplate = true
|
image.isTemplate = true
|
||||||
itemView.setIcon(image)
|
menuIcon = image
|
||||||
|
button.image = image
|
||||||
}
|
}
|
||||||
updateStatusItemLength()
|
isIconOnlyMode = true
|
||||||
|
|
||||||
menu = NSMenu()
|
menu = NSMenu()
|
||||||
menu!.delegate = self
|
menu!.delegate = self
|
||||||
@@ -520,16 +510,47 @@ public class StatusBarController: NSObject, NSMenuDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func updateSpeedDisplay(status: LibboxStatusMessage?) {
|
private func updateSpeedDisplay(status: LibboxStatusMessage?) {
|
||||||
guard statusItem != nil else { return }
|
guard let statusItem, let button = statusItem.button else { return }
|
||||||
|
let title: String
|
||||||
if speedMode == .disabled || status == nil || !status!.trafficAvailable {
|
if speedMode == .disabled || status == nil || !status!.trafficAvailable {
|
||||||
statusItemView?.setTitle("")
|
title = ""
|
||||||
} else if speedMode == .enabled {
|
} else if speedMode == .enabled {
|
||||||
statusItemView?.setTitle("\(LibboxFormatBytes(status!.uplink))/s\n\(LibboxFormatBytes(status!.downlink))/s")
|
title = "\(LibboxFormatBytes(status!.uplink))/s\n\(LibboxFormatBytes(status!.downlink))/s"
|
||||||
} else {
|
} else {
|
||||||
statusItemView?.setTitle("\(LibboxFormatBytes(status!.uplink + status!.downlink))/s")
|
title = "\(LibboxFormatBytes(status!.uplink + status!.downlink))/s"
|
||||||
|
}
|
||||||
|
|
||||||
|
let shouldUseIconOnly = title.isEmpty
|
||||||
|
if shouldUseIconOnly != isIconOnlyMode {
|
||||||
|
isIconOnlyMode = shouldUseIconOnly
|
||||||
|
if shouldUseIconOnly {
|
||||||
|
statusItemView?.removeFromSuperview()
|
||||||
|
statusItemView = nil
|
||||||
|
button.image = menuIcon
|
||||||
|
statusItem.length = NSStatusItem.squareLength
|
||||||
|
} else {
|
||||||
|
button.image = nil
|
||||||
|
let itemView = StatusBarItemView()
|
||||||
|
itemView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
button.addSubview(itemView)
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
itemView.leadingAnchor.constraint(equalTo: button.leadingAnchor),
|
||||||
|
itemView.trailingAnchor.constraint(equalTo: button.trailingAnchor),
|
||||||
|
itemView.topAnchor.constraint(equalTo: button.topAnchor),
|
||||||
|
itemView.bottomAnchor.constraint(equalTo: button.bottomAnchor),
|
||||||
|
])
|
||||||
|
statusItemView = itemView
|
||||||
|
itemView.attach(to: button)
|
||||||
|
itemView.setIcon(menuIcon!)
|
||||||
|
itemView.setTitle(title)
|
||||||
|
updateStatusItemLength()
|
||||||
|
}
|
||||||
|
} else if !shouldUseIconOnly {
|
||||||
|
statusItemView?.setTitle(title)
|
||||||
|
updateStatusItemLength()
|
||||||
}
|
}
|
||||||
updateStatusItemLength()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateStatusItemLength() {
|
private func updateStatusItemLength() {
|
||||||
guard let statusItem, let statusItemView else { return }
|
guard let statusItem, let statusItemView else { return }
|
||||||
let width = statusItemView.fittingWidth()
|
let width = statusItemView.fittingWidth()
|
||||||
@@ -620,10 +641,15 @@ public class StatusBarController: NSObject, NSMenuDelegate {
|
|||||||
|
|
||||||
public func menuWillOpen(_: NSMenu) {
|
public func menuWillOpen(_: NSMenu) {
|
||||||
headerView?.refresh()
|
headerView?.refresh()
|
||||||
|
statusItemView?.setHighlighted(true)
|
||||||
Task {
|
Task {
|
||||||
await loadProfiles()
|
await loadProfiles()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func menuDidClose(_: NSMenu) {
|
||||||
|
statusItemView?.setHighlighted(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - StatusBarItemView
|
// MARK: - StatusBarItemView
|
||||||
@@ -651,7 +677,6 @@ private class StatusBarItemView: NSView {
|
|||||||
private var topConstraint: NSLayoutConstraint?
|
private var topConstraint: NSLayoutConstraint?
|
||||||
private var bottomConstraint: NSLayoutConstraint?
|
private var bottomConstraint: NSLayoutConstraint?
|
||||||
private var textWidthConstraint: NSLayoutConstraint?
|
private var textWidthConstraint: NSLayoutConstraint?
|
||||||
private var currentHorizontalPadding = Layout.horizontalPadding
|
|
||||||
|
|
||||||
override init(frame frameRect: NSRect) {
|
override init(frame frameRect: NSRect) {
|
||||||
imageView = NSImageView()
|
imageView = NSImageView()
|
||||||
@@ -718,8 +743,6 @@ private class StatusBarItemView: NSView {
|
|||||||
bottomConstraint!,
|
bottomConstraint!,
|
||||||
textWidthConstraint!,
|
textWidthConstraint!,
|
||||||
])
|
])
|
||||||
|
|
||||||
updateLayout(hasTitle: false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func setIcon(_ image: NSImage) {
|
func setIcon(_ image: NSImage) {
|
||||||
@@ -729,6 +752,7 @@ private class StatusBarItemView: NSView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setTitle(_ title: String) {
|
func setTitle(_ title: String) {
|
||||||
|
guard !title.isEmpty else { return }
|
||||||
currentTitle = title
|
currentTitle = title
|
||||||
updateTitle()
|
updateTitle()
|
||||||
}
|
}
|
||||||
@@ -738,51 +762,39 @@ private class StatusBarItemView: NSView {
|
|||||||
updateHighlight(button.isHighlighted)
|
updateHighlight(button.isHighlighted)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setHighlighted(_ highlighted: Bool) {
|
||||||
|
updateHighlight(highlighted)
|
||||||
|
}
|
||||||
|
|
||||||
func fittingWidth() -> CGFloat {
|
func fittingWidth() -> CGFloat {
|
||||||
layoutSubtreeIfNeeded()
|
layoutSubtreeIfNeeded()
|
||||||
let width = stackView.fittingSize.width + currentHorizontalPadding * 2
|
let width = stackView.fittingSize.width + Layout.horizontalPadding * 2
|
||||||
return ceil(width)
|
return ceil(width)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateTitle() {
|
private func updateTitle() {
|
||||||
let hasTitle = !currentTitle.isEmpty
|
guard !currentTitle.isEmpty else { return }
|
||||||
updateLayout(hasTitle: hasTitle)
|
var attributes = textAttributes
|
||||||
if !hasTitle {
|
attributes[.foregroundColor] = isHighlighted
|
||||||
textField.stringValue = ""
|
? NSColor.unemphasizedSelectedTextColor
|
||||||
textField.isHidden = true
|
: NSColor.labelColor
|
||||||
} else {
|
textField.attributedStringValue = NSAttributedString(string: currentTitle, attributes: attributes)
|
||||||
var attributes = textAttributes
|
textField.isHidden = false
|
||||||
attributes[.foregroundColor] = isHighlighted
|
|
||||||
? NSColor.selectedMenuItemTextColor
|
|
||||||
: NSColor.labelColor
|
|
||||||
textField.attributedStringValue = NSAttributedString(string: currentTitle, attributes: attributes)
|
|
||||||
textField.isHidden = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func updateLayout(hasTitle: Bool) {
|
|
||||||
let horizontalPadding = hasTitle ? Layout.horizontalPadding : 0
|
|
||||||
let verticalPadding = hasTitle ? Layout.verticalPadding : 0
|
|
||||||
currentHorizontalPadding = horizontalPadding
|
|
||||||
leadingConstraint?.constant = horizontalPadding
|
|
||||||
trailingConstraint?.constant = -horizontalPadding
|
|
||||||
topConstraint?.constant = verticalPadding
|
|
||||||
bottomConstraint?.constant = -verticalPadding
|
|
||||||
textWidthConstraint?.constant = hasTitle ? Layout.textWidth : 0
|
|
||||||
stackView.spacing = hasTitle ? Layout.spacing : 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateTintColor() {
|
private func updateTintColor() {
|
||||||
imageView.contentTintColor = isHighlighted
|
imageView.contentTintColor = isHighlighted
|
||||||
? NSColor.selectedMenuItemTextColor
|
? NSColor.unemphasizedSelectedTextColor
|
||||||
: NSColor.labelColor
|
: NSColor.labelColor
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateHighlight(_ highlighted: Bool) {
|
private func updateHighlight(_ highlighted: Bool) {
|
||||||
guard isHighlighted != highlighted else { return }
|
guard isHighlighted != highlighted else { return }
|
||||||
isHighlighted = highlighted
|
isHighlighted = highlighted
|
||||||
|
statusButton?.highlight(isHighlighted)
|
||||||
updateTitle()
|
updateTitle()
|
||||||
updateTintColor()
|
updateTintColor()
|
||||||
|
needsDisplay = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillDraw() {
|
override func viewWillDraw() {
|
||||||
@@ -790,7 +802,7 @@ private class StatusBarItemView: NSView {
|
|||||||
updateHighlight(statusButton?.isHighlighted == true)
|
updateHighlight(statusButton?.isHighlighted == true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func hitTest(_ point: NSPoint) -> NSView? {
|
override func hitTest(_: NSPoint) -> NSView? {
|
||||||
nil
|
nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user