@ -15,7 +15,7 @@ class Themer: NSObject {
case solarizedLight
case solarizedDark
}
private static var sharedInstance = Themer ( index : UserDefaults . standard . integer ( forKey : UserDefaultKeys . themeKey ) )
private var effectiveApperanceObserver : NSKeyValueObservation ?
private var themeIndex : Theme {
@ -23,7 +23,7 @@ class Themer: NSObject {
NotificationCenter . default . post ( name : . themeDidChangeNotification , object : nil )
}
}
init ( index : Int ) {
switch index {
case 0 :
@ -39,20 +39,18 @@ class Themer: NSObject {
default :
themeIndex = Theme . light
}
super . init ( )
setAppAppearance ( )
DistributedNotificationCenter . default . addObserver ( self ,
selector : #selector ( respondToInterfaceStyle ) ,
name : . interfaceStyleDidChange ,
object : nil )
if #available ( macOS 10.14 , * ) {
effectiveApperanceObserver = NSApp . observe ( \ . effectiveAppearance ) { _ , _ in
NotificationCenter . default . post ( name : . themeDidChangeNotification , object : nil )
}
effectiveApperanceObserver = NSApp . observe ( \ . effectiveAppearance ) { _ , _ in
NotificationCenter . default . post ( name : . themeDidChangeNotification , object : nil )
}
}
}
@ -61,12 +59,12 @@ extension Themer {
class func shared ( ) -> Themer {
return sharedInstance
}
func set ( theme : Int ) {
if themeIndex . rawValue = = theme {
return
}
switch theme {
case 0 :
themeIndex = Theme . light
@ -81,18 +79,18 @@ extension Themer {
default :
themeIndex = Theme . light
}
setAppAppearance ( )
}
@objc func respondToInterfaceStyle ( ) {
OperationQueue . main . addOperation {
self . setAppAppearance ( )
}
}
// MARK: C o l o r
func sliderKnobColor ( ) -> NSColor {
switch themeIndex {
case . light , . solarizedLight :
@ -103,7 +101,7 @@ extension Themer {
return retrieveCurrentSystem ( ) = = . light ? NSColor ( deviceRed : 255.0 , green : 255.0 , blue : 255 , alpha : 0.9 ) : NSColor ( deviceRed : 0.0 , green : 0.0 , blue : 0 , alpha : 0.9 )
}
}
func sliderRightColor ( ) -> NSColor {
switch themeIndex {
case . dark :
@ -114,104 +112,90 @@ extension Themer {
return NSColor . gray
}
}
func mainBackgroundColor ( ) -> NSColor {
if #available ( macOS 10.14 , * ) {
switch themeIndex {
case . light :
return NSColor . white
case . dark :
return NSColor ( deviceRed : 42.0 / 255.0 , green : 42.0 / 255.0 , blue : 42.0 / 255.0 , alpha : 1.0 )
case . system :
return retrieveCurrentSystem ( ) = = . light ? NSColor . white : NSColor . windowBackgroundColor
case . solarizedLight :
return NSColor ( deviceRed : 253.0 / 255.0 , green : 246.0 / 255.0 , blue : 227.0 / 255.0 , alpha : 1.0 )
case . solarizedDark :
return NSColor ( deviceRed : 7.0 / 255.0 , green : 54.0 / 255.0 , blue : 66.0 / 255.0 , alpha : 1.0 )
}
switch themeIndex {
case . light :
return NSColor . white
case . dark :
return NSColor ( deviceRed : 42.0 / 255.0 , green : 42.0 / 255.0 , blue : 42.0 / 255.0 , alpha : 1.0 )
case . system :
return retrieveCurrentSystem ( ) = = . light ? NSColor . white : NSColor . windowBackgroundColor
case . solarizedLight :
return NSColor ( deviceRed : 253.0 / 255.0 , green : 246.0 / 255.0 , blue : 227.0 / 255.0 , alpha : 1.0 )
case . solarizedDark :
return NSColor ( deviceRed : 7.0 / 255.0 , green : 54.0 / 255.0 , blue : 66.0 / 255.0 , alpha : 1.0 )
}
return themeIndex = = . light ? NSColor . white : NSColor ( deviceRed : 55.0 / 255.0 , green : 71.0 / 255.0 , blue : 79.0 / 255.0 , alpha : 1.0 )
}
func textBackgroundColor ( ) -> NSColor {
if #available ( macOS 10.14 , * ) {
switch themeIndex {
case . light :
return NSColor ( deviceRed : 241.0 / 255.0 , green : 241.0 / 255.0 , blue : 241.0 / 255.0 , alpha : 1.0 )
case . dark :
return NSColor ( deviceRed : 42.0 / 255.0 , green : 55.0 / 255.0 , blue : 62.0 / 255.0 , alpha : 1.0 )
case . system :
return retrieveCurrentSystem ( ) = = . light ? NSColor ( deviceRed : 241.0 / 255.0 , green : 241.0 / 255.0 , blue : 241.0 / 255.0 , alpha : 1.0 ) : NSColor . controlBackgroundColor
case . solarizedLight :
return NSColor ( deviceRed : 238.0 / 255.0 , green : 232.0 / 255.0 , blue : 213.0 / 255.0 , alpha : 1.0 )
case . solarizedDark :
return NSColor ( deviceRed : 0.0 / 255.0 , green : 43.0 / 255.0 , blue : 54.0 / 255.0 , alpha : 1.0 )
}
switch themeIndex {
case . light :
return NSColor ( deviceRed : 241.0 / 255.0 , green : 241.0 / 255.0 , blue : 241.0 / 255.0 , alpha : 1.0 )
case . dark :
return NSColor ( deviceRed : 42.0 / 255.0 , green : 55.0 / 255.0 , blue : 62.0 / 255.0 , alpha : 1.0 )
case . system :
return retrieveCurrentSystem ( ) = = . light ? NSColor ( deviceRed : 241.0 / 255.0 , green : 241.0 / 255.0 , blue : 241.0 / 255.0 , alpha : 1.0 ) : NSColor . controlBackgroundColor
case . solarizedLight :
return NSColor ( deviceRed : 238.0 / 255.0 , green : 232.0 / 255.0 , blue : 213.0 / 255.0 , alpha : 1.0 )
case . solarizedDark :
return NSColor ( deviceRed : 0.0 / 255.0 , green : 43.0 / 255.0 , blue : 54.0 / 255.0 , alpha : 1.0 )
}
return themeIndex = = . light ?
NSColor ( deviceRed : 241.0 / 255.0 , green : 241.0 / 255.0 , blue : 241.0 / 255.0 , alpha : 1.0 ) :
NSColor ( deviceRed : 42.0 / 255.0 , green : 55.0 / 255.0 , blue : 62.0 / 255.0 , alpha : 1.0 )
}
func mainTextColor ( ) -> NSColor {
if #available ( macOS 10.14 , * ) {
switch themeIndex {
case . light :
return NSColor . black
case . dark :
return NSColor . white
case . system :
return NSColor . textColor
case . solarizedLight :
return NSColor . black
case . solarizedDark :
return NSColor . white
}
switch themeIndex {
case . light :
return NSColor . black
case . dark :
return NSColor . white
case . system :
return NSColor . textColor
case . solarizedLight :
return NSColor . black
case . solarizedDark :
return NSColor . white
}
return themeIndex = = . light ? NSColor . black : NSColor . white
}
// MARK: I m a g e s
func shutdownImage ( ) -> NSImage {
if let symbolImageForShutdown = symbolImage ( for : " ellipsis.circle " ) {
return symbolImageForShutdown
}
return fallbackImageProvider ( NSImage ( named : NSImage . Name ( " PowerIcon " ) ) ! ,
NSImage ( named : NSImage . Name ( " PowerIcon-White " ) ) ! ,
NSImage ( named : NSImage . Name ( " Power " ) ) ! ,
NSImage ( named : NSImage . Name ( " PowerIcon " ) ) ! ,
NSImage ( named : NSImage . Name ( " PowerIcon-White " ) ) ! )
}
func preferenceImage ( ) -> NSImage {
if let symbolImageForPreference = symbolImage ( for : " plus " ) {
return symbolImageForPreference
}
return fallbackImageProvider ( NSImage ( named : NSImage . Name ( " Settings " ) ) ! ,
NSImage ( named : NSImage . Name ( " Settings-White " ) ) ! ,
NSImage ( named : NSImage . actionTemplateName ) ! ,
NSImage ( named : NSImage . Name ( " Settings " ) ) ! ,
NSImage ( named : NSImage . Name ( " Settings-White " ) ) ! )
}
func pinImage ( ) -> NSImage {
if let pinImage = symbolImage ( for : " macwindow.on.rectangle " ) {
return pinImage
}
return fallbackImageProvider ( NSImage ( named : NSImage . Name ( " Float " ) ) ! ,
NSImage ( named : NSImage . Name ( " Float-White " ) ) ! ,
NSImage ( named : NSImage . Name ( " Pin " ) ) ! ,
NSImage ( named : NSImage . Name ( " Float " ) ) ! ,
NSImage ( named : NSImage . Name ( " Float-White " ) ) ! )
}
func sunriseImage ( ) -> NSImage {
if let symbolImage = symbolImage ( for : " sunrise.fill " ) {
return symbolImage
@ -222,31 +206,31 @@ extension Themer {
NSImage ( named : NSImage . Name ( " Sunrise " ) ) ! ,
NSImage ( named : NSImage . Name ( " WhiteSunrise " ) ) ! )
}
func sunsetImage ( ) -> NSImage {
if let symbolImage = symbolImage ( for : " sunset.fill " ) {
return symbolImage
}
return fallbackImageProvider ( NSImage ( named : NSImage . Name ( " Sunset " ) ) ! ,
NSImage ( named : NSImage . Name ( " WhiteSunset " ) ) ! ,
NSImage ( named : NSImage . Name ( " Sunset Dynamic " ) ) ! ,
NSImage ( named : NSImage . Name ( " Sunset " ) ) ! ,
NSImage ( named : NSImage . Name ( " WhiteSunset " ) ) ! )
}
func removeImage ( ) -> NSImage {
if let symbolImage = symbolImage ( for : " xmark " ) {
return symbolImage
}
return fallbackImageProvider ( NSImage ( named : NSImage . Name ( " Remove " ) ) ! ,
NSImage ( named : NSImage . Name ( " WhiteRemove " ) ) ! ,
NSImage ( named : NSImage . Name ( " Remove Dynamic " ) ) ! ,
NSImage ( named : NSImage . Name ( " Remove " ) ) ! ,
NSImage ( named : NSImage . Name ( " WhiteRemove " ) ) ! )
}
func extraOptionsImage ( ) -> NSImage {
return fallbackImageProvider ( NSImage ( named : NSImage . Name ( " Extra " ) ) ! ,
NSImage ( named : NSImage . Name ( " ExtraWhite " ) ) ! ,
@ -254,22 +238,18 @@ extension Themer {
NSImage ( named : NSImage . Name ( " Extra " ) ) ! ,
NSImage ( named : NSImage . Name ( " ExtraWhite " ) ) ! )
}
func menubarOnboardingImage ( ) -> NSImage {
if #available ( macOS 10.14 , * ) {
switch themeIndex {
case . system :
return NSImage ( named : NSImage . Name ( " Dynamic Menubar " ) ) !
case . light , . solarizedLight :
return NSImage ( named : NSImage . Name ( " Light Menubar " ) ) !
case . dark , . solarizedDark :
return NSImage ( named : NSImage . Name ( " Dark Menubar " ) ) !
}
switch themeIndex {
case . system :
return NSImage ( named : NSImage . Name ( " Dynamic Menubar " ) ) !
case . light , . solarizedLight :
return NSImage ( named : NSImage . Name ( " Light Menubar " ) ) !
case . dark , . solarizedDark :
return NSImage ( named : NSImage . Name ( " Dark Menubar " ) ) !
}
return retrieveCurrentSystem ( ) = = . dark ? NSImage ( named : NSImage . Name ( " Dark Menubar " ) ) ! : NSImage ( named : NSImage . Name ( " Light Menubar " ) ) !
}
func extraOptionsHighlightedImage ( ) -> NSImage {
return fallbackImageProvider ( NSImage ( named : NSImage . Name ( " ExtraHighlighted " ) ) ! ,
NSImage ( named : NSImage . Name ( " ExtraWhiteHighlighted " ) ) ! ,
@ -282,7 +262,7 @@ extension Themer {
if let copyImage = symbolImage ( for : " doc.on.doc " ) {
return copyImage
}
return NSImage ( )
}
@ -290,105 +270,101 @@ extension Themer {
if let copyImage = symbolImage ( for : " doc.on.doc.fill " ) {
return copyImage
}
return nil
}
func sharingImage ( ) -> NSImage {
if let sharingImage = symbolImage ( for : " square.and.arrow.up.on.square.fill " ) {
return sharingImage
}
return fallbackImageProvider ( NSImage ( named : NSImage . Name ( " Sharing " ) ) ! ,
NSImage ( named : NSImage . Name ( " SharingDarkIcon " ) ) ! ,
NSImage ( named : NSImage . Name ( " Sharing Dynamic " ) ) ! ,
NSImage ( named : NSImage . Name ( " Sharing " ) ) ! ,
NSImage ( named : NSImage . Name ( " SharingDarkIcon " ) ) ! )
}
func currentLocationImage ( ) -> NSImage {
if let symbolImage = symbolImage ( for : " location.fill " ) {
return symbolImage
}
return fallbackImageProvider ( NSImage ( named : NSImage . Name ( " CurrentLocation " ) ) ! ,
NSImage ( named : NSImage . Name ( " CurrentLocationWhite " ) ) ! ,
NSImage ( named : NSImage . Name ( " CurrentLocationDynamic " ) ) ! ,
NSImage ( named : NSImage . Name ( " CurrentLocation " ) ) ! ,
NSImage ( named : NSImage . Name ( " CurrentLocationWhite " ) ) ! )
}
func popoverAppearance ( ) -> NSAppearance {
if #available ( macOS 10.14 , * ) {
switch themeIndex {
case . light , . solarizedLight :
return NSAppearance ( named : NSAppearance . Name . vibrantLight ) !
case . dark , . solarizedDark :
return NSAppearance ( named : NSAppearance . Name . vibrantDark ) !
case . system :
return NSAppearance . current
}
switch themeIndex {
case . light , . solarizedLight :
return NSAppearance ( named : NSAppearance . Name . vibrantLight ) !
case . dark , . solarizedDark :
return NSAppearance ( named : NSAppearance . Name . vibrantDark ) !
case . system :
return NSAppearance . current
}
return themeIndex = = . light ? NSAppearance ( named : NSAppearance . Name . vibrantLight ) ! : NSAppearance ( named : NSAppearance . Name . vibrantDark ) !
}
func addImage ( ) -> NSImage {
if let symbolImageForPreference = symbolImage ( for : " plus " ) {
return symbolImageForPreference
}
return fallbackImageProvider ( NSImage ( named : NSImage . Name ( " Add Icon " ) ) ! ,
NSImage ( named : NSImage . Name ( " Add White " ) ) ! ,
NSImage ( named : . addDynamicIcon ) ! ,
NSImage ( named : NSImage . Name ( " Add Icon " ) ) ! ,
NSImage ( named : NSImage . Name ( " Add White " ) ) ! )
}
func privacyTabImage ( ) -> NSImage {
if let privacyTabSFImage = symbolImage ( for : " lock " ) {
return privacyTabSFImage
}
return fallbackImageProvider ( NSImage ( named : NSImage . Name ( " Privacy " ) ) ! ,
NSImage ( named : NSImage . Name ( " Privacy Dark " ) ) ! ,
NSImage ( named : . permissionTabIcon ) ! ,
NSImage ( named : NSImage . Name ( " Privacy " ) ) ! ,
NSImage ( named : NSImage . Name ( " Privacy Dark " ) ) ! )
}
func appearanceTabImage ( ) -> NSImage {
if let appearanceTabImage = symbolImage ( for : " eye " ) {
return appearanceTabImage
}
return fallbackImageProvider ( NSImage ( named : NSImage . Name ( " Appearance " ) ) ! ,
NSImage ( named : NSImage . Name ( " Appearance Dark " ) ) ! ,
NSImage ( named : . appearanceTabIcon ) ! ,
NSImage ( named : NSImage . Name ( " Appearance " ) ) ! ,
NSImage ( named : NSImage . Name ( " Appearance Dark " ) ) ! )
}
func calendarTabImage ( ) -> NSImage {
if let calendarTabImage = symbolImage ( for : " calendar " ) {
return calendarTabImage
}
return fallbackImageProvider ( NSImage ( named : NSImage . Name ( " Calendar Tab Icon " ) ) ! ,
NSImage ( named : NSImage . Name ( " Calendar Tab Dark " ) ) ! ,
NSImage ( named : . calendarTabIcon ) ! ,
NSImage ( named : NSImage . Name ( " Calendar Tab Icon " ) ) ! ,
NSImage ( named : NSImage . Name ( " Calendar Tab Dark " ) ) ! )
}
func generalTabImage ( ) -> NSImage ? {
return symbolImage ( for : " gearshape " )
}
func aboutTabImage ( ) -> NSImage ? {
return symbolImage ( for : " info.circle " )
}
func videoCallImage ( ) -> NSImage ? {
if #available ( macOS 11.0 , * ) {
let symbolConfig = NSImage . SymbolConfiguration ( pointSize : 20 , weight : . regular )
@ -397,54 +373,54 @@ extension Themer {
return nil
}
}
func filledTrashImage ( ) -> NSImage ? {
return symbolImage ( for : " trash.fill " )
}
// M o d e r n S l i d e r
func goBackwardsImage ( ) -> NSImage ? {
return symbolImage ( for : " gobackward.15 " )
}
func goForwardsImage ( ) -> NSImage ? {
return symbolImage ( for : " goforward.15 " )
}
func resetModernSliderImage ( ) -> NSImage ? {
if let xmarkImage = symbolImage ( for : " xmark.circle.fill " ) {
return xmarkImage
}
return removeImage ( )
}
// MARK: D e b u g D e s c r i p t i o n
override var debugDescription : String {
if themeIndex = = . system {
return " System Theme is \( retrieveCurrentSystem ( ) ) "
}
return " Current Theme is \( themeIndex ) "
}
override var description : String {
return debugDescription
}
// MARK: P r i v a t e
private func symbolImage ( for name : String ) -> NSImage ? {
assert ( name . isEmpty = = false )
if #available ( OSX 11.0 , * ) {
return NSImage ( systemSymbolName : name ,
accessibilityDescription : name )
}
return nil
}
private func retrieveCurrentSystem ( ) -> Theme {
if #available ( OSX 10.14 , * ) {
if let appleInterfaceStyle = UserDefaults . standard . object ( forKey : UserDefaultKeys . appleInterfaceStyleKey ) as ? String {
@ -455,43 +431,38 @@ extension Themer {
}
return . light
}
private func setAppAppearance ( ) {
if #available ( OSX 10.14 , * ) {
var appAppearance = NSAppearance ( named : . aqua )
if themeIndex = = . dark || themeIndex = = . solarizedDark {
appAppearance = NSAppearance ( named : . darkAqua )
} else if themeIndex = = . system {
appAppearance = retrieveCurrentSystem ( ) = = . dark ? NSAppearance ( named : . darkAqua ) : NSAppearance ( named : . aqua )
}
if NSApp . appearance != appAppearance {
NSApp . appearance = appAppearance
}
var appAppearance = NSAppearance ( named : . aqua )
if themeIndex = = . dark || themeIndex = = . solarizedDark {
appAppearance = NSAppearance ( named : . darkAqua )
} else if themeIndex = = . system {
appAppearance = retrieveCurrentSystem ( ) = = . dark ? NSAppearance ( named : . darkAqua ) : NSAppearance ( named : . aqua )
}
if NSApp . appearance != appAppearance {
NSApp . appearance = appAppearance
}
}
private func fallbackImageProvider ( _ lightImage : NSImage ,
_ darkImage : NSImage ,
_ systemImage : NSImage ,
_ solarizedLightImage : NSImage ,
_ solarizedDarkImage : NSImage ) -> NSImage
{
if #available ( macOS 10.14 , * ) {
switch themeIndex {
case . light :
return lightImage
case . dark :
return darkImage
case . system :
return systemImage
case . solarizedLight :
return solarizedLightImage
case . solarizedDark :
return solarizedDarkImage
}
switch themeIndex {
case . light :
return lightImage
case . dark :
return darkImage
case . system :
return systemImage
case . solarizedLight :
return solarizedLightImage
case . solarizedDark :
return solarizedDarkImage
}
return themeIndex = = . light ? lightImage : darkImage
}
}