|
@@ -215,17 +215,45 @@ private final class SettingsIconBadge: NSView, AppearanceRefreshable {
|
|
|
|
|
|
|
|
// MARK: - Rows
|
|
// MARK: - Rows
|
|
|
|
|
|
|
|
-private class SettingsRowBase: NSView {
|
|
|
|
|
- init(isLast: Bool) {
|
|
|
|
|
|
|
+private class SettingsRowBase: NSView, AppearanceRefreshable {
|
|
|
|
|
+ private var hoverTracker: HoverTracker?
|
|
|
|
|
+ private var isHovered = false
|
|
|
|
|
+ private let isInteractive: Bool
|
|
|
|
|
+
|
|
|
|
|
+ init(isLast: Bool, isInteractive: Bool = false) {
|
|
|
|
|
+ self.isInteractive = isInteractive
|
|
|
super.init(frame: .zero)
|
|
super.init(frame: .zero)
|
|
|
translatesAutoresizingMaskIntoConstraints = false
|
|
translatesAutoresizingMaskIntoConstraints = false
|
|
|
heightAnchor.constraint(equalToConstant: 56).isActive = true
|
|
heightAnchor.constraint(equalToConstant: 56).isActive = true
|
|
|
if !isLast { addDivider() }
|
|
if !isLast { addDivider() }
|
|
|
|
|
+
|
|
|
|
|
+ if isInteractive {
|
|
|
|
|
+ wantsLayer = true
|
|
|
|
|
+ hoverTracker = HoverTracker(view: self) { [weak self] hovering in
|
|
|
|
|
+ self?.setHovered(hovering)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@available(*, unavailable)
|
|
@available(*, unavailable)
|
|
|
required init?(coder: NSCoder) { nil }
|
|
required init?(coder: NSCoder) { nil }
|
|
|
|
|
|
|
|
|
|
+ func refreshAppearance() {
|
|
|
|
|
+ updateHoverAppearance()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private func setHovered(_ hovering: Bool) {
|
|
|
|
|
+ isHovered = hovering
|
|
|
|
|
+ updateHoverAppearance()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private func updateHoverAppearance() {
|
|
|
|
|
+ guard isInteractive else { return }
|
|
|
|
|
+ animateHover {
|
|
|
|
|
+ layer?.backgroundColor = (isHovered ? AppTheme.sidebarHoverBackground : .clear).cgColor
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
func addDivider() {
|
|
func addDivider() {
|
|
|
let divider = NSBox()
|
|
let divider = NSBox()
|
|
|
divider.boxType = .separator
|
|
divider.boxType = .separator
|
|
@@ -267,7 +295,7 @@ private class SettingsRowBase: NSView {
|
|
|
|
|
|
|
|
private final class SettingsActionRow: SettingsRowBase {
|
|
private final class SettingsActionRow: SettingsRowBase {
|
|
|
init(symbolName: String, title: String, isLast: Bool = false, action: @escaping () -> Void) {
|
|
init(symbolName: String, title: String, isLast: Bool = false, action: @escaping () -> Void) {
|
|
|
- super.init(isLast: isLast)
|
|
|
|
|
|
|
+ super.init(isLast: isLast, isInteractive: true)
|
|
|
|
|
|
|
|
let badge = SettingsIconBadge(symbolName: symbolName)
|
|
let badge = SettingsIconBadge(symbolName: symbolName)
|
|
|
let titleLabel = NSTextField.themeLabel(title, style: .primary, font: AppTheme.mediumFont(size: 15))
|
|
let titleLabel = NSTextField.themeLabel(title, style: .primary, font: AppTheme.mediumFont(size: 15))
|
|
@@ -304,7 +332,7 @@ private final class SettingsPopupRow: SettingsRowBase {
|
|
|
|
|
|
|
|
init(symbolName: String, title: String, options: [String], selection: String, isLast: Bool = false, onChange: @escaping (String) -> Void) {
|
|
init(symbolName: String, title: String, options: [String], selection: String, isLast: Bool = false, onChange: @escaping (String) -> Void) {
|
|
|
popupTarget = PopupTarget(handler: onChange)
|
|
popupTarget = PopupTarget(handler: onChange)
|
|
|
- super.init(isLast: isLast)
|
|
|
|
|
|
|
+ super.init(isLast: isLast, isInteractive: true)
|
|
|
|
|
|
|
|
let popup = NSPopUpButton()
|
|
let popup = NSPopUpButton()
|
|
|
popup.bezelStyle = .rounded
|
|
popup.bezelStyle = .rounded
|
|
@@ -326,7 +354,7 @@ private final class SettingsToggleRow: SettingsRowBase {
|
|
|
|
|
|
|
|
init(symbolName: String, title: String, isOn: Bool, isLast: Bool = false, onChange: @escaping (Bool) -> Void) {
|
|
init(symbolName: String, title: String, isOn: Bool, isLast: Bool = false, onChange: @escaping (Bool) -> Void) {
|
|
|
toggleTarget = ToggleTarget(handler: onChange)
|
|
toggleTarget = ToggleTarget(handler: onChange)
|
|
|
- super.init(isLast: isLast)
|
|
|
|
|
|
|
+ super.init(isLast: isLast, isInteractive: true)
|
|
|
|
|
|
|
|
let toggle = NSSwitch()
|
|
let toggle = NSSwitch()
|
|
|
toggle.state = isOn ? .on : .off
|
|
toggle.state = isOn ? .on : .off
|