From a55396cdaa26437dd41d84e96f2363a69765e007 Mon Sep 17 00:00:00 2001 From: Alin Date: Tue, 19 Mar 2024 16:21:01 -0600 Subject: [PATCH] v3.2.1 --- Pearcleaner.xcodeproj/project.pbxproj | 8 +- Pearcleaner/Logic/DeepLink.swift | 4 +- Pearcleaner/Logic/Logic.swift | 23 ++-- Pearcleaner/Logic/Styles.swift | 13 +- Pearcleaner/Logic/Utilities.swift | 19 +-- Pearcleaner/PearcleanerApp.swift | 43 ++----- Pearcleaner/Settings/Interface.swift | 55 ++++++--- Pearcleaner/Views/AppListItems.swift | 6 +- Pearcleaner/Views/FilesView.swift | 10 +- Pearcleaner/Views/MenuBarMiniAppView.swift | 137 +++++++++++++++------ Pearcleaner/Views/MiniMode.swift | 4 +- Pearcleaner/Views/RegularMode.swift | 4 +- Pearcleaner/Views/ZombieView.swift | 17 +-- Pearcleaner/Windows/MenuBarItem.swift | 29 +++-- Pearcleaner/Windows/WindowSettings.swift | 5 +- 15 files changed, 226 insertions(+), 151 deletions(-) diff --git a/Pearcleaner.xcodeproj/project.pbxproj b/Pearcleaner.xcodeproj/project.pbxproj index d8d1f5c..6a69049 100644 --- a/Pearcleaner.xcodeproj/project.pbxproj +++ b/Pearcleaner.xcodeproj/project.pbxproj @@ -559,7 +559,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 24; + CURRENT_PROJECT_VERSION = 25; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = BK8443AXLU; @@ -577,7 +577,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 3.2.0; + MARKETING_VERSION = 3.2.1; PRODUCT_BUNDLE_IDENTIFIER = com.alienator88.Pearcleaner; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -594,7 +594,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 24; + CURRENT_PROJECT_VERSION = 25; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = BK8443AXLU; @@ -612,7 +612,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 3.2.0; + MARKETING_VERSION = 3.2.1; PRODUCT_BUNDLE_IDENTIFIER = com.alienator88.Pearcleaner; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; diff --git a/Pearcleaner/Logic/DeepLink.swift b/Pearcleaner/Logic/DeepLink.swift index 39f8026..387682e 100644 --- a/Pearcleaner/Logic/DeepLink.swift +++ b/Pearcleaner/Logic/DeepLink.swift @@ -34,7 +34,7 @@ class DeeplinkManager { if let path = queryItems.first(where: { $0.name == DeepLinkConstants.query })?.value { let pathURL = URL(fileURLWithPath: path) let appInfo = getAppInfo(atPath: pathURL) - showAppInFiles(appInfo: appInfo!, mini: mini, appState: appState, locations: locations, showPopover: $showPopover) + showAppInFiles(appInfo: appInfo!, appState: appState, locations: locations, showPopover: $showPopover) } else { printOS("No path query parameter found in the URL") } @@ -46,7 +46,7 @@ class DeeplinkManager { func handleAppBundle(url: URL, appState: AppState, locations: Locations) { let appInfo = getAppInfo(atPath: url) - showAppInFiles(appInfo: appInfo!, mini: mini, appState: appState, locations: locations, showPopover: $showPopover) + showAppInFiles(appInfo: appInfo!, appState: appState, locations: locations, showPopover: $showPopover) } } diff --git a/Pearcleaner/Logic/Logic.swift b/Pearcleaner/Logic/Logic.swift index 41fe35f..2699bcd 100644 --- a/Pearcleaner/Logic/Logic.swift +++ b/Pearcleaner/Logic/Logic.swift @@ -471,7 +471,7 @@ func loadAllPaths(allApps: [AppInfo], appState: AppState, locations: Locations, // Load item in Files view -func showAppInFiles(appInfo: AppInfo, mini: Bool, appState: AppState, locations: Locations, showPopover: Binding) { +func showAppInFiles(appInfo: AppInfo, appState: AppState, locations: Locations, showPopover: Binding) { showPopover.wrappedValue = false DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { updateOnMain { @@ -481,23 +481,15 @@ func showAppInFiles(appInfo: AppInfo, mini: Bool, appState: AppState, locations: appState.appInfo = storedAppInfo appState.selectedItems = Set(storedAppInfo.files) withAnimation(Animation.easeIn(duration: 0.4)) { - if mini { - appState.currentView = .files - showPopover.wrappedValue.toggle() - } else { - appState.currentView = .files - } + appState.currentView = .files + showPopover.wrappedValue.toggle() } } else { // Handle the case where the appInfo is not found in the store withAnimation(Animation.easeIn(duration: 0.4)) { appState.showProgress = true - if mini { - appState.currentView = .files - showPopover.wrappedValue.toggle() - } else { - appState.currentView = .files - } + appState.currentView = .files + showPopover.wrappedValue.toggle() } appState.appInfo = appInfo findPathsForApp(appInfo: appInfo, appState: appState, locations: locations) { @@ -640,7 +632,9 @@ func reversePathsSearch(appState: AppState, locations: Locations, completion: @e // Move files to trash using applescript/Finder so it asks for user password if needed func moveFilesToTrash(at fileURLs: [URL], completion: @escaping () -> Void = {}) { @AppStorage("settings.sentinel.enable") var sentinel: Bool = false - + if sentinel { + launchctl(load: false) + } updateOnBackground { let posixFiles = fileURLs.map { "POSIX file \"\($0.path)\", " }.joined().dropLast(3) let scriptSource = """ @@ -660,6 +654,7 @@ func moveFilesToTrash(at fileURLs: [URL], completion: @escaping () -> Void = {}) completion() } } + } diff --git a/Pearcleaner/Logic/Styles.swift b/Pearcleaner/Logic/Styles.swift index e4af7d5..29bfc09 100644 --- a/Pearcleaner/Logic/Styles.swift +++ b/Pearcleaner/Logic/Styles.swift @@ -11,15 +11,15 @@ import SwiftUI struct SimpleButtonStyle: ButtonStyle { @State private var hovered = false let icon: String + let label: String? let help: String let color: Color - let shield: Bool? - - init(icon: String, help: String, color: Color, shield: Bool? = nil) { + + init(icon: String, label: String? = "", help: String, color: Color) { self.icon = icon + self.label = label self.help = help self.color = color - self.shield = shield } func makeBody(configuration: Self.Configuration) -> some View { @@ -28,8 +28,11 @@ struct SimpleButtonStyle: ButtonStyle { .resizable() .scaledToFit() .frame(width: 20) - .foregroundColor(hovered ? color : color.opacity(0.5)) + if label != "" { + Text(label!) + } } + .foregroundColor(hovered ? color : color.opacity(0.5)) .padding(5) .onHover { hovering in withAnimation() { diff --git a/Pearcleaner/Logic/Utilities.swift b/Pearcleaner/Logic/Utilities.swift index f876c2d..61b4bc4 100644 --- a/Pearcleaner/Logic/Utilities.swift +++ b/Pearcleaner/Logic/Utilities.swift @@ -34,15 +34,15 @@ func updateOnBackground(_ updates: @escaping () -> Void) { // Resize window -func resizeWindow(width: CGFloat, height: CGFloat) { - if let window = NSApplication.shared.windows.first { - let newSize = NSSize(width: width, height: height) - window.setContentSize(newSize) - } -} +//func resizeWindow(width: CGFloat, height: CGFloat) { +// if let window = NSApplication.shared.windows.first { +// let newSize = NSSize(width: width, height: height) +// window.setContentSize(newSize) +// } +//} -func resizeWindowAuto(windowSettings: WindowSettings) { - if let window = NSApplication.shared.windows.first { +func resizeWindowAuto(windowSettings: WindowSettings, title: String) { + if let window = NSApplication.shared.windows.first(where: { $0.title == title }) { let newSize = NSSize(width: windowSettings.loadWindowSettings().width, height: windowSettings.loadWindowSettings().height) window.setContentSize(newSize) } @@ -168,7 +168,8 @@ func hasWindowOpen() -> Bool { func findAndHideWindows(named titles: [String]) { for title in titles { if let window = NSApp.windows.first(where: { $0.title == title }) { - window.orderOut(nil) +// window.orderOut(nil) + window.close() } } } diff --git a/Pearcleaner/PearcleanerApp.swift b/Pearcleaner/PearcleanerApp.swift index ce67f54..c61db89 100644 --- a/Pearcleaner/PearcleanerApp.swift +++ b/Pearcleaner/PearcleanerApp.swift @@ -110,6 +110,7 @@ struct PearcleanerApp: App { MenuBarMiniAppView(search: $search, showPopover: $showPopover) .environmentObject(locations) .environmentObject(appState) + .preferredColorScheme(displayMode.colorScheme) }, icon: selectedMenubarIcon) } @@ -181,49 +182,27 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate { } -#if !DEBUG - func windowShouldClose(_ sender: NSWindow) -> Bool { - let menubarEnabled = UserDefaults.standard.bool(forKey: "settings.menubar.enabled") -// let alert = NSAlert.init() -// alert.addButton(withTitle: "Return") -// alert.addButton(withTitle: "Quit") -// alert.informativeText = "Quit or return to application?" -// let response = alert.runModal() -// if response == NSApplication.ModalResponse.alertFirstButtonReturn { +//#if !DEBUG +// func windowShouldClose(_ sender: NSWindow) -> Bool { +// let menubarEnabled = UserDefaults.standard.bool(forKey: "settings.menubar.enabled") +// if menubarEnabled { +// findAndHideWindows(named: ["Pearcleaner"]) // return false // } else { -// NSApplication.shared.terminate(self) // return true // } - if menubarEnabled { - findAndHideWindows(named: ["Pearcleaner"]) - return false - } else { - return true - } - } -#endif +// } +//#endif func applicationDidFinishLaunching(_ notification: Notification) { let menubarEnabled = UserDefaults.standard.bool(forKey: "settings.menubar.enabled") -// let dockEnabled = UserDefaults.standard.bool(forKey: "settings.dock.enabled") - if menubarEnabled { -#if !DEBUG findAndHideWindows(named: ["Pearcleaner"]) -// NSApp.windows.first?.close() NSApplication.shared.setActivationPolicy(.accessory) -#endif -// if dockEnabled { -// NSApplication.shared.setActivationPolicy(.regular) -// } else { -// NSApplication.shared.setActivationPolicy(.accessory) -// } } - - // Link window to delegate - let mainWindow = NSApp.windows[0] - mainWindow.delegate = self +// Link window to delegate +// let mainWindow = NSApp.windows[0] +// mainWindow.delegate = self } diff --git a/Pearcleaner/Settings/Interface.swift b/Pearcleaner/Settings/Interface.swift index 322f55c..fb023df 100644 --- a/Pearcleaner/Settings/Interface.swift +++ b/Pearcleaner/Settings/Interface.swift @@ -15,7 +15,6 @@ struct InterfaceSettingsTab: View { @EnvironmentObject var locations: Locations @State private var windowSettings = WindowSettings() @AppStorage("settings.menubar.enabled") private var menubarEnabled: Bool = false -// @AppStorage("settings.dock.enabled") private var dockEnabled: Bool = false @AppStorage("settings.general.mini") private var mini: Bool = false @AppStorage("displayMode") var displayMode: DisplayMode = .system @AppStorage("settings.general.glass") private var glass: Bool = true @@ -57,6 +56,9 @@ struct InterfaceSettingsTab: View { Toggle(isOn: $glass, label: { }) .toggleStyle(.switch) + .onChange(of: glass) { newVal in + MenuBarExtraManager.shared.restartMenuBarExtra() + } } .padding(5) .padding(.leading) @@ -89,13 +91,17 @@ struct InterfaceSettingsTab: View { displayMode.colorScheme = nil if isDarkModeEnabled() { displayMode.colorScheme = .dark + MenuBarExtraManager.shared.restartMenuBarExtra() } else { displayMode.colorScheme = .light + MenuBarExtraManager.shared.restartMenuBarExtra() } case "Dark": displayMode.colorScheme = .dark + MenuBarExtraManager.shared.restartMenuBarExtra() case "Light": displayMode.colorScheme = .light + MenuBarExtraManager.shared.restartMenuBarExtra() default: break } @@ -135,19 +141,35 @@ struct InterfaceSettingsTab: View { Toggle(isOn: $mini, label: { }) .toggleStyle(.switch) + .disabled(menubarEnabled) + .help(menubarEnabled ? "Disabled when menubar icon is enabled" : "") .onChange(of: mini) { newVal in - if mini { - appState.currentView = miniView ? .apps : .empty - showPopover = false - resizeWindowAuto(windowSettings: windowSettings) - } else { - resizeWindowAuto(windowSettings: windowSettings) - if appState.appInfo.appName.isEmpty { - appState.currentView = .empty + if mini { + appState.currentView = miniView ? .apps : .empty + showPopover = false + windowSettings.newWindow { + MiniMode(search: $search, showPopover: $showPopover) + .environmentObject(locations) + .environmentObject(appState) + .preferredColorScheme(displayMode.colorScheme) + } + resizeWindowAuto(windowSettings: windowSettings, title: "Pearcleaner") } else { - appState.currentView = .files + if appState.appInfo.appName.isEmpty { + appState.currentView = .empty + } else { + appState.currentView = .files + } + windowSettings.newWindow { + RegularMode(search: $search, showPopover: $showPopover) + .environmentObject(locations) + .environmentObject(appState) + .preferredColorScheme(displayMode.colorScheme) + } + resizeWindowAuto(windowSettings: windowSettings, title: "Pearcleaner") } - } + + } } .padding(5) @@ -229,7 +251,7 @@ struct InterfaceSettingsTab: View { .font(.callout) .foregroundStyle(.gray) } - InfoButton(text: "When menubar icon is enabled, the main app window and dock icon will be hidden. You can still pop-out the main app window from the menubar icon temporarily if you'd like.", color: nil, label: "") + InfoButton(text: "When menubar icon is enabled, the main app window and dock icon will be disabled since the app will be put in accessory mode.", color: nil, label: "") Spacer() Toggle(isOn: $menubarEnabled, label: { }) @@ -240,12 +262,13 @@ struct InterfaceSettingsTab: View { MenuBarMiniAppView(search: $search, showPopover: $showPopover) .environmentObject(locations) .environmentObject(appState) + .preferredColorScheme(displayMode.colorScheme) }, icon: selectedMenubarIcon) NSApplication.shared.setActivationPolicy(.accessory) - findAndShowWindows(named: ["Pearcleaner", "Interface"]) + findAndHideWindows(named: ["Pearcleaner"]) +// findAndShowWindows(named: ["Pearcleaner", "Interface"]) } else { MenuBarExtraManager.shared.removeMenuBarExtra() -// dockEnabled = true NSApplication.shared.setActivationPolicy(.regular) if !hasWindowOpen() { if mini { @@ -253,13 +276,17 @@ struct InterfaceSettingsTab: View { MiniMode(search: $search, showPopover: $showPopover) .environmentObject(locations) .environmentObject(appState) + .preferredColorScheme(displayMode.colorScheme) } + resizeWindowAuto(windowSettings: windowSettings, title: "Pearcleaner") } else { windowSettings.newWindow { RegularMode(search: $search, showPopover: $showPopover) .environmentObject(locations) .environmentObject(appState) + .preferredColorScheme(displayMode.colorScheme) } + resizeWindowAuto(windowSettings: windowSettings, title: "Pearcleaner") } } diff --git a/Pearcleaner/Views/AppListItems.swift b/Pearcleaner/Views/AppListItems.swift index 10d591f..617d3b2 100644 --- a/Pearcleaner/Views/AppListItems.swift +++ b/Pearcleaner/Views/AppListItems.swift @@ -14,8 +14,8 @@ struct AppListItems: View { @State private var isHovered = false @State private var windowSettings = WindowSettings() @Environment(\.colorScheme) var colorScheme - @AppStorage("settings.general.mini") private var mini: Bool = false - @AppStorage("settings.general.popover") private var popoverStay: Bool = true +// @AppStorage("settings.general.mini") private var mini: Bool = false +// @AppStorage("settings.general.popover") private var popoverStay: Bool = true @AppStorage("displayMode") var displayMode: DisplayMode = .system @Binding var showPopover: Bool @EnvironmentObject var locations: Locations @@ -110,7 +110,7 @@ struct AppListItems: View { } .onTapGesture { withAnimation(Animation.easeInOut(duration: 0.4)) { - showAppInFiles(appInfo: appInfo, mini: mini, appState: appState, locations: locations, showPopover: $showPopover) + showAppInFiles(appInfo: appInfo, appState: appState, locations: locations, showPopover: $showPopover) } } diff --git a/Pearcleaner/Views/FilesView.swift b/Pearcleaner/Views/FilesView.swift index 736e60c..bf81041 100644 --- a/Pearcleaner/Views/FilesView.swift +++ b/Pearcleaner/Views/FilesView.swift @@ -16,9 +16,11 @@ struct FilesView: View { @AppStorage("settings.sentinel.enable") private var sentinel: Bool = false @AppStorage("settings.general.instant") var instantSearch: Bool = true @AppStorage("settings.general.brew") private var brew: Bool = false + @AppStorage("settings.menubar.enabled") private var menubarEnabled: Bool = false @Environment(\.colorScheme) var colorScheme @Binding var showPopover: Bool @Binding var search: String + var regularWin: Bool @State private var selectedOption = "Default" var body: some View { @@ -38,7 +40,7 @@ struct FilesView: View { .transition(.opacity) } else { // Titlebar - if mini { + if !regularWin { HStack() { Spacer() @@ -192,7 +194,7 @@ struct FilesView: View { updateOnMain { // appState.appInfo = AppInfo.empty search = "" - if mini { + if !regularWin { appState.currentView = .apps showPopover = false } else { @@ -200,7 +202,6 @@ struct FilesView: View { } } var selectedItemsArray = Array(appState.selectedItems) - if let url = URL(string: appState.appInfo.path.absoluteString) { let appFolderURL = appState.appInfo.path.absoluteString.contains("Wrapper") ? url.deletingLastPathComponent().deletingLastPathComponent().deletingLastPathComponent() : url.deletingLastPathComponent() // Get the immediate parent directory of regular and wrapped apps @@ -220,6 +221,9 @@ struct FilesView: View { appState.currentView = mini ? .apps : .empty appState.isReminderVisible.toggle() } + if sentinel { + launchctl(load: true) + } } // Remove app from app list removeApp(appState: appState, withId: appState.appInfo.id) diff --git a/Pearcleaner/Views/MenuBarMiniAppView.swift b/Pearcleaner/Views/MenuBarMiniAppView.swift index 3070e60..ae68296 100644 --- a/Pearcleaner/Views/MenuBarMiniAppView.swift +++ b/Pearcleaner/Views/MenuBarMiniAppView.swift @@ -22,6 +22,7 @@ struct MenuBarMiniAppView: View { @AppStorage("settings.general.glass") private var glass: Bool = true @AppStorage("settings.general.popover") private var popoverStay: Bool = true @Binding var showPopover: Bool + @State private var showMenu = false var body: some View { @@ -57,20 +58,11 @@ struct MenuBarMiniAppView: View { AppsListView(search: $search, showPopover: $showPopover, filteredApps: filteredApps).padding(0) HStack(spacing: 10) { - if #available(macOS 14.0, *) { - SettingsLink() - .buttonStyle(SimpleButtonStyle(icon: "gear", help: "Settings", color: Color("mode"))) - } else { - Button("Settings") { - NSApp.sendAction(Selector(("showPreferencesWindow:")), to: NSApp.delegate, from: nil) - } - .buttonStyle(SimpleButtonStyle(icon: "gear", help: "Settings", color: Color("mode"))) - } - - Button("") { + Button("Leftover Files") { + showMenu = false withAnimation(.easeInOut(duration: 0.5)) { showPopover = false - updateOnMain { + updateOnMain() { appState.appInfo = .empty appState.selectedZombieItems = [] if appState.zombieFile.fileSize.keys.count == 0 { @@ -91,34 +83,89 @@ struct MenuBarMiniAppView: View { } } .buttonStyle(SimpleButtonStyle(icon: "clock.arrow.circlepath", help: "Leftover Files", color: Color("mode"))) + .padding(.leading, 10) SearchBarMiniBottom(search: $search) +// .padding(.leading, 20) - Button("Main") { - findAndShowWindows(named: ["Pearcleaner"]) -// if mini { -// windowSettings.newWindow { -// MiniMode(search: $search, showPopover: $showPopover) -// .environmentObject(locations) -// .environmentObject(appState) -// } -// } else { -// windowSettings.newWindow { -// RegularMode(search: $search, showPopover: $showPopover) -// .environmentObject(locations) -// .environmentObject(appState) + Button("More") { + self.showMenu.toggle() + } + .padding(.trailing, 10) + .buttonStyle(SimpleButtonStyle(icon: "ellipsis.circle", help: "More", color: Color("mode"))) + .popover(isPresented: $showMenu) { + VStack(alignment: .leading) { + + if #available(macOS 14.0, *) { + SettingsLink{ + Label("Settings", systemImage: "gear") + } + .buttonStyle(SimpleButtonStyle(icon: "gear", label: "Settings", help: "Settings", color: Color("mode"))) + } else { + Button("Settings") { + NSApp.sendAction(Selector(("showPreferencesWindow:")), to: NSApp.delegate, from: nil) + showMenu = false + } + .buttonStyle(SimpleButtonStyle(icon: "gear", label: "Settings", help: "Settings", color: Color("mode"))) + } + + + +// Button("Leftover Files") { +// showMenu = false +// withAnimation(.easeInOut(duration: 0.5)) { +// showPopover = false +// updateOnMain() { +// appState.appInfo = .empty +// appState.selectedZombieItems = [] +// if appState.zombieFile.fileSize.keys.count == 0 { +// appState.currentView = .zombie +// appState.showProgress.toggle() +// showPopover.toggle() +// if instantSearch { +// reversePathsSearch(appState: appState, locations: locations) +// } else { +// loadAllPaths(allApps: appState.sortedApps, appState: appState, locations: locations, reverseAddon: true) +// } +// } else { +// appState.currentView = .zombie +// showPopover.toggle() +// } +// } +// +// } // } -// } +// .buttonStyle(SimpleButtonStyle(icon: "clock.arrow.circlepath", label: "Leftover Files", help: "Leftover Files", color: Color("mode"))) + + - } - .buttonStyle(SimpleButtonStyle(icon: "macwindow.on.rectangle", help: "Pop Out Window", color: Color("mode"))) - Button("Kill") { - NSApp.terminate(nil) + Button("Quit") { + NSApp.terminate(nil) + } + .buttonStyle(SimpleButtonStyle(icon: "x.circle.fill", label: "Quit Pearcleaner", help: "Quit Pearcleaner", color: Color("mode"))) + } + .padding() + .background( + Group { + if glass { + GlassEffect(material: .sidebar, blendingMode: .behindWindow) + .edgesIgnoringSafeArea(.all) + } else { + Rectangle() + .fill(Color("pop")) + .padding(-80) + + } + } + ) } - .buttonStyle(SimpleButtonStyle(icon: "x.circle.fill", help: "Quit", color: Color("mode"))) + + + + } - .padding(.horizontal) +// .padding(.horizontal) } .padding(.vertical, 5) @@ -136,30 +183,40 @@ struct MenuBarMiniAppView: View { GlassEffect(material: .sidebar, blendingMode: .behindWindow) .edgesIgnoringSafeArea(.all) } else { - Color("pop") + Rectangle() + .fill(Color("pop")) .padding(-80) + } } ) .transition(.opacity) - .popover(isPresented: $showPopover, arrowEdge: .trailing) { + .popover(isPresented: $showPopover, arrowEdge: .leading) { VStack { if appState.currentView == .files { - FilesView(showPopover: $showPopover, search: $search) + FilesView(showPopover: $showPopover, search: $search, regularWin: false) .id(appState.appInfo.id) } else if appState.currentView == .zombie { - ZombieView(showPopover: $showPopover, search: $search) + ZombieView(showPopover: $showPopover, search: $search, regularWin: false) .id(appState.appInfo.id) } } .interactiveDismissDisabled(popoverStay) .background( - Rectangle() - .fill(Color("pop")) - .padding(-80) + Group { + if glass { + GlassEffect(material: .sidebar, blendingMode: .behindWindow) + .edgesIgnoringSafeArea(.all) + } else { + Rectangle() + .fill(Color("pop")) + .padding(-80) + + } + } ) - .frame(width: 650, height: 550) + .frame(width: 650, height: 500) } } diff --git a/Pearcleaner/Views/MiniMode.swift b/Pearcleaner/Views/MiniMode.swift index 209de49..284cf3a 100644 --- a/Pearcleaner/Views/MiniMode.swift +++ b/Pearcleaner/Views/MiniMode.swift @@ -39,10 +39,10 @@ struct MiniMode: View { .popover(isPresented: $showPopover, arrowEdge: .trailing) { VStack { if appState.currentView == .files { - FilesView(showPopover: $showPopover, search: $search) + FilesView(showPopover: $showPopover, search: $search, regularWin: false) .id(appState.appInfo.id) } else if appState.currentView == .zombie { - ZombieView(showPopover: $showPopover, search: $search) + ZombieView(showPopover: $showPopover, search: $search, regularWin: false) .id(appState.appInfo.id) } diff --git a/Pearcleaner/Views/RegularMode.swift b/Pearcleaner/Views/RegularMode.swift index 1dbd887..da66817 100644 --- a/Pearcleaner/Views/RegularMode.swift +++ b/Pearcleaner/Views/RegularMode.swift @@ -93,11 +93,11 @@ struct RegularMode: View { AppDetailsEmptyView(showPopover: $showPopover) } else if appState.currentView == .files { TopBar(showPopover: $showPopover) - FilesView(showPopover: $showPopover, search: $search) + FilesView(showPopover: $showPopover, search: $search, regularWin: true) .id(appState.appInfo.id) } else if appState.currentView == .zombie { TopBar(showPopover: $showPopover) - ZombieView(showPopover: $showPopover, search: $search) + ZombieView(showPopover: $showPopover, search: $search, regularWin: true) .id(appState.appInfo.id) } } diff --git a/Pearcleaner/Views/ZombieView.swift b/Pearcleaner/Views/ZombieView.swift index 0d7cc8d..ded1dcf 100644 --- a/Pearcleaner/Views/ZombieView.swift +++ b/Pearcleaner/Views/ZombieView.swift @@ -15,23 +15,16 @@ struct ZombieView: View { @AppStorage("settings.general.mini") private var mini: Bool = false @AppStorage("settings.sentinel.enable") private var sentinel: Bool = false @AppStorage("settings.general.instant") private var instantSearch: Bool = true + @AppStorage("settings.menubar.enabled") private var menubarEnabled: Bool = false @Environment(\.colorScheme) var colorScheme @Binding var showPopover: Bool @Binding var search: String @State private var searchZ: String = "" @State private var selectedOption = "Default" + var regularWin: Bool var body: some View { - -// let filteredAndSortedFiles: [URL] = { -// let files = appState.zombieFile.fileSize.keys.filter { url in -// searchZ.isEmpty || url.lastPathComponent.localizedCaseInsensitiveContains(searchZ) -// } -// -// return selectedOption == "Default" ? -// files.sorted(by: { $0.lastPathComponent < $1.lastPathComponent }) : -// files.sorted(by: { appState.zombieFile.fileSize[$0, default: 0] > appState.zombieFile.fileSize[$1, default: 0] }) -// }() + let filteredAndSortedFiles: ([URL], Int64) = { let filteredFiles = appState.zombieFile.fileSize.filter { (url, _) in searchZ.isEmpty || url.lastPathComponent.localizedCaseInsensitiveContains(searchZ) @@ -68,7 +61,7 @@ struct ZombieView: View { .frame(maxWidth: .infinity, maxHeight: .infinity) } else { // Titlebar - if mini { + if !regularWin { HStack(spacing: 0) { Spacer() @@ -188,7 +181,7 @@ struct ZombieView: View { updateOnMain { appState.zombieFile = .empty search = "" - if mini { + if !regularWin { appState.currentView = .apps showPopover = false } else { diff --git a/Pearcleaner/Windows/MenuBarItem.swift b/Pearcleaner/Windows/MenuBarItem.swift index 5796ab9..a6d4f83 100644 --- a/Pearcleaner/Windows/MenuBarItem.swift +++ b/Pearcleaner/Windows/MenuBarItem.swift @@ -12,15 +12,22 @@ class MenuBarExtraManager { static let shared = MenuBarExtraManager() private var statusItem: NSStatusItem? private var popover = NSPopover() + // Store the last view and icon for restart + private var lastView: (() -> AnyView)? + private var lastIcon: String? func addMenuBarExtra(withView view: @escaping () -> V, icon: String) { guard statusItem == nil else { return } + // Remember the last view and icon + lastView = { AnyView(view()) } + lastIcon = icon + // Initialize the status item statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) // Set up the status item's button - if let button = statusItem?.button { + if let button = statusItem?.button{ if NSImage(systemSymbolName: icon, accessibilityDescription: nil) != nil { button.image = NSImage(systemSymbolName: icon, accessibilityDescription: "Pearcleaner") } else { @@ -29,6 +36,7 @@ class MenuBarExtraManager { } button.action = #selector(togglePopover(_:)) button.target = self + button.sendAction(on: [.leftMouseDown, .rightMouseDown]) } // Set up the popover @@ -54,13 +62,16 @@ class MenuBarExtraManager { } } -// func getStatus() -> Bool { -// if let item = statusItem { -// return true -// } else { -// return false -// } -// } + func restartMenuBarExtra() { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + self.removeMenuBarExtra() + + // Ensure the last view and icon are available before re-adding + if let lastView = self.lastView, let lastIcon = self.lastIcon { + self.addMenuBarExtra(withView: lastView, icon: lastIcon) + } + } + } @objc func togglePopover(_ sender: AnyObject?) { if let button = statusItem?.button { @@ -71,4 +82,6 @@ class MenuBarExtraManager { } } } + + } diff --git a/Pearcleaner/Windows/WindowSettings.swift b/Pearcleaner/Windows/WindowSettings.swift index ac6226c..9f3e406 100644 --- a/Pearcleaner/Windows/WindowSettings.swift +++ b/Pearcleaner/Windows/WindowSettings.swift @@ -35,6 +35,7 @@ class WindowSettings { } func newWindow(withView view: @escaping () -> V) { + findAndHideWindows(named: ["Pearcleaner"]) let contentView = view let frame = self.loadWindowSettings() let newWindow = NSWindow( @@ -44,7 +45,9 @@ class WindowSettings { newWindow.titlebarAppearsTransparent = true newWindow.isMovableByWindowBackground = true newWindow.center() - newWindow.setFrameAutosaveName("Main Window") + newWindow.title = "Pearcleaner" + newWindow.titleVisibility = .hidden + newWindow.setFrameAutosaveName("Pearcleaner") newWindow.contentView = NSHostingView(rootView: contentView()) // self.window = newWindow self.windows.append(newWindow)