|
@@ -86,6 +86,7 @@ final class ViewController: NSViewController {
|
|
86
|
private weak var scheduleFilterDropdown: NSPopUpButton?
|
86
|
private weak var scheduleFilterDropdown: NSPopUpButton?
|
|
87
|
private weak var scheduleGoogleAuthButton: NSButton?
|
87
|
private weak var scheduleGoogleAuthButton: NSButton?
|
|
88
|
private var scheduleGoogleAuthButtonWidthConstraint: NSLayoutConstraint?
|
88
|
private var scheduleGoogleAuthButtonWidthConstraint: NSLayoutConstraint?
|
|
|
|
89
|
+ private var scheduleGoogleAuthHovering = false
|
|
89
|
private var scheduleCurrentProfile: GoogleProfileDisplay?
|
90
|
private var scheduleCurrentProfile: GoogleProfileDisplay?
|
|
90
|
private var scheduleProfileImageTask: Task<Void, Never>?
|
91
|
private var scheduleProfileImageTask: Task<Void, Never>?
|
|
91
|
|
92
|
|
|
@@ -1895,7 +1896,7 @@ private extension ViewController {
|
|
1895
|
}
|
1896
|
}
|
|
1896
|
|
1897
|
|
|
1897
|
private func makeGoogleAuthButton() -> NSButton {
|
1898
|
private func makeGoogleAuthButton() -> NSButton {
|
|
1898
|
- let button = NSButton(title: "", target: self, action: #selector(scheduleConnectButtonPressed(_:)))
|
|
|
|
|
|
1899
|
+ let button = HoverButton(title: "", target: self, action: #selector(scheduleConnectButtonPressed(_:)))
|
|
1899
|
button.translatesAutoresizingMaskIntoConstraints = false
|
1900
|
button.translatesAutoresizingMaskIntoConstraints = false
|
|
1900
|
button.isBordered = false
|
1901
|
button.isBordered = false
|
|
1901
|
button.bezelStyle = .regularSquare
|
1902
|
button.bezelStyle = .regularSquare
|
|
@@ -1904,8 +1905,8 @@ private extension ViewController {
|
|
1904
|
button.layer?.borderWidth = 1
|
1905
|
button.layer?.borderWidth = 1
|
|
1905
|
button.font = NSFont.systemFont(ofSize: 14, weight: .semibold)
|
1906
|
button.font = NSFont.systemFont(ofSize: 14, weight: .semibold)
|
|
1906
|
button.imagePosition = .imageLeading
|
1907
|
button.imagePosition = .imageLeading
|
|
1907
|
- button.alignment = .left
|
|
|
|
1908
|
- button.imageHugsTitle = false
|
|
|
|
|
|
1908
|
+ button.alignment = .center
|
|
|
|
1909
|
+ button.imageHugsTitle = true
|
|
1909
|
button.lineBreakMode = .byTruncatingTail
|
1910
|
button.lineBreakMode = .byTruncatingTail
|
|
1910
|
button.contentTintColor = palette.textPrimary
|
1911
|
button.contentTintColor = palette.textPrimary
|
|
1911
|
button.imageScaling = .scaleNone
|
1912
|
button.imageScaling = .scaleNone
|
|
@@ -1913,6 +1914,11 @@ private extension ViewController {
|
|
1913
|
let widthConstraint = button.widthAnchor.constraint(equalToConstant: 248)
|
1914
|
let widthConstraint = button.widthAnchor.constraint(equalToConstant: 248)
|
|
1914
|
widthConstraint.isActive = true
|
1915
|
widthConstraint.isActive = true
|
|
1915
|
scheduleGoogleAuthButtonWidthConstraint = widthConstraint
|
1916
|
scheduleGoogleAuthButtonWidthConstraint = widthConstraint
|
|
|
|
1917
|
+ button.onHoverChanged = { [weak self] hovering in
|
|
|
|
1918
|
+ self?.scheduleGoogleAuthHovering = hovering
|
|
|
|
1919
|
+ self?.applyGoogleAuthButtonSurface()
|
|
|
|
1920
|
+ }
|
|
|
|
1921
|
+ button.onHoverChanged?(false)
|
|
1916
|
return button
|
1922
|
return button
|
|
1917
|
}
|
1923
|
}
|
|
1918
|
|
1924
|
|
|
@@ -2951,7 +2957,6 @@ private extension ViewController {
|
|
2951
|
private func updateGoogleAuthButtonTitle() {
|
2957
|
private func updateGoogleAuthButtonTitle() {
|
|
2952
|
let signedIn = (googleOAuth.loadTokens() != nil)
|
2958
|
let signedIn = (googleOAuth.loadTokens() != nil)
|
|
2953
|
guard let button = scheduleGoogleAuthButton else { return }
|
2959
|
guard let button = scheduleGoogleAuthButton else { return }
|
|
2954
|
- let iconLeftInset: CGFloat = 12
|
|
|
|
2955
|
|
2960
|
|
|
2956
|
let profileName = scheduleCurrentProfile?.name ?? "Google account"
|
2961
|
let profileName = scheduleCurrentProfile?.name ?? "Google account"
|
|
2957
|
let profileEmail = scheduleCurrentProfile?.email ?? "Sign in with Google"
|
2962
|
let profileEmail = scheduleCurrentProfile?.email ?? "Sign in with Google"
|
|
@@ -2968,12 +2973,12 @@ private extension ViewController {
|
|
2968
|
|
2973
|
|
|
2969
|
if signedIn {
|
2974
|
if signedIn {
|
|
2970
|
let symbol = NSImage(systemSymbolName: "person.crop.circle.fill", accessibilityDescription: "Profile")
|
2975
|
let symbol = NSImage(systemSymbolName: "person.crop.circle.fill", accessibilityDescription: "Profile")
|
|
2971
|
- button.image = symbol.flatMap { paddedImage($0, iconSize: NSSize(width: 16, height: 16), leftInset: iconLeftInset) }
|
|
|
|
2972
|
- button.symbolConfiguration = NSImage.SymbolConfiguration(pointSize: 16, weight: .regular)
|
|
|
|
|
|
2976
|
+ button.image = symbol.flatMap { resizedImage($0, to: NSSize(width: 20, height: 20)) }
|
|
|
|
2977
|
+ button.symbolConfiguration = NSImage.SymbolConfiguration(pointSize: 20, weight: .regular)
|
|
2973
|
button.contentTintColor = palette.textPrimary
|
2978
|
button.contentTintColor = palette.textPrimary
|
|
2974
|
} else {
|
2979
|
} else {
|
|
2975
|
if let g = NSImage(named: "GoogleGLogo") {
|
2980
|
if let g = NSImage(named: "GoogleGLogo") {
|
|
2976
|
- button.image = paddedImage(g, iconSize: NSSize(width: 16, height: 16), leftInset: iconLeftInset)
|
|
|
|
|
|
2981
|
+ button.image = resizedImage(g, to: NSSize(width: 20, height: 20))
|
|
2977
|
} else {
|
2982
|
} else {
|
|
2978
|
button.image = nil
|
2983
|
button.image = nil
|
|
2979
|
}
|
2984
|
}
|
|
@@ -2981,9 +2986,7 @@ private extension ViewController {
|
|
2981
|
}
|
2986
|
}
|
|
2982
|
button.contentTintColor = signedIn ? palette.textPrimary : nil
|
2987
|
button.contentTintColor = signedIn ? palette.textPrimary : nil
|
|
2983
|
|
2988
|
|
|
2984
|
- let isDark = darkModeEnabled
|
|
|
|
2985
|
- button.layer?.backgroundColor = isDark ? NSColor(calibratedRed: 8.0 / 255.0, green: 14.0 / 255.0, blue: 24.0 / 255.0, alpha: 1).cgColor : NSColor.white.cgColor
|
|
|
|
2986
|
- button.layer?.borderColor = (isDark ? NSColor(calibratedWhite: 0.50, alpha: 1) : NSColor(calibratedWhite: 0.72, alpha: 1)).cgColor
|
|
|
|
|
|
2989
|
+ applyGoogleAuthButtonSurface()
|
|
2987
|
}
|
2990
|
}
|
|
2988
|
|
2991
|
|
|
2989
|
private func makeGoogleProfileDisplay(from profile: GoogleUserProfile) -> GoogleProfileDisplay {
|
2992
|
private func makeGoogleProfileDisplay(from profile: GoogleUserProfile) -> GoogleProfileDisplay {
|
|
@@ -3010,7 +3013,7 @@ private extension ViewController {
|
|
3010
|
if Task.isCancelled { return }
|
3013
|
if Task.isCancelled { return }
|
|
3011
|
guard let image = NSImage(data: data) else { return }
|
3014
|
guard let image = NSImage(data: data) else { return }
|
|
3012
|
await MainActor.run {
|
3015
|
await MainActor.run {
|
|
3013
|
- self?.scheduleGoogleAuthButton?.image = self?.paddedImage(image, iconSize: NSSize(width: 16, height: 16), leftInset: 12)
|
|
|
|
|
|
3016
|
+ self?.scheduleGoogleAuthButton?.image = self?.resizedImage(image, to: NSSize(width: 20, height: 20))
|
|
3014
|
self?.scheduleGoogleAuthButton?.contentTintColor = nil
|
3017
|
self?.scheduleGoogleAuthButton?.contentTintColor = nil
|
|
3015
|
}
|
3018
|
}
|
|
3016
|
} catch {
|
3019
|
} catch {
|
|
@@ -3031,17 +3034,22 @@ private extension ViewController {
|
|
3031
|
return result
|
3034
|
return result
|
|
3032
|
}
|
3035
|
}
|
|
3033
|
|
3036
|
|
|
3034
|
- private func paddedImage(_ image: NSImage, iconSize: NSSize, leftInset: CGFloat) -> NSImage {
|
|
|
|
3035
|
- let canvasSize = NSSize(width: iconSize.width + leftInset, height: iconSize.height)
|
|
|
|
3036
|
- let result = NSImage(size: canvasSize)
|
|
|
|
3037
|
- result.lockFocus()
|
|
|
|
3038
|
- image.draw(in: NSRect(x: leftInset, y: 0, width: iconSize.width, height: iconSize.height),
|
|
|
|
3039
|
- from: NSRect(origin: .zero, size: image.size),
|
|
|
|
3040
|
- operation: .copy,
|
|
|
|
3041
|
- fraction: 1.0)
|
|
|
|
3042
|
- result.unlockFocus()
|
|
|
|
3043
|
- result.isTemplate = false
|
|
|
|
3044
|
- return result
|
|
|
|
|
|
3037
|
+ private func applyGoogleAuthButtonSurface() {
|
|
|
|
3038
|
+ guard let button = scheduleGoogleAuthButton else { return }
|
|
|
|
3039
|
+ let isDark = darkModeEnabled
|
|
|
|
3040
|
+ let baseBackground = isDark
|
|
|
|
3041
|
+ ? NSColor(calibratedRed: 8.0 / 255.0, green: 14.0 / 255.0, blue: 24.0 / 255.0, alpha: 1)
|
|
|
|
3042
|
+ : NSColor.white
|
|
|
|
3043
|
+ let hoverBlend = isDark ? NSColor.white : NSColor.black
|
|
|
|
3044
|
+ let hoverBackground = baseBackground.blended(withFraction: 0.07, of: hoverBlend) ?? baseBackground
|
|
|
|
3045
|
+ let baseBorder = isDark
|
|
|
|
3046
|
+ ? NSColor(calibratedWhite: 0.50, alpha: 1)
|
|
|
|
3047
|
+ : NSColor(calibratedWhite: 0.72, alpha: 1)
|
|
|
|
3048
|
+ let hoverBorder = isDark
|
|
|
|
3049
|
+ ? NSColor(calibratedWhite: 0.62, alpha: 1)
|
|
|
|
3050
|
+ : NSColor(calibratedWhite: 0.56, alpha: 1)
|
|
|
|
3051
|
+ button.layer?.backgroundColor = (scheduleGoogleAuthHovering ? hoverBackground : baseBackground).cgColor
|
|
|
|
3052
|
+ button.layer?.borderColor = (scheduleGoogleAuthHovering ? hoverBorder : baseBorder).cgColor
|
|
3045
|
}
|
3053
|
}
|
|
3046
|
|
3054
|
|
|
3047
|
@MainActor
|
3055
|
@MainActor
|