mirror of
https://github.com/exituser/Pearcleaner.git
synced 2026-09-17 04:58:56 +00:00
v3.8.0
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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() }
|
||||
|
||||
@@ -28,15 +28,15 @@ 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.
|
||||
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() {
|
||||
if let components = UserDefaults.standard.array(forKey: colorKey) as? [CGFloat], components.count == 4 {
|
||||
|
||||
@@ -178,10 +178,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
|
||||
|
||||
findAndSetWindowFrame(named: ["Pearcleaner"], windowSettings: windowSettings)
|
||||
|
||||
// if UserDefaults.standard.object(forKey: "themeColor") == nil {
|
||||
// self.appearanceChanged()
|
||||
// }
|
||||
|
||||
self.appearanceCheck()
|
||||
|
||||
if menubarEnabled {
|
||||
@@ -191,42 +187,58 @@ 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()
|
||||
// }
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
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 {
|
||||
|
||||
@@ -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,38 +69,43 @@ 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: 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("\(themesEnabled ? "Custom theming is enabled" : "Custom theming is disabled")")
|
||||
.font(.callout)
|
||||
.foregroundStyle(Color("mode").opacity(0.5))
|
||||
}
|
||||
Spacer()
|
||||
Toggle(isOn: $themesEnabled, label: {
|
||||
})
|
||||
.toggleStyle(.switch)
|
||||
.onChange(of: themesEnabled) { newVal in
|
||||
themeSettings.resetToDefault(dark: isDarkMode())
|
||||
if isDarkMode() {
|
||||
displayMode.colorScheme = .dark
|
||||
} else {
|
||||
displayMode.colorScheme = .light
|
||||
}
|
||||
if newVal {
|
||||
selectedTheme = isDarkMode() ? "Dark" : "Light"
|
||||
} else {
|
||||
selectedTheme = "Auto"
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(5)
|
||||
.padding(.leading)
|
||||
|
||||
|
||||
/// Show theme color selector if theming is enabled
|
||||
if themesEnabled {
|
||||
HStack(spacing: 0) {
|
||||
Image(systemName: "paintbrush")
|
||||
.resizable()
|
||||
@@ -109,11 +114,11 @@ struct InterfaceSettingsTab: View {
|
||||
.padding(.trailing)
|
||||
.foregroundStyle(Color("mode").opacity(0.5))
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("Application base color")
|
||||
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")
|
||||
// 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()
|
||||
|
||||
|
||||
@@ -130,13 +135,11 @@ struct InterfaceSettingsTab: View {
|
||||
|
||||
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"))
|
||||
}
|
||||
@@ -153,13 +156,20 @@ struct InterfaceSettingsTab: View {
|
||||
.padding(.horizontal, 5)
|
||||
|
||||
Button("") {
|
||||
themeSettings.resetToDefault(dark: colorScheme == .dark)
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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) {
|
||||
if !themesEnabled {
|
||||
Text("Auto")
|
||||
.tag("Auto")
|
||||
Text("Dark")
|
||||
}
|
||||
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
|
||||
}
|
||||
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
|
||||
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
|
||||
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)
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user