This commit is contained in:
Alin
2024-07-08 11:09:30 -06:00
parent 68aab7c1a2
commit 4610ae90f2
5 changed files with 156 additions and 126 deletions
+4 -6
View File
@@ -34,7 +34,6 @@
C77B90232AF2D616009CC655 /* FilesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C77B90222AF2D616009CC655 /* FilesView.swift */; };
C78121662BC892A000BE06BD /* FinderOpen.swift in Sources */ = {isa = PBXBuildFile; fileRef = C78121652BC892A000BE06BD /* FinderOpen.swift */; };
C781216B2BC892A000BE06BD /* FinderOpen.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = C78121632BC892A000BE06BD /* FinderOpen.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
C786F1A82C29E599001B3800 /* Builds in Resources */ = {isa = PBXBuildFile; fileRef = C786F1A72C29E599001B3800 /* Builds */; };
C79947962C34A794007279CC /* Tips.swift in Sources */ = {isa = PBXBuildFile; fileRef = C79947952C34A794007279CC /* Tips.swift */; };
C79D05202BC99EB40083F976 /* ThemeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C79D051F2BC99EB40083F976 /* ThemeManager.swift */; };
C7A27E812AFD7C4600166168 /* com.alienator88.PearcleanerSentinel.plist in Resources */ = {isa = PBXBuildFile; fileRef = C7A27E802AFD7C4600166168 /* com.alienator88.PearcleanerSentinel.plist */; };
@@ -447,7 +446,6 @@
buildActionMask = 2147483647;
files = (
C77B90082AF18E2F009CC655 /* Assets.xcassets in Resources */,
C786F1A82C29E599001B3800 /* Builds in Resources */,
C7A27E812AFD7C4600166168 /* com.alienator88.PearcleanerSentinel.plist in Resources */,
C7DC1FEE2B9F7D3D009AC317 /* features.json in Resources */,
);
@@ -588,8 +586,8 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
APP_BUILD = 53;
APP_VERSION = 3.7.8;
APP_BUILD = 54;
APP_VERSION = 3.8.0;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
@@ -658,8 +656,8 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
APP_BUILD = 53;
APP_VERSION = 3.7.8;
APP_BUILD = 54;
APP_VERSION = 3.8.0;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+5 -5
View File
@@ -962,10 +962,10 @@ struct PickerModifier: ViewModifier {
content
.buttonStyle(.borderless)
.padding(4)
.background {
backgroundView(themeSettings: themeSettings, darker: isHovered)
.clipShape(RoundedRectangle(cornerRadius: 10))
}
// .background {
// backgroundView(themeSettings: themeSettings, darker: isHovered)
// .clipShape(RoundedRectangle(cornerRadius: 10))
// }
.onHover { hovering in
isHovered = hovering
}
@@ -995,7 +995,7 @@ struct PresetColor: ButtonStyle {
.help(label)
.overlay(
RoundedRectangle(cornerRadius: 25)
.strokeBorder(Color("mode").opacity(0.8), lineWidth: 1.5))
.strokeBorder(Color("mode").opacity(0.8), lineWidth: 1))
// Text(label)
}
.onHover { inside in inside ? NSCursor.pointingHand.push() : NSCursor.pop() }
+8 -8
View File
@@ -28,14 +28,14 @@ class ThemeSettings: ObservableObject {
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()
}
func setupInitialColor(forcedDarkMode: Bool? = nil) {
// Determine dark mode either from forced setting or system setting
let darkMode = forcedDarkMode ?? isDarkMode()
// Set the theme color based on the dark mode status
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() {
+35 -23
View File
@@ -177,10 +177,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
// UserDefaults.standard.register(defaults: ["NSQuitAlwaysKeepsWindows" : false])
findAndSetWindowFrame(named: ["Pearcleaner"], windowSettings: windowSettings)
// if UserDefaults.standard.object(forKey: "themeColor") == nil {
// self.appearanceChanged()
// }
self.appearanceCheck()
@@ -191,11 +187,11 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
// Start observing the appearance change
observer = DistributedNotificationCenter.default().addObserver(forName: NSNotification.Name(rawValue: "AppleInterfaceThemeChangedNotification"), object: nil, queue: OperationQueue.main) { [weak self] _ in
// let themeMode = UserDefaults.standard.string(forKey: "settings.general.selectedTheme")
// if themeMode == "Auto" {
// self?.appearanceCheck()
// }
self?.appearanceCheck(reset: true)
let themeMode = UserDefaults.standard.string(forKey: "settings.general.selectedTheme")
let themesEnabled = UserDefaults.standard.bool(forKey: "settings.interface.themesEnabled")
if themeMode == "Auto" && !themesEnabled {
self?.appearanceCheck(reset: true)
}
}
}
@@ -203,30 +199,46 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
func appearanceCheck(reset: Bool = false) {
// Setup initial color
ThemeSettings.shared.setupInitialColor()
let themesEnabled = UserDefaults.standard.bool(forKey: "settings.interface.themesEnabled")
let themeMode = UserDefaults.standard.string(forKey: "settings.general.selectedTheme")
// 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")
if themesEnabled {
// Custom theming is enabled; user's manual settings take priority.
} 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")
switch themeMode {
case "Auto":
// Auto mode: adjust theme based on system appearance.
ThemeSettings.shared.setupInitialColor()
updateDisplayModeBasedOnThemeColor()
case "Light", "Dark":
// Specific mode set: ensure theme color matches the display mode.
ThemeSettings.shared.setupInitialColor(forcedDarkMode: themeMode == "Dark")
UserDefaults.standard.set(themeMode == "Dark" ? DisplayMode.dark.rawValue : DisplayMode.light.rawValue, forKey: "displayMode")
default:
// No specific handling needed or unrecognized mode; fall back to default behavior.
printOS("No specific theme mode set or unrecognized value.")
}
}
// Reset theme when OS changes appearance
if reset {
if reset && themeMode == "Auto" {
let dark = isDarkMode()
ThemeSettings.shared.resetToDefault(dark: dark)
}
}
func updateDisplayModeBasedOnThemeColor() {
let themeColor = ThemeSettings.shared.themeColor
if let isLightColor = themeColor.isLight() {
let shouldUseDarkMode = !isLightColor
UserDefaults.standard.set(shouldUseDarkMode ? DisplayMode.dark.rawValue : DisplayMode.light.rawValue, forKey: "displayMode")
} else {
// Default to system preference if brightness cannot be determined.
let dark = isDarkMode()
UserDefaults.standard.set(dark ? DisplayMode.dark.rawValue : DisplayMode.light.rawValue, forKey: "displayMode")
}
}
func applicationWillTerminate(_ notification: Notification) {
// Stop observing the appearance change
if let observer = observer {
+104 -84
View File
@@ -23,9 +23,9 @@ struct InterfaceSettingsTab: View {
@AppStorage("settings.general.selectedTab") private var selectedTab: CurrentTabView = .general
@AppStorage("settings.general.glass") private var glass: Bool = false
@AppStorage("settings.general.dark") var isDark: Bool = true
@AppStorage("settings.interface.themesEnabled") var themesEnabled: Bool = false
@AppStorage("settings.general.popover") private var popoverStay: Bool = true
@AppStorage("settings.general.miniview") private var miniView: Bool = true
// @AppStorage("settings.general.animateLogo") private var animateLogo: Bool = true
@AppStorage("settings.general.selectedTheme") var selectedTheme: String = "Auto"
@AppStorage("settings.interface.selectedMenubarIcon") var selectedMenubarIcon: String = "pear-4"
@State private var isLaunchAtLoginEnabled: Bool = false
@@ -69,99 +69,109 @@ struct InterfaceSettingsTab: View {
.padding(.leading)
// HStack(spacing: 0) {
// Image(systemName: animateLogo ? "play.fill" : "pause")
// .resizable()
// .scaledToFit()
// .frame(width: 20, height: 20)
// .padding(.trailing)
// .foregroundStyle(Color("mode").opacity(0.5))
// VStack(alignment: .leading, spacing: 5) {
// Text("\(animateLogo ? "Logo animation enabled" : "Logo animation disabled")")
// .font(.callout)
// .foregroundStyle(Color("mode").opacity(0.5))
//
// }
// if !isMacOS14OrHigher {
// Text("(macOS 14+)")
// .font(.footnote)
// .foregroundStyle(Color("mode").opacity(0.3))
// .padding(.leading, 5)
// }
//// InfoButton(text: "The logo animation is only available in macOS 14 or higher")
// Spacer()
// Toggle(isOn: $animateLogo, label: {
// })
// .toggleStyle(.switch)
// .disabled(!isMacOS14OrHigher)
// }
// .padding(5)
// .padding(.leading)
HStack(spacing: 0) {
Image(systemName: "paintbrush")
Image(systemName: themesEnabled ? "paintpalette.fill" : "paintpalette")
.resizable()
.scaledToFit()
.frame(width: 20, height: 20)
.padding(.trailing)
.foregroundStyle(Color("mode").opacity(0.5))
VStack(alignment: .leading, spacing: 5) {
Text("Application base color")
Text("\(themesEnabled ? "Custom theming is enabled" : "Custom theming is disabled")")
.font(.callout)
.foregroundStyle(Color("mode").opacity(0.5))
}
InfoButton(text: "When using a custom color, you might need to change the application color mode below to Dark or Light so text is readable")
Spacer()
HStack(spacing: 10) {
Button("") {
themeSettings.setPreset(preset: "pearcleaner", colorScheme: displayMode)
Toggle(isOn: $themesEnabled, label: {
})
.toggleStyle(.switch)
.onChange(of: themesEnabled) { newVal in
themeSettings.resetToDefault(dark: isDarkMode())
if isDarkMode() {
displayMode.colorScheme = .dark
} else {
displayMode.colorScheme = .light
}
.buttonStyle(PresetColor(fillColor: themeSettings.getColorForPreset(preset: "pearcleaner", colorScheme: displayMode), label: "Pearcleaner"))
Button("") {
themeSettings.setPreset(preset: "dracula", colorScheme: displayMode)
if newVal {
selectedTheme = isDarkMode() ? "Dark" : "Light"
} else {
selectedTheme = "Auto"
}
.buttonStyle(PresetColor(fillColor: themeSettings.getColorForPreset(preset: "dracula", colorScheme: displayMode), label: "Dracula"))
Button("") {
themeSettings.setPreset(preset: "solarized", colorScheme: displayMode)
themeSettings.saveThemeColor()
}
.buttonStyle(PresetColor(fillColor: themeSettings.getColorForPreset(preset: "solarized", colorScheme: displayMode), label: "Solarized"))
Button("") {
themeSettings.setPreset(preset: "macOS", colorScheme: displayMode)
themeSettings.saveThemeColor()
}
.buttonStyle(PresetColor(fillColor: themeSettings.getColorForPreset(preset: "macOS", colorScheme: displayMode), label: "macOS"))
}
Spacer()
ColorPicker("", selection: $themeSettings.themeColor, supportsOpacity: false)
.onChange(of: themeSettings.themeColor) { newValue in
themeSettings.saveThemeColor()
}
.padding(.horizontal, 5)
Button("") {
themeSettings.resetToDefault(dark: colorScheme == .dark)
}
.buttonStyle(SimpleButtonStyle(icon: "arrow.uturn.left.circle", help: "Reset color to default"))
}
.padding(5)
.padding(.leading)
/// Show theme color selector if theming is enabled
if themesEnabled {
HStack(spacing: 0) {
Image(systemName: "paintbrush")
.resizable()
.scaledToFit()
.frame(width: 20, height: 20)
.padding(.trailing)
.foregroundStyle(Color("mode").opacity(0.5))
VStack(alignment: .leading, spacing: 5) {
Text("Application theme color")
.font(.callout)
.foregroundStyle(Color("mode").opacity(0.5))
}
// InfoButton(text: "When using a custom color, you might need to change the application color mode below to Dark or Light so text is readable")
Spacer()
HStack(spacing: 10) {
Button("") {
themeSettings.setPreset(preset: "pearcleaner", colorScheme: displayMode)
}
.buttonStyle(PresetColor(fillColor: themeSettings.getColorForPreset(preset: "pearcleaner", colorScheme: displayMode), label: "Pearcleaner"))
Button("") {
themeSettings.setPreset(preset: "dracula", colorScheme: displayMode)
}
.buttonStyle(PresetColor(fillColor: themeSettings.getColorForPreset(preset: "dracula", colorScheme: displayMode), label: "Dracula"))
Button("") {
themeSettings.setPreset(preset: "solarized", colorScheme: displayMode)
}
.buttonStyle(PresetColor(fillColor: themeSettings.getColorForPreset(preset: "solarized", colorScheme: displayMode), label: "Solarized"))
Button("") {
themeSettings.setPreset(preset: "macOS", colorScheme: displayMode)
}
.buttonStyle(PresetColor(fillColor: themeSettings.getColorForPreset(preset: "macOS", colorScheme: displayMode), label: "macOS"))
}
Spacer()
ColorPicker("", selection: $themeSettings.themeColor, supportsOpacity: false)
.onChange(of: themeSettings.themeColor) { newValue in
themeSettings.saveThemeColor()
}
.padding(.horizontal, 5)
Button("") {
themeSettings.resetToDefault(dark: isDarkMode())
if isDarkMode() {
displayMode.colorScheme = .dark
} else {
displayMode.colorScheme = .light
}
selectedTheme = isDarkMode() ? "Dark" : "Light"
}
.buttonStyle(SimpleButtonStyle(icon: "arrow.uturn.left.circle", help: "Reset color to default"))
}
.padding(5)
.padding(.leading)
}
HStack(spacing: 0) {
Image(systemName: {
@@ -180,18 +190,20 @@ struct InterfaceSettingsTab: View {
.padding(.trailing)
.foregroundStyle(Color("mode").opacity(0.5))
VStack(alignment: .leading, spacing: 5) {
Text("Application color mode")
Text(themesEnabled ? "Application font color" : "Application color mode")
.font(.callout)
.foregroundStyle(Color("mode").opacity(0.5))
}
InfoButton(text: "This changes the text color to match the OS. It will also reset the base color to defaults when swapping between these.")
InfoButton(text: "When custom theming is disabled, you can set the application color mode to follow the operating system using Auto. Or manually set it to Light or Dark. When custom theming is enabled, this selector acts mainly as a font color picker between light or dark to match your custom theme color.")
Spacer()
Picker("", selection: $selectedTheme) {
Text("Auto")
.tag("Auto")
Text("Dark")
if !themesEnabled {
Text("Auto")
.tag("Auto")
}
Text(themesEnabled ? "Light" : "Dark")
.tag("Dark")
Text("Light")
Text(themesEnabled ? "Dark" : "Light")
.tag("Light")
}
.pickerStyle(themeSettings: themeSettings)
@@ -203,7 +215,9 @@ struct InterfaceSettingsTab: View {
} else {
displayMode.colorScheme = .light
}
themeSettings.resetToDefault(dark: isDarkMode())
if !themesEnabled {
themeSettings.resetToDefault(dark: isDarkMode())
}
// Refresh foreground colors
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.selectedTab = .interface
@@ -213,7 +227,9 @@ struct InterfaceSettingsTab: View {
}
case "Dark":
displayMode.colorScheme = .dark
themeSettings.resetToDefault(dark: true)
if !themesEnabled {
themeSettings.resetToDefault(dark: true)
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.selectedTab = .interface
}
@@ -222,7 +238,9 @@ struct InterfaceSettingsTab: View {
}
case "Light":
displayMode.colorScheme = .light
themeSettings.resetToDefault(dark: false)
if !themesEnabled {
themeSettings.resetToDefault(dark: false)
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.selectedTab = .interface
}
@@ -515,6 +533,8 @@ struct InterfaceSettingsTab: View {
.onChange(of: selectedMenubarIcon) { newValue in
MenuBarExtraManager.shared.swapMenuBarIcon(icon: newValue)
}
.pickerStyle(themeSettings: themeSettings)
}
.padding(5)
@@ -525,7 +545,7 @@ struct InterfaceSettingsTab: View {
}
.padding(20)
.frame(width: 500, height: 580)
.frame(width: 500, height: themesEnabled ? 600 : 580)
}