From fbcd12d35f91ee2fb90e4cbd3d4ab44bfa1b6054 Mon Sep 17 00:00:00 2001 From: Alin Date: Mon, 30 Sep 2024 15:00:29 -0600 Subject: [PATCH] v3.9.0 --- Pearcleaner.xcodeproj/project.pbxproj | 8 +- Pearcleaner/Logic/WindowSettings.swift | 47 +------- Pearcleaner/PearcleanerApp.swift | 18 +-- Pearcleaner/Settings/About.swift | 140 ++++++++++++++-------- Pearcleaner/Settings/General.swift | 4 +- Pearcleaner/Settings/SettingsWindow.swift | 1 + 6 files changed, 107 insertions(+), 111 deletions(-) diff --git a/Pearcleaner.xcodeproj/project.pbxproj b/Pearcleaner.xcodeproj/project.pbxproj index f6c0e54..d07ad1d 100644 --- a/Pearcleaner.xcodeproj/project.pbxproj +++ b/Pearcleaner.xcodeproj/project.pbxproj @@ -533,8 +533,8 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - APP_BUILD = 61; - APP_VERSION = 3.8.7; + APP_BUILD = 62; + APP_VERSION = 3.9.0; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -603,8 +603,8 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - APP_BUILD = 61; - APP_VERSION = 3.8.7; + APP_BUILD = 62; + APP_VERSION = 3.9.0; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; diff --git a/Pearcleaner/Logic/WindowSettings.swift b/Pearcleaner/Logic/WindowSettings.swift index e02d4a3..3258938 100644 --- a/Pearcleaner/Logic/WindowSettings.swift +++ b/Pearcleaner/Logic/WindowSettings.swift @@ -7,27 +7,27 @@ import SwiftUI import AlinFoundation -import Combine class WindowSettings: ObservableObject { static let shared = WindowSettings() - + let menubarEnabled = UserDefaults.standard.bool(forKey: "settings.menubar.enabled") + private let windowWidthKey = "windowWidthKey" private let windowHeightKey = "windowHeightKey" private let windowXKey = "windowXKey" private let windowYKey = "windowYKey" - var windows: [NSWindow] = [] var windowRef: NSWindow? init() { - trackMainWindow() registerDefaultWindowSettings() } func trackMainWindow() { if let mainWindow = NSApplication.shared.windows.first(where: { $0.title == "Pearcleaner" }) { windowRef = mainWindow - print("Main window detected and tracked: \(mainWindow.title)") +// print("Main window detected and tracked") + } else { + print("No main Pearcleaner window detected") } } @@ -35,7 +35,7 @@ class WindowSettings: ObservableObject { func newWindow(mini: Bool, withView view: @escaping () -> V) { let frame = self.resetWindowSettings(mini: mini) - if windowRef == nil { + if menubarEnabled { windowRef = NSWindow( contentRect: .zero, styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], @@ -51,41 +51,6 @@ class WindowSettings: ObservableObject { windowRef?.titleVisibility = .hidden windowRef?.makeKeyAndOrderFront(nil) windowRef?.isReleasedWhenClosed = false -// if let curWindow = windowRef { -// print("Window exists, reopening...") -// let frame = self.resetWindowSettings(mini: mini) -// curWindow.contentView = NSHostingView(rootView: view()) -// curWindow.setFrame(frame, display: true, animate: true) -// curWindow.titlebarAppearsTransparent = true -// curWindow.isMovableByWindowBackground = true -// curWindow.title = "Pearcleaner" -// curWindow.isRestorable = false -// curWindow.titleVisibility = .hidden -// curWindow.makeKeyAndOrderFront(nil) -// curWindow.isReleasedWhenClosed = false -// return -// } -// print("Window doesn't exist, creating...") -// -// // Close existing window -// findAndHideWindows(named: ["Pearcleaner"]) -// // Create new window using defaults -// let frame = self.resetWindowSettings(mini: mini) -// let newWindow = NSWindow( -// contentRect: .zero, -// styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], -// backing: .buffered, defer: false) -// newWindow.contentView = NSHostingView(rootView: view()) -// newWindow.setFrame(frame, display: true, animate: true) -// newWindow.titlebarAppearsTransparent = true -// newWindow.isMovableByWindowBackground = true -// newWindow.title = "Pearcleaner" -// newWindow.isRestorable = false -//// self.windows.append(newWindow) -// newWindow.titleVisibility = .hidden -// newWindow.makeKeyAndOrderFront(nil) -// newWindow.isReleasedWhenClosed = false -// windowRef = newWindow } // Register default sizes if the AppStorage keys are invalid diff --git a/Pearcleaner/PearcleanerApp.swift b/Pearcleaner/PearcleanerApp.swift index 6c13778..54d7259 100644 --- a/Pearcleaner/PearcleanerApp.swift +++ b/Pearcleaner/PearcleanerApp.swift @@ -104,6 +104,9 @@ struct PearcleanerApp: App { appState.currentView = .empty } + // Track main window within windowSettings class + windowSettings.trackMainWindow() + // Disable tabbing NSWindow.allowsAutomaticWindowTabbing = false @@ -128,16 +131,6 @@ struct PearcleanerApp: App { } - -#if !DEBUG - Task { - - // Make sure App Support folder exists in the future if needed for storage - // ensureApplicationSupportFolderExists(appState: appState) - - } - -#endif } } .windowStyle(.hiddenTitleBar) @@ -189,11 +182,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate { themeManager.setupAppearance() -// if menubarEnabled { -// findAndHideWindows(named: ["Pearcleaner"]) -// NSApplication.shared.setActivationPolicy(.accessory) -// } - windowFrameObserver = NotificationCenter.default.addObserver(forName: nil, object: nil, queue: nil) { notification in if let window = notification.object as? NSWindow, window.title == "Pearcleaner" { if notification.name == NSWindow.didEndLiveResizeNotification || notification.name == NSWindow.didMoveNotification { diff --git a/Pearcleaner/Settings/About.swift b/Pearcleaner/Settings/About.swift index f974ef2..f17daca 100644 --- a/Pearcleaner/Settings/About.swift +++ b/Pearcleaner/Settings/About.swift @@ -16,23 +16,48 @@ struct AboutSettingsTab: View { var body: some View { let sponsors = Sponsor.sponsors - let credits = Credit.credits +// let credits = Credit.credits VStack(alignment: .center) { - Image(nsImage: NSApp.applicationIconImage) - Text(Bundle.main.name) - .font(.title) - .bold() + HStack { - Text("Version \(Bundle.main.version)") - Text("(Build \(Bundle.main.buildVersion))").font(.footnote) + Spacer() + Button(action: { + NSWorkspace.shared.open(URL(string: "https://github.com/sponsors/alienator88")!) + }, label: { + HStack(alignment: .center, spacing: 8) { + Image(systemName: "heart") + .resizable() + .scaledToFit() + .frame(width: 16, height: 16) + .foregroundStyle(.pink) + + Text("Sponsor") + .font(.body) + .bold() + } + .padding(5) + }) + } + + VStack(spacing: 10) { + Image(nsImage: NSApp.applicationIconImage) + Text(Bundle.main.name) + .font(.title) + .bold() + HStack { + Text("Version \(Bundle.main.version)") + Text("(Build \(Bundle.main.buildVersion))").font(.footnote) + } + + Text("Made with ❤️ by Alin Lupascu").font(.footnote) } + .padding(.vertical, 50) - Text("Made with ❤️ by Alin Lupascu").font(.footnote) VStack(spacing: 20) { // GitHub - PearGroupBox(header: { Text("GitHub Issues").font(.title2) }, content: { + PearGroupBox(header: { Text("Support").font(.title2) }, content: { HStack{ Image(systemName: "star") .resizable() @@ -41,7 +66,7 @@ struct AboutSettingsTab: View { .padding(.trailing) VStack(alignment: .leading){ - Text("Submit a bug or feature request via the repo") + Text("Submit a bug or feature request") .font(.callout) .foregroundStyle(.primary) @@ -50,7 +75,7 @@ struct AboutSettingsTab: View { Button(""){ NSWorkspace.shared.open(URL(string: "https://github.com/alienator88/Pearcleaner/issues/new/choose")!) } - .buttonStyle(SimpleButtonStyle(icon: "link", help: "View")) + .buttonStyle(SimpleButtonStyle(icon: "paperplane", help: "View")) } @@ -84,50 +109,67 @@ struct AboutSettingsTab: View { } .frame(maxWidth: .infinity, maxHeight: .infinity) } - .frame(height: 100) + .frame(height: 45) .padding(5) }) + +// Button(action: { +// NSWorkspace.shared.open(URL(string: "https://github.com/sponsors/alienator88")!) +// }, label: { +// HStack(alignment: .center, spacing: 8) { +// Image(systemName: "heart") +// .resizable() +// .scaledToFit() +// .frame(width: 20, height: 20) +// .foregroundStyle(.pink) +// +// Text("Sponsor") +// .font(.title3) +// .bold() +// } +// .padding(5) +// }) } }) // Credits - PearGroupBox(header: { Text("Credits").font(.title2) }, content: { - HStack{ - Image(systemName: "info.circle") - .resizable() - .scaledToFit() - .frame(width: 20, height: 20) - .padding(.trailing) - - Text("View project resources") - - DisclosureGroup("", isExpanded: $discloseCredits, content: { - VStack(alignment: .leading) { - - ForEach(credits) { credit in - HStack{ - VStack(alignment: .leading){ - Text(credit.name) - Text(credit.description) - .font(.callout) - .foregroundStyle(.primary.opacity(0.5)) - - } - Spacer() - Button(""){ - NSWorkspace.shared.open(credit.url) - } - .buttonStyle(SimpleButtonStyle(icon: "link", help: "View")) - .padding(.trailing) - - } - } - } - .padding(5) - }) - } - - }) +// PearGroupBox(header: { Text("Credits").font(.title2) }, content: { +// HStack{ +// Image(systemName: "info.circle") +// .resizable() +// .scaledToFit() +// .frame(width: 20, height: 20) +// .padding(.trailing) +// +// Text("View project resources") +// +// DisclosureGroup("", isExpanded: $discloseCredits, content: { +// VStack(alignment: .leading) { +// +// ForEach(credits) { credit in +// HStack{ +// VStack(alignment: .leading){ +// Text(credit.name) +// Text(credit.description) +// .font(.callout) +// .foregroundStyle(.primary.opacity(0.5)) +// +// } +// Spacer() +// Button(""){ +// NSWorkspace.shared.open(credit.url) +// } +// .buttonStyle(SimpleButtonStyle(icon: "link", help: "View")) +// .padding(.trailing) +// +// } +// } +// } +// .padding(5) +// }) +// } +// +// }) } diff --git a/Pearcleaner/Settings/General.swift b/Pearcleaner/Settings/General.swift index 01ddef1..f604d31 100644 --- a/Pearcleaner/Settings/General.swift +++ b/Pearcleaner/Settings/General.swift @@ -43,7 +43,7 @@ struct GeneralSettingsTab: View { Text("Homebrew cleanup after uninstall") .font(.callout) .foregroundStyle(.primary.opacity(1)) - InfoButton(text: "When homebrew cleanup is enabled, Pearcleaner will check if the app you are removing was installed via homebrew and launch Terminal.app to execute a brew uninstall and cleanup command to let homebrew know that the app is removed. This way your homebrew list will be synced up correctly and caching will be removed. Terminal.app is required since some apps need sudo permissions to remove services and files placed in system folders. Since other terminal apps don't support applescript and/or the 'do script' command, I opted to use the default macOS Terminal app for this.\n\nNOTE: If you undo the file delete with CMD+Z, the files will be put back but homebrew will not be aware of it. To get the homebrew list back in sync you'd need to run:\n brew install APPNAME --force") + InfoButton(text: "When homebrew cleanup is enabled, Pearcleaner will check if the app you are removing was installed via homebrew and launch Terminal.app to execute a brew uninstall and cleanup command to let homebrew know that the app is removed. This way your homebrew list will be synced up correctly and caching will be removed. Terminal.app is required since some apps need sudo permissions to remove services and files placed in system folders. Since other terminal apps don't support applescript and/or the 'do script' command, I opted to use the default macOS Terminal app for this.\n\nNOTE: If you undo the file delete with CMD+Z, the files will be put back but homebrew will not be aware of it. To get the homebrew list back in sync you'd need to run:\n\n> brew install APPNAME --force") } } @@ -96,7 +96,7 @@ struct GeneralSettingsTab: View { .foregroundStyle(.primary) } - InfoButton(text: "When this mode is enabled, clicking the Uninstall button to remove an app will also close Pearcleaner right after.\n This only affects Pearcleaner when it is opened via external means, like Sentinel Trash Monitor, Finder extension or a Deep Link.\nThis allows for single use of the app for a quick uninstall. When Pearcleaner is opened normally, this setting is ignored and will work as usual.") + InfoButton(text: "When this mode is enabled, clicking the Uninstall button to remove an app will also close Pearcleaner right after.\nThis only affects Pearcleaner when it is opened via external means, like Sentinel Trash Monitor, Finder extension or a Deep Link.\nThis allows for single use of the app for a quick uninstall. When Pearcleaner is opened normally, this setting is ignored and will work as usual.") Spacer() Toggle(isOn: $oneShotMode, label: { diff --git a/Pearcleaner/Settings/SettingsWindow.swift b/Pearcleaner/Settings/SettingsWindow.swift index a173831..3ebaccf 100644 --- a/Pearcleaner/Settings/SettingsWindow.swift +++ b/Pearcleaner/Settings/SettingsWindow.swift @@ -42,6 +42,7 @@ struct SettingsView: View { Divider() .padding(.bottom, 8) + .padding(.horizontal, 9) SidebarItemView(title: "General", systemImage: "gear", isSelected: selectedTab == .general) { selectedTab = .general