diff --git a/Pearcleaner/Logic/PermissionChecker.swift b/Pearcleaner/Logic/PermissionChecker.swift index abc17c6..dde0c6a 100644 --- a/Pearcleaner/Logic/PermissionChecker.swift +++ b/Pearcleaner/Logic/PermissionChecker.swift @@ -133,7 +133,12 @@ struct PermissionsNotificationView: View { .help("Check all permissions") } else { Button(action: { - NSApp.sendAction(Selector(("showPreferencesWindow:")), to: nil, from: nil) + if #available(macOS 13.0, *) { + NSApp.sendAction(Selector(("showSettingsWindow:")), to: nil, from: nil) + } + else { + NSApp.sendAction(Selector(("showPreferencesWindow:")), to: nil, from: nil) + } }) { labelContent } diff --git a/Pearcleaner/Logic/ThemeManager.swift b/Pearcleaner/Logic/ThemeManager.swift index 2dec8dd..e0ab8bc 100644 --- a/Pearcleaner/Logic/ThemeManager.swift +++ b/Pearcleaner/Logic/ThemeManager.swift @@ -25,14 +25,24 @@ class ThemeSettings: ObservableObject { // pearcleaner - Color(.sRGB, red: 0.188143, green: 0.208556, blue: 0.262679, opacity: 1) init() { - // Initialize color from UserDefaults or use a default value - if let components = UserDefaults.standard.object(forKey: colorKey) as? [CGFloat], components.count >= 4 { - themeColor = Color(.sRGB, red: components[0], green: components[1], blue: components[2], opacity: components[3]) - } else { - themeColor = Color(.sRGB, red: 0.188143, green: 0.208556, blue: 0.262679, opacity: 1) + themeColor = userDefaults.color(forKey: colorKey) ?? .clear + } + + func setupInitialColor() { + if userDefaults.color(forKey: colorKey) == nil { + // Only set the initial color if it has not been set by the user. + let darkMode = isDarkMode() // Safe to call here after the application is fully set up. + themeColor = darkMode ? Color(.sRGB, red: 0.188143, green: 0.208556, blue: 0.262679, opacity: 1) : + Color(.sRGB, red: 1.0, green: 1.0, blue: 1.0, opacity: 1) + saveThemeColor() } } + private func loadThemeColor() { + if let components = UserDefaults.standard.array(forKey: colorKey) as? [CGFloat], components.count == 4 { + themeColor = Color(.sRGB, red: components[0], green: components[1], blue: components[2], opacity: components[3]) + } + } func saveThemeColor() { let nsColor = NSColor(themeColor) @@ -90,6 +100,18 @@ extension Color { } } +extension Color { + /// Checks if the current themeColor is of a light or dark variant to set the appropriate displayMode on launch + func isLight() -> Bool? { + guard let components = NSColor(self).cgColor.components, components.count >= 3 else { + return nil + } + // Formula to calculate perceived luminance + let brightness = 0.299 * components[0] + 0.587 * components[1] + 0.114 * components[2] + return brightness > 0.5 + } +} + extension UserDefaults { func color(forKey key: String) -> Color? { guard let components = array(forKey: key) as? [CGFloat], components.count == 4 else { diff --git a/Pearcleaner/Logic/Utilities.swift b/Pearcleaner/Logic/Utilities.swift index df39717..9f1a34a 100644 --- a/Pearcleaner/Logic/Utilities.swift +++ b/Pearcleaner/Logic/Utilities.swift @@ -468,6 +468,15 @@ func isNested(path: URL) -> Bool { return parentDirectory != applicationsPath && parentDirectory != homeApplicationsPath } +// Check if macOS is 14.0 or higher +func isMacOS14OrHigher() -> Bool { + if #available(macOS 14, *) { + return true + } else { + return false + } +} + // --- Extend Int to convert hours to seconds --- diff --git a/Pearcleaner/PearcleanerApp.swift b/Pearcleaner/PearcleanerApp.swift index d9b4334..dbdc635 100644 --- a/Pearcleaner/PearcleanerApp.swift +++ b/Pearcleaner/PearcleanerApp.swift @@ -202,19 +202,26 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate { func appearanceCheck(reset: Bool = false) { - let dm = UserDefaults.standard.integer(forKey: "displayMode") - var displayMode = DisplayMode(rawValue: dm) - let dark = isDarkMode() - if dark { - displayMode?.colorScheme = .dark - } else { - displayMode?.colorScheme = .light - } - UserDefaults.standard.set(displayMode?.rawValue, forKey: "displayMode") + // Setup initial color + ThemeSettings.shared.setupInitialColor() + + // Get the current theme color + let themeColor = ThemeSettings.shared.themeColor + + // Determine if the color is light or dark + if let isLightColor = themeColor.isLight() { + let shouldUseDarkMode = !isLightColor // Use dark mode if color is dark + UserDefaults.standard.set(shouldUseDarkMode ? DisplayMode.dark.rawValue : DisplayMode.light.rawValue, forKey: "displayMode") + } else { + // Default to system preference if unable to determine color brightness + let dark = isDarkMode() + UserDefaults.standard.set(dark ? DisplayMode.dark.rawValue : DisplayMode.light.rawValue, forKey: "displayMode") + } // Reset theme when OS changes appearance if reset { + let dark = isDarkMode() ThemeSettings.shared.resetToDefault(dark: dark) } diff --git a/Pearcleaner/Settings/General.swift b/Pearcleaner/Settings/General.swift index 01e8949..a24611a 100644 --- a/Pearcleaner/Settings/General.swift +++ b/Pearcleaner/Settings/General.swift @@ -217,7 +217,7 @@ struct GeneralSettingsTab: View { HStack(spacing: 0) { - Image(systemName: "accessibility") + Image(systemName: isMacOS14OrHigher() ? "accessibility" : "figure.arms.open") .resizable() .scaledToFit() .frame(width: 20, height: 20) diff --git a/Pearcleaner/Settings/Interface.swift b/Pearcleaner/Settings/Interface.swift index 18fbf3a..298a84f 100644 --- a/Pearcleaner/Settings/Interface.swift +++ b/Pearcleaner/Settings/Interface.swift @@ -33,13 +33,6 @@ struct InterfaceSettingsTab: View { @Binding var search: String let icons = ["externaldrive", "trash", "folder", "pear-1", "pear-1.5", "pear-2", "pear-3", "pear-4"] - var isMacOS14OrHigher: Bool { - if #available(macOS 14, *) { - return true - } else { - return false - } - } var body: some View { @@ -191,7 +184,7 @@ struct InterfaceSettingsTab: View { .font(.callout) .foregroundStyle(Color("mode").opacity(0.5)) } - InfoButton(text: "Changing the color mode will reset the base color to defaults") + InfoButton(text: "This changes the text color to match the OS. It will also reset the base color to defaults when swapping between these.") Spacer() Picker("", selection: $selectedTheme) { Text("Auto") @@ -260,7 +253,7 @@ struct InterfaceSettingsTab: View { .padding(.leading) HStack(spacing: 0) { - Image(systemName: mini ? "square.resize.up" : "square.resize.down") + Image(systemName: isMacOS14OrHigher() ? "square.resize.up" : "macwindow.on.rectangle") .resizable() .scaledToFit() .frame(width: 20, height: 20) @@ -448,7 +441,7 @@ struct InterfaceSettingsTab: View { HStack(spacing: 0) { - Image(systemName: isLaunchAtLoginEnabled ? "person" : "person.slash") + Image(systemName: isLaunchAtLoginEnabled ? "person.fill" : "person") .resizable() .scaledToFit() .frame(width: 20, height: 20) diff --git a/Pearcleaner/Views/AppSearchView.swift b/Pearcleaner/Views/AppSearchView.swift index 6a7630d..4135ea8 100644 --- a/Pearcleaner/Views/AppSearchView.swift +++ b/Pearcleaner/Views/AppSearchView.swift @@ -117,7 +117,12 @@ struct AppSearchView: View { .buttonStyle(SimpleButtonStyle(icon: "circle.fill", label: "Settings", help: "Settings", size: 5)) } else { Button("Settings") { - NSApp.sendAction(Selector(("showPreferencesWindow:")), to: NSApp.delegate, from: nil) + if #available(macOS 13.0, *) { + NSApp.sendAction(Selector(("showSettingsWindow:")), to: nil, from: nil) + } + else { + NSApp.sendAction(Selector(("showPreferencesWindow:")), to: nil, from: nil) + } showMenu = false } .buttonStyle(SimpleButtonStyle(icon: "circle.fill", label: "Settings", help: "Settings", size: 5)) diff --git a/Pearcleaner/Windows/PermView.swift b/Pearcleaner/Windows/PermView.swift index 415c526..5823a4b 100644 --- a/Pearcleaner/Windows/PermView.swift +++ b/Pearcleaner/Windows/PermView.swift @@ -100,7 +100,12 @@ struct PermView: View { .buttonStyle(SimpleButtonBrightStyle(icon: "gear", label: "Settings", help: "Check permissions in Settings", color: Color("mode"))) } else { Button("Settings") { - NSApp.sendAction(Selector(("showPreferencesWindow:")), to: NSApp.delegate, from: nil) + if #available(macOS 13.0, *) { + NSApp.sendAction(Selector(("showSettingsWindow:")), to: nil, from: nil) + } + else { + NSApp.sendAction(Selector(("showPreferencesWindow:")), to: nil, from: nil) + } } .buttonStyle(SimpleButtonBrightStyle(icon: "gear", label: "Settings", help: "Check permissions in Settings", color: .red)) }