From e3fe9ad281e7753de5e5c6906fc12cb783a64040 Mon Sep 17 00:00:00 2001 From: Alin Date: Tue, 14 Nov 2023 13:41:21 -0700 Subject: [PATCH] v1.2 --- Pearcleaner.xcodeproj/project.pbxproj | 16 +- Pearcleaner/Logic/AppState.swift | 8 + Pearcleaner/Logic/DeepLink.swift | 67 ++++-- Pearcleaner/Logic/Styles.swift | 18 +- Pearcleaner/Logic/Utilities.swift | 16 +- Pearcleaner/PearcleanerApp.swift | 137 ++++++++---- .../logo.imageset/Contents.json | 2 +- .../logo.imageset/logo_combo.png | Bin 20291 -> 0 bytes .../logo.imageset/logo_combo_small.png | Bin 0 -> 22186 bytes .../pear.imageset/Contents.json | 21 ++ .../pear.imageset/pear_small.png | Bin 0 -> 11692 bytes Pearcleaner/Resources/Info.plist | 15 ++ Pearcleaner/Settings/About.swift | 2 +- Pearcleaner/Settings/General.swift | 66 ++++-- Pearcleaner/Settings/Update.swift | 7 +- Pearcleaner/Views/AppListView.swift | 47 ++-- Pearcleaner/Views/DropTarget.swift | 12 +- Pearcleaner/Views/FilesView.swift | 16 +- Pearcleaner/Views/MiniMode.swift | 203 ++++++++++++++++++ Pearcleaner/Views/TopBar.swift | 104 +++------ Pearcleaner/Views/TopBarMini.swift | 111 ++++++++++ 21 files changed, 673 insertions(+), 195 deletions(-) delete mode 100644 Pearcleaner/Resources/Assets.xcassets/logo.imageset/logo_combo.png create mode 100644 Pearcleaner/Resources/Assets.xcassets/logo.imageset/logo_combo_small.png create mode 100644 Pearcleaner/Resources/Assets.xcassets/pear.imageset/Contents.json create mode 100644 Pearcleaner/Resources/Assets.xcassets/pear.imageset/pear_small.png create mode 100644 Pearcleaner/Views/MiniMode.swift create mode 100644 Pearcleaner/Views/TopBarMini.swift diff --git a/Pearcleaner.xcodeproj/project.pbxproj b/Pearcleaner.xcodeproj/project.pbxproj index 5eab03a..32e0c4f 100644 --- a/Pearcleaner.xcodeproj/project.pbxproj +++ b/Pearcleaner.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + C7045A282B03E71D00376976 /* MiniMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7045A272B03E71D00376976 /* MiniMode.swift */; }; + C7045A2A2B03FAF000376976 /* TopBarMini.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7045A292B03FAF000376976 /* TopBarMini.swift */; }; C72893052AFD42E600C8C1CD /* DeepLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = C72893042AFD42E600C8C1CD /* DeepLink.swift */; }; C72893122AFD51EA00C8C1CD /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = C72893112AFD51EA00C8C1CD /* main.swift */; }; C7575D382B0181FC006A600A /* FileWatcher in Frameworks */ = {isa = PBXBuildFile; productRef = C7575D372B0181FC006A600A /* FileWatcher */; }; @@ -59,6 +61,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + C7045A272B03E71D00376976 /* MiniMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MiniMode.swift; sourceTree = ""; }; + C7045A292B03FAF000376976 /* TopBarMini.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopBarMini.swift; sourceTree = ""; }; C72893042AFD42E600C8C1CD /* DeepLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeepLink.swift; sourceTree = ""; }; C728930F2AFD51EA00C8C1CD /* PearcleanerSentinel */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = PearcleanerSentinel; sourceTree = BUILT_PRODUCTS_DIR; }; C72893112AFD51EA00C8C1CD /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; @@ -206,9 +210,11 @@ C77B90222AF2D616009CC655 /* FilesView.swift */, C76D08542AF89CDE00D07867 /* AppListView.swift */, C7D31D472AFEB23700C7ED9E /* TopBar.swift */, + C7045A292B03FAF000376976 /* TopBarMini.swift */, C7D31D492AFEB26700C7ED9E /* AppListItems.swift */, C7D31D522B0048BE00C7ED9E /* TrashView.swift */, C7D31D582B00A49300C7ED9E /* DropTarget.swift */, + C7045A272B03E71D00376976 /* MiniMode.swift */, ); path = Views; sourceTree = ""; @@ -336,7 +342,9 @@ C7D31D462AFDA90C00C7ED9E /* Sentinel.swift in Sources */, C7D31D592B00A49300C7ED9E /* DropTarget.swift in Sources */, C77B90062AF18E2E009CC655 /* ContentView.swift in Sources */, + C7045A2A2B03FAF000376976 /* TopBarMini.swift in Sources */, C77B901C2AF193A3009CC655 /* Styles.swift in Sources */, + C7045A282B03E71D00376976 /* MiniMode.swift in Sources */, C72893052AFD42E600C8C1CD /* DeepLink.swift in Sources */, C76D084C2AF83C9D00D07867 /* Permissions.swift in Sources */, C76D084A2AF83C6E00D07867 /* General.swift in Sources */, @@ -517,7 +525,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = BK8443AXLU; ENABLE_HARDENED_RUNTIME = YES; @@ -534,7 +542,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.1; + MARKETING_VERSION = 1.2; PRODUCT_BUNDLE_IDENTIFIER = com.alienator88.Pearcleaner; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -551,7 +559,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = BK8443AXLU; ENABLE_HARDENED_RUNTIME = YES; @@ -568,7 +576,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 13.0; - MARKETING_VERSION = 1.1; + MARKETING_VERSION = 1.2; PRODUCT_BUNDLE_IDENTIFIER = com.alienator88.Pearcleaner; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; diff --git a/Pearcleaner/Logic/AppState.swift b/Pearcleaner/Logic/AppState.swift index 15c9348..7b17ccc 100644 --- a/Pearcleaner/Logic/AppState.swift +++ b/Pearcleaner/Logic/AppState.swift @@ -19,6 +19,7 @@ class AppState: ObservableObject @Published var selectedItems = Set() @Published var alertType = AlertType.off @Published var currentView = CurrentDetailsView.empty +// @Published var currentMode = CurrentMode.regular @Published var showAlert: Bool = false @Published var sidebar: Bool = true @Published var isReminderVisible: Bool = false @@ -74,8 +75,15 @@ enum CurrentDetailsView:Int { case empty case files + case apps } +//enum CurrentMode:Int +//{ +// case regular +// case mini +//} + enum AlertType:Int { case diskAccess diff --git a/Pearcleaner/Logic/DeepLink.swift b/Pearcleaner/Logic/DeepLink.swift index 0949af2..76ff08a 100644 --- a/Pearcleaner/Logic/DeepLink.swift +++ b/Pearcleaner/Logic/DeepLink.swift @@ -17,25 +17,58 @@ class DeeplinkManager { } func manage(url: URL, appState: AppState) { - guard url.scheme == DeepLinkConstants.scheme, - url.host == DeepLinkConstants.host, - let components = URLComponents(url: url, resolvingAgainstBaseURL: true), - let queryItems = components.queryItems - else { - print("URL does not match the expected scheme and host") - return - } - - if let path = queryItems.first(where: { $0.name == DeepLinkConstants.query })?.value { - let pathURL = URL(fileURLWithPath: path) - let appInfo = getAppInfo(atPath: pathURL) - updateOnMain { - appState.appInfo = appInfo! - findPathsForApp(appState: appState, appInfo: appState.appInfo) - appState.currentView = .files + if url.pathExtension == "app" { + handleAppBundle(url: url, appState: appState) + } else if url.scheme == DeepLinkConstants.scheme, + url.host == DeepLinkConstants.host, + let components = URLComponents(url: url, resolvingAgainstBaseURL: true), + let queryItems = components.queryItems { + if let path = queryItems.first(where: { $0.name == DeepLinkConstants.query })?.value { + let pathURL = URL(fileURLWithPath: path) + let appInfo = getAppInfo(atPath: pathURL) + updateOnMain { + appState.appInfo = appInfo! + findPathsForApp(appState: appState, appInfo: appState.appInfo) + appState.currentView = .files + } + } else { + print("No path query parameter found in the URL") } } else { - print("No path query parameter found in the URL") + print("URL does not match the expected scheme and host") } } + +// func manage(url: URL, appState: AppState) { +// guard url.scheme == DeepLinkConstants.scheme, +// url.host == DeepLinkConstants.host, +// let components = URLComponents(url: url, resolvingAgainstBaseURL: true), +// let queryItems = components.queryItems +// else { +// print("URL does not match the expected scheme and host") +// return +// } +// +// if let path = queryItems.first(where: { $0.name == DeepLinkConstants.query })?.value { +// let pathURL = URL(fileURLWithPath: path) +// let appInfo = getAppInfo(atPath: pathURL) +// updateOnMain { +// appState.appInfo = appInfo! +// findPathsForApp(appState: appState, appInfo: appState.appInfo) +// appState.currentView = .files +// } +// } else { +// print("No path query parameter found in the URL") +// } +// } + + func handleAppBundle(url: URL, appState: AppState) { + let appInfo = getAppInfo(atPath: url) + updateOnMain { + appState.appInfo = appInfo! + findPathsForApp(appState: appState, appInfo: appState.appInfo) + appState.currentView = .files + } + } + } diff --git a/Pearcleaner/Logic/Styles.swift b/Pearcleaner/Logic/Styles.swift index 803c379..837f9ef 100644 --- a/Pearcleaner/Logic/Styles.swift +++ b/Pearcleaner/Logic/Styles.swift @@ -28,18 +28,18 @@ struct SimpleButtonStyle: ButtonStyle { .resizable() .scaledToFit() .frame(width: 20) - .foregroundColor(color) + .foregroundColor(hovered ? color : color.opacity(0.5)) } .padding(8) - .background { - if hovered && !(shield ?? false) { -// Circle() +// .background { +// if hovered && !(shield ?? false) { +//// Circle() +//// .strokeBorder(Color("AccentColor"), lineWidth: 1) +// RoundedRectangle(cornerRadius: 8) // .strokeBorder(Color("AccentColor"), lineWidth: 1) - RoundedRectangle(cornerRadius: 8) - .strokeBorder(Color("AccentColor"), lineWidth: 1) - } - - } +// } +// +// } .onHover { hovering in withAnimation() { hovered = hovering diff --git a/Pearcleaner/Logic/Utilities.swift b/Pearcleaner/Logic/Utilities.swift index dad15f0..6e40fb2 100644 --- a/Pearcleaner/Logic/Utilities.swift +++ b/Pearcleaner/Logic/Utilities.swift @@ -24,6 +24,15 @@ func updateOnBackground(_ updates: @escaping () -> Void) { } +// Resize window +func resizeWindow() { + if let window = NSApplication.shared.windows.first { + let newSize = NSSize(width: 500, height: 450) + window.setContentSize(newSize) + } +} + + // Check for access to Full Disk access func checkAndRequestFullDiskAccess(appState: AppState, skipAlert: Bool = false) -> Bool { @AppStorage("settings.permissions.disk") var diskP: Bool = false @@ -268,8 +277,9 @@ func presentAlert(appState: AppState) -> Alert { switch appState.alertType { case .update: - return Alert(title: Text("Update Available 🥳"), message: Text("You may choose to install the update now, otherwise you may start the update later from Settings"), primaryButton: .default(Text("Install")) { - downloadUpdate(appState: appState) + return Alert(title: Text("Update Available 🥳"), message: Text("You may choose to install the update now, otherwise you may check again later from Settings"), primaryButton: .default(Text("Open")) { +// downloadUpdate(appState: appState) + launchUpdate() appState.alertType = .off }, secondaryButton: .cancel()) case .no_update: @@ -278,7 +288,7 @@ func presentAlert(appState: AppState) -> Alert { appState.alertType = .off }) case .diskAccess: - return Alert(title: Text("Permissions"), message: Text("This application requires Full Disk and Accessibility permissions. Once you grant full disk, don't restart the app yet. Wait a second for a second prompt for accessibility and then restart"), primaryButton: .default(Text("Allow in Settings")) { + return Alert(title: Text("Permissions"), message: Text("This application requires Full Disk and Accessibility permissions. Drag the app into the Full Disk pane if not visible."), primaryButton: .default(Text("Allow in Settings")) { if let url = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_AllFiles") { NSWorkspace.shared.open(url) } diff --git a/Pearcleaner/PearcleanerApp.swift b/Pearcleaner/PearcleanerApp.swift index 231a701..41d9c7f 100644 --- a/Pearcleaner/PearcleanerApp.swift +++ b/Pearcleaner/PearcleanerApp.swift @@ -16,54 +16,108 @@ struct PearcleanerApp: App { @AppStorage("settings.permissions.disk") private var diskP: Bool = false @AppStorage("settings.permissions.events") private var diskE: Bool = false @AppStorage("displayMode") var displayMode: DisplayMode = .dark + @AppStorage("settings.general.mini") private var mini: Bool = false @State private var search = "" var body: some Scene { WindowGroup { - AppListView(search: $search) - .environmentObject(appState) - .frame(minWidth: 1020, minHeight: 700) - .preferredColorScheme(displayMode.colorScheme) - .alert(isPresented: $appState.showAlert) { presentAlert(appState: appState) } - .handlesExternalEvents(preferring: Set(arrayLiteral: "pear"), allowing: Set(arrayLiteral: "*")) - .onAppear { - NSWindow.allowsAutomaticWindowTabbing = false - - // Get Apps - let sortedApps = getSortedApps() - appState.sortedApps.userApps = sortedApps.userApps - appState.sortedApps.systemApps = sortedApps.systemApps - - Task { + if !mini { + AppListView(search: $search) + .environmentObject(appState) + .frame(minWidth: 1020, minHeight: 700) + .preferredColorScheme(displayMode.colorScheme) + .alert(isPresented: $appState.showAlert) { presentAlert(appState: appState) } + .handlesExternalEvents(preferring: Set(arrayLiteral: "pear"), allowing: Set(arrayLiteral: "*")) + .onAppear { + NSWindow.allowsAutomaticWindowTabbing = false + // Get Apps + let sortedApps = getSortedApps() + appState.sortedApps.userApps = sortedApps.userApps + appState.sortedApps.systemApps = sortedApps.systemApps + + Task { + #if !DEBUG - - // Make sure App Support folder exists in the future if needed for storage - ensureApplicationSupportFolderExists(appState: appState) - - // Check for updates - if diskP && diskE { - loadGithubReleases(appState: appState) - } - - // Check for disk/accessibility permissions - _ = checkAndRequestFullDiskAccess(appState: appState) - - - // TIMERS //////////////////////////////////////////////////////////////////////////////////// - - // Check for app updates every 8 hours or whatever user saved setting. Also refresh autosuggestion list - let updateSeconds = updateTimeframe.daysToSeconds - _ = Timer.scheduledTimer(withTimeInterval: updateSeconds, repeats: true) { _ in - DispatchQueue.main.async { + + // Make sure App Support folder exists in the future if needed for storage + ensureApplicationSupportFolderExists(appState: appState) + let fileManager = FileManager.default + let destinationURL = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!.appendingPathComponent("Pearcleaner").appendingPathComponent("Pearcleaner.zip") + try? fileManager.removeItem(at: destinationURL) + + // Check for updates + if diskP && diskE { loadGithubReleases(appState: appState) } - } - + + // Check for disk/accessibility permissions + _ = checkAndRequestFullDiskAccess(appState: appState) + + + // TIMERS //////////////////////////////////////////////////////////////////////////////////// + + // Check for app updates every 8 hours or whatever user saved setting. Also refresh autosuggestion list + let updateSeconds = updateTimeframe.daysToSeconds + _ = Timer.scheduledTimer(withTimeInterval: updateSeconds, repeats: true) { _ in + DispatchQueue.main.async { + loadGithubReleases(appState: appState) + } + } + #endif + } } - } + } else { + MiniMode(search: $search) + .environmentObject(appState) + .frame(minWidth: 500, minHeight: 450) + .preferredColorScheme(displayMode.colorScheme) + .alert(isPresented: $appState.showAlert) { presentAlert(appState: appState) } + .handlesExternalEvents(preferring: Set(arrayLiteral: "pear"), allowing: Set(arrayLiteral: "*")) + .onAppear { + NSWindow.allowsAutomaticWindowTabbing = false + + // Get Apps + let sortedApps = getSortedApps() + appState.sortedApps.userApps = sortedApps.userApps + appState.sortedApps.systemApps = sortedApps.systemApps + + Task { + +#if !DEBUG + + // Make sure App Support folder exists in the future if needed for storage + ensureApplicationSupportFolderExists(appState: appState) + let fileManager = FileManager.default + let destinationURL = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!.appendingPathComponent("Pearcleaner").appendingPathComponent("Pearcleaner.zip") + try? fileManager.removeItem(at: destinationURL) + + // Check for updates + if diskP && diskE { + loadGithubReleases(appState: appState) + } + + // Check for disk/accessibility permissions + _ = checkAndRequestFullDiskAccess(appState: appState) + + + // TIMERS //////////////////////////////////////////////////////////////////////////////////// + + // Check for app updates every 8 hours or whatever user saved setting. Also refresh autosuggestion list + let updateSeconds = updateTimeframe.daysToSeconds + _ = Timer.scheduledTimer(withTimeInterval: updateSeconds, repeats: true) { _ in + DispatchQueue.main.async { + loadGithubReleases(appState: appState) + } + } + +#endif + } + } + } + } .windowStyle(.hiddenTitleBar) .windowToolbarStyle(.unified) @@ -73,6 +127,7 @@ struct PearcleanerApp: App { CommandGroup(replacing: .newItem, addition: { }) } + Settings { SettingsView() .environmentObject(appState) @@ -89,4 +144,12 @@ class AppDelegate: NSObject, NSApplicationDelegate { func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true } +// func application(_ sender: NSApplication, open urls: [URL]) { +// for url in urls { +// if url.pathExtension == "app" { +// print("Dropped app path:", url.path) +// } +// } +// } } + diff --git a/Pearcleaner/Resources/Assets.xcassets/logo.imageset/Contents.json b/Pearcleaner/Resources/Assets.xcassets/logo.imageset/Contents.json index 38a858c..3fb7627 100644 --- a/Pearcleaner/Resources/Assets.xcassets/logo.imageset/Contents.json +++ b/Pearcleaner/Resources/Assets.xcassets/logo.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "logo_combo.png", + "filename" : "logo_combo_small.png", "idiom" : "universal", "scale" : "1x" }, diff --git a/Pearcleaner/Resources/Assets.xcassets/logo.imageset/logo_combo.png b/Pearcleaner/Resources/Assets.xcassets/logo.imageset/logo_combo.png deleted file mode 100644 index ae575d542a128d29efca616c252631e016fea6df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20291 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 z 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 literal 0 HcmV?d00001 diff --git a/Pearcleaner/Resources/Assets.xcassets/pear.imageset/Contents.json b/Pearcleaner/Resources/Assets.xcassets/pear.imageset/Contents.json new file mode 100644 index 0000000..9460316 --- /dev/null +++ b/Pearcleaner/Resources/Assets.xcassets/pear.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "pear_small.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Pearcleaner/Resources/Assets.xcassets/pear.imageset/pear_small.png b/Pearcleaner/Resources/Assets.xcassets/pear.imageset/pear_small.png new file mode 100644 index 0000000000000000000000000000000000000000..5f4b01fe67ed9de91f3f8d28379588399514ffd1 GIT binary patch literal 11692 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 + CFBundleDocumentTypes + + + CFBundleTypeName + Application Bundle + LSHandlerRank + Default + CFBundleTypeRole + Viewer + LSItemContentTypes + + com.apple.application-bundle + + + CFBundleURLTypes diff --git a/Pearcleaner/Settings/About.swift b/Pearcleaner/Settings/About.swift index 6edc9dc..47ec869 100644 --- a/Pearcleaner/Settings/About.swift +++ b/Pearcleaner/Settings/About.swift @@ -29,7 +29,7 @@ struct AboutSettingsTab: View { .buttonStyle(SimpleButtonStyle(icon: "cloud", help: "Update application", color: Color("AccentColor"))) Button("") { - NSWorkspace.shared.open(URL(string: "https://github.com/ghosted-labs/Pearcleaner")!) + NSWorkspace.shared.open(URL(string: "https://github.com/alienator88/Pearcleaner")!) } .buttonStyle(SimpleButtonStyle(icon: "paperplane", help: "View repository", color: Color("AccentColor"))) } diff --git a/Pearcleaner/Settings/General.swift b/Pearcleaner/Settings/General.swift index 8fd7896..788f6fc 100644 --- a/Pearcleaner/Settings/General.swift +++ b/Pearcleaner/Settings/General.swift @@ -11,8 +11,10 @@ import SwiftUI struct GeneralSettingsTab: View { @EnvironmentObject var appState: AppState @AppStorage("settings.general.glass") private var glass: Bool = true -// @AppStorage("settings.general.ants") private var ants: Bool = false - + @AppStorage("settings.general.mini") private var mini: Bool = false + @AppStorage("settings.general.dark") var isDark: Bool = true + @AppStorage("displayMode") var displayMode: DisplayMode = .dark + var body: some View { Form { VStack { @@ -34,30 +36,54 @@ struct GeneralSettingsTab: View { .fill(Color("mode").opacity(0.05)) ) -// HStack { -// VStack(alignment: .leading, spacing: 5) { -// Text("Animation").font(.title2) -// Text("Toggles the marching ants animation on the drop zone") -// .font(.footnote) -// .foregroundStyle(.gray) -// } -// Spacer() -// Toggle(isOn: $ants, label: { -// }) -// .toggleStyle(.switch) -// } -// .padding() -// .background( -// RoundedRectangle(cornerRadius: 8) -// .fill(Color("mode").opacity(0.05)) -// ) + HStack { + VStack(alignment: .leading, spacing: 5) { + Text("Dark Mode").font(.title2) + Text("Toggles between dark and light mode") + .font(.footnote) + .foregroundStyle(.gray) + } + Spacer() + Toggle(isOn: $isDark, label: { + }) + .toggleStyle(.switch) + .onChange(of: isDark) { newValue in + displayMode.colorScheme = newValue ? .dark : .light + } + } + .padding() + .background( + RoundedRectangle(cornerRadius: 8) + .fill(Color("mode").opacity(0.05)) + ) + + HStack { + VStack(alignment: .leading, spacing: 5) { + Text("Mini").font(.title2) + Text("Toggles a smaller, unified view with hidden app list") + .font(.footnote) + .foregroundStyle(.gray) + } + Spacer() + Toggle(isOn: $mini, label: { + }) + .toggleStyle(.switch) + .onChange(of: mini) { newVal in + resizeWindow() + } + } + .padding() + .background( + RoundedRectangle(cornerRadius: 8) + .fill(Color("mode").opacity(0.05)) + ) Spacer() } } .padding(20) - .frame(width: 400, height: 100) + .frame(width: 400, height: 250) } diff --git a/Pearcleaner/Settings/Update.swift b/Pearcleaner/Settings/Update.swift index 5a5529b..1459542 100644 --- a/Pearcleaner/Settings/Update.swift +++ b/Pearcleaner/Settings/Update.swift @@ -124,6 +124,11 @@ func checkForUpdate(appState: AppState, manual: Bool = false) { } } +func launchUpdate() { + NSWorkspace.shared.open(URL(string: "https://github.com/alienator88/Pearcleaner/releases")!) + +} + func downloadUpdate(appState: AppState) { guard let latestRelease = appState.releases.first else { return } guard let asset = latestRelease.assets.first else { return } @@ -140,7 +145,7 @@ func downloadUpdate(appState: AppState) { do { if fileManager.fileExists(atPath: destinationURL.path) { - try fileManager.removeItem(at: destinationURL) + try? fileManager.removeItem(at: destinationURL) } try fileManager.moveItem(at: localURL, to: destinationURL) diff --git a/Pearcleaner/Views/AppListView.swift b/Pearcleaner/Views/AppListView.swift index 6ae1120..c933619 100644 --- a/Pearcleaner/Views/AppListView.swift +++ b/Pearcleaner/Views/AppListView.swift @@ -53,7 +53,24 @@ struct AppListView: View { VStack(alignment: .center) { VStack(alignment: .center, spacing: 20) { - SearchBar(search: $search) + HStack { + SearchBar(search: $search) + + Button("") { + withAnimation(.easeInOut(duration: 0.5)) { + // Refresh Apps list + reload.toggle() + let sortedApps = getSortedApps() + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + appState.sortedApps.userApps = sortedApps.userApps + appState.sortedApps.systemApps = sortedApps.systemApps + reload.toggle() + } + + } + } + .buttonStyle(SimpleButtonStyle(icon: "arrow.triangle.2.circlepath", help: "Refresh app list", color: Color("mode"))) + } } .padding(.horizontal) .padding(.top, 20) @@ -157,20 +174,20 @@ struct AppDetailsEmptyView: View { Spacer() - if appState.isReminderVisible { - Text("􀆔 + Z to undo") - .font(.title2) - .foregroundStyle(Color("AccentColor").opacity(0.5)) - .fontWeight(.medium) - .onAppear { - DispatchQueue.main.asyncAfter(deadline: .now() + 2) { - withAnimation { - appState.isReminderVisible = false - } - } - } - Spacer() - } +// if appState.isReminderVisible { +// Text("􀆔 + Z to undo") +// .font(.title2) +// .foregroundStyle(Color("AccentColor").opacity(0.5)) +// .fontWeight(.medium) +// .onAppear { +// DispatchQueue.main.asyncAfter(deadline: .now() + 2) { +// withAnimation { +// appState.isReminderVisible = false +// } +// } +// } +// Spacer() +// } Text("Drop an app above or select one from the list to begin") .font(.title3) diff --git a/Pearcleaner/Views/DropTarget.swift b/Pearcleaner/Views/DropTarget.swift index b2e0f10..16c1427 100644 --- a/Pearcleaner/Views/DropTarget.swift +++ b/Pearcleaner/Views/DropTarget.swift @@ -11,6 +11,7 @@ import UniformTypeIdentifiers struct DropTarget: View, DropDelegate { @AppStorage("settings.general.ants") private var ants: Bool = false + @AppStorage("settings.general.mini") private var mini: Bool = false @ObservedObject var appState: AppState @State private var shouldFlash = false private var types: [UTType] = [.fileURL] @@ -34,15 +35,16 @@ struct DropTarget: View, DropDelegate { ZStack { LinearGradient(gradient: Gradient(colors: [.pink, .orange]), startPoint: .leading, endPoint: .trailing) - .mask(Image("logo") + .mask( + Image(mini ? "pear" : "logo") .resizable() - .scaledToFit()) + .scaledToFit() + .frame(width: mini ? 104 : 500) + ) } - .frame(width: 500, height: 200) Spacer() - } Spacer() @@ -71,6 +73,8 @@ struct DropTarget: View, DropDelegate { } .onDrop(of: types, delegate: self) .padding(20) + .frame(maxWidth: mini ? 200 : .infinity) + .frame(maxHeight: mini ? 200 : .infinity) } diff --git a/Pearcleaner/Views/FilesView.swift b/Pearcleaner/Views/FilesView.swift index a1917c5..554468f 100644 --- a/Pearcleaner/Views/FilesView.swift +++ b/Pearcleaner/Views/FilesView.swift @@ -14,6 +14,7 @@ struct FilesView: View { @State private var showDetails: Bool = false @State private var showPop: Bool = false @State private var itemDetails: [(size: String, icon: Image?)] = [] + @AppStorage("settings.general.mini") private var mini: Bool = false @Environment(\.colorScheme) var colorScheme var body: some View { @@ -34,8 +35,9 @@ struct FilesView: View { if let appIcon = appState.appInfo.appIcon { Image(nsImage: appIcon) .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: 100, height: 100) + .scaledToFit() +// .aspectRatio(contentMode: .fit) + .frame(width: 50, height: 50) .padding(.leading) } //app title, size and items @@ -43,19 +45,19 @@ struct FilesView: View { HStack(alignment: .center) { VStack(alignment: .leading, spacing: 5){ HStack { - Text("\(appState.appInfo.appName)").font(.title).fontWeight(.bold) + Text("\(appState.appInfo.appName)").font(mini ? .title2 :.title).fontWeight(.bold) // .foregroundStyle(Color("AccentColor")) Text("•").foregroundStyle(Color("AccentColor")) Text("\(appState.appInfo.appVersion)").font(.title3) // .foregroundStyle(.gray.opacity(0.8)) } - Text("\(appState.appInfo.bundleIdentifier)").font(.title3) + Text("\(appState.appInfo.bundleIdentifier)").font(mini ? .footnote :.title3) .foregroundStyle((.gray.opacity(0.8))) } Spacer() - Text("\(appSize)").font(.title).fontWeight(.bold) + Text("\(appSize)").font(mini ? .title2 :.title).fontWeight(.bold) // .foregroundStyle(Color("AccentColor")) } @@ -180,7 +182,7 @@ struct FilesView: View { } } - .frame(minWidth: 700) +// .frame(minWidth: 700) .onAppear { Task { calculateFileDetails() @@ -291,7 +293,7 @@ struct FileDetailsItem: View { Button("") { NSWorkspace.shared.selectFile(path.path, inFileViewerRootedAtPath: path.deletingLastPathComponent().path) } - .buttonStyle(SimpleButtonStyle(icon: "folder.fill", help: "Show in Finder", color: Color("AccentColor"))) + .buttonStyle(SimpleButtonStyle(icon: "folder.fill", help: "Show in Finder", color: Color("mode"))) } .background( diff --git a/Pearcleaner/Views/MiniMode.swift b/Pearcleaner/Views/MiniMode.swift new file mode 100644 index 0000000..d488c67 --- /dev/null +++ b/Pearcleaner/Views/MiniMode.swift @@ -0,0 +1,203 @@ +// +// MiniMode.swift +// Pearcleaner +// +// Created by Alin Lupascu on 11/14/23. +// + + +import Foundation +import SwiftUI + +struct MiniMode: View { + @EnvironmentObject var appState: AppState + @Binding var search: String + @State private var showSys: Bool = true + @State private var showUsr: Bool = true + @State private var reload: Bool = false + + + + var body: some View { + + HStack(alignment: .center, spacing: 0) { + + // Main Mini View + VStack(spacing: 0) { + if appState.currentView == .empty { + TopBarMini(reload: $reload, search: $search) + AppDetailsEmptyView() + } else if appState.currentView == .files { + TopBarMini(reload: $reload, search: $search) + FilesView() + .id(appState.appInfo.id) + } else if appState.currentView == .apps { + TopBarMini(reload: $reload, search: $search) + MiniAppView(search: $search, reload: $reload) + } + } + // .padding(.leading, appState.sidebar ? 0 : 10) + .transition(.move(edge: .leading)) + + } + .edgesIgnoringSafeArea(.all) + .onOpenURL(perform: { url in + let deeplinkManager = DeeplinkManager() + deeplinkManager.manage(url: url, appState: appState) + }) + // MARK: Background for whole app + // .background(Color("bg").opacity(1)) + // .background(VisualEffect(material: .sidebar, blendingMode: .behindWindow).edgesIgnoringSafeArea(.all)) + } +} + + + + + + +struct MiniEmptyView: View { + @Environment(\.colorScheme) var colorScheme + @EnvironmentObject var appState: AppState + @State private var animateGradient: Bool = false + @AppStorage("settings.general.mini") private var mini: Bool = false + + var body: some View { + VStack() { + + Spacer() + + DropTarget(appState: appState) + .frame(maxWidth: mini ? 300 : 500) + + Spacer() + + if appState.isReminderVisible { + Text("CMD + Z to undo") + .font(.title2) + .foregroundStyle(Color("AccentColor").opacity(0.5)) + .fontWeight(.medium) + .onAppear { + DispatchQueue.main.asyncAfter(deadline: .now() + 2) { + withAnimation { + appState.isReminderVisible = false + } + } + } + Spacer() + } + + Text("Drop an app above or select one from the list to begin") + .font(.title3) + .padding(.bottom, 25) + .opacity(0.5) + } + } +} + + + + + +struct MiniAppView: View { + @Environment(\.colorScheme) var colorScheme + @EnvironmentObject var appState: AppState + @State private var animateGradient: Bool = false + @Binding var search: String + @State private var showSys: Bool = true + @State private var showUsr: Bool = true + @Binding var reload: Bool + @AppStorage("settings.general.mini") private var mini: Bool = false + + var body: some View { + + var filteredUserApps: [AppInfo] { + if search.isEmpty { + return appState.sortedApps.userApps + } else { + return appState.sortedApps.userApps.filter { $0.appName.localizedCaseInsensitiveContains(search) } + } + } + + var filteredSystemApps: [AppInfo] { + if search.isEmpty { + return appState.sortedApps.systemApps + } else { + return appState.sortedApps.systemApps.filter { $0.appName.localizedCaseInsensitiveContains(search) } + } + } + + ZStack { + HStack(spacing: 0){ + + if reload { + VStack { + Spacer() + ProgressView("Refreshing applications") + Spacer() + } + .padding(.vertical) + } else { + VStack(alignment: .center) { + +// VStack(alignment: .center, spacing: 20) { +// HStack { +// SearchBar(search: $search) +// } +// } +// .padding(.horizontal, 5) +// .padding(.bottom) + + ScrollView { + + VStack(alignment: .leading) { + + if filteredUserApps.count > 0 { + VStack { + Header(title: "User", count: filteredUserApps.count) + ForEach(filteredUserApps, id: \.self) { appInfo in + AppListItems(appInfo: appInfo) + if appInfo != filteredUserApps.last { + Divider().padding(.horizontal, 5) + } + } + .padding(.bottom) + } + + } + + if filteredSystemApps.count > 0 { + VStack { + Header(title: "System", count: filteredSystemApps.count) + ForEach(filteredSystemApps, id: \.self) { appInfo in + AppListItems(appInfo: appInfo) + if appInfo != filteredSystemApps.last { + Divider().padding(.horizontal, 5) + } + } + } + } + + } + .padding(.horizontal) + + } + .scrollIndicators(.never) + + } + .padding(.vertical) + } + + + } + } + .transition(.move(edge: .leading)) + } +} + + + + + + + diff --git a/Pearcleaner/Views/TopBar.swift b/Pearcleaner/Views/TopBar.swift index 9137f45..ff46d72 100644 --- a/Pearcleaner/Views/TopBar.swift +++ b/Pearcleaner/Views/TopBar.swift @@ -9,57 +9,19 @@ import Foundation import SwiftUI struct TopBar: View { -// @Binding var sidebar: Bool + // @Binding var sidebar: Bool @Binding var reload: Bool @AppStorage("displayMode") var displayMode: DisplayMode = .system @AppStorage("settings.general.glass") private var glass: Bool = false @AppStorage("settings.sentinel.enable") private var sentinel: Bool = false + @AppStorage("settings.general.mini") private var mini: Bool = false @EnvironmentObject var appState: AppState - + var body: some View { HStack(alignment: .center, spacing: 20) { - HStack(alignment: .center, spacing: 5) { -// Button("") { -// withAnimation(.easeInOut(duration: 0.5)) { -// appState.sidebar.toggle() -// if appState.sidebar { -// appState.winWidth += 300 -// } else { -// appState.winWidth -= 300 -// } -// } -// } -// .buttonStyle(SimpleButtonStyle(icon: "sidebar.left", help: "Toggle Sidebar", color: Color("AccentColor"))) - - - Button("") { - withAnimation(.easeInOut(duration: 0.5)) { - // Refresh Apps list - reload.toggle() - let sortedApps = getSortedApps() - DispatchQueue.main.asyncAfter(deadline: .now() + 1) { - appState.sortedApps.userApps = sortedApps.userApps - appState.sortedApps.systemApps = sortedApps.systemApps - reload.toggle() - } - - } - } - .buttonStyle(SimpleButtonStyle(icon: "arrow.circlepath", help: "Refresh app list", color: Color("AccentColor"))) - - Button("") { - withAnimation(.easeInOut(duration: 0.5)) { - openTrash() - } - } - .buttonStyle(SimpleButtonStyle(icon: "trash", help: "Open Trash", color: Color("AccentColor"))) - } - Spacer() - - if appState.currentView != .empty { Button("") { withAnimation(.easeInOut(duration: 0.5)) { @@ -67,48 +29,38 @@ struct TopBar: View { appState.appInfo = AppInfo.empty } } - .buttonStyle(SimpleButtonStyle(icon: "house", help: "Home", color: Color("AccentColor"))) + .buttonStyle(SimpleButtonStyle(icon: "arrow.down.app", help: "Drop", color: Color("mode"))) } - - + if appState.isReminderVisible { + Text("CMD + Z to undo") + .font(.title2) + .foregroundStyle(Color("AccentColor").opacity(0.5)) + .fontWeight(.medium) + .onAppear { + DispatchQueue.main.asyncAfter(deadline: .now() + 2) { + withAnimation { + appState.isReminderVisible = false + } + } + } + } Spacer() - HStack(alignment: .center, spacing: 5) { - - if sentinel { - Button("") { - // - } - .buttonStyle(SimpleButtonStyle(icon: "lock.shield", help: "Sentinel enabled", color: .green, shield: true)) - } - - - Button("") { - withAnimation(.easeInOut(duration: 0.5)) { - glass.toggle() - } - } - .buttonStyle(SimpleButtonStyle(icon: glass ? "circle.dashed" : "circle.dashed.inset.filled", help: "Toggle transparency", color: Color("AccentColor"))) - - Button("") { - withAnimation(.easeInOut(duration: 0.5)) { - if displayMode.colorScheme == .dark { - displayMode.colorScheme = .light - } else if displayMode.colorScheme == .light { - displayMode.colorScheme = .dark - } else { - displayMode.colorScheme = .dark - } - } - } - .buttonStyle(SimpleButtonStyle(icon: displayMode.colorScheme == .dark ? "sun.max.fill" : "moon.fill", help: "Toggle appearance", color: Color("AccentColor"))) - } - + + +// if sentinel { +// Button("") { +// // +// } +// .buttonStyle(SimpleButtonStyle(icon: "lock.shield", help: "Sentinel enabled", color: .green, shield: true)) +// } + + } .padding(.horizontal, 20) - .padding(.top, 30) + .padding(.top, 20) } } diff --git a/Pearcleaner/Views/TopBarMini.swift b/Pearcleaner/Views/TopBarMini.swift new file mode 100644 index 0000000..cc04e62 --- /dev/null +++ b/Pearcleaner/Views/TopBarMini.swift @@ -0,0 +1,111 @@ +// +// TopBarMini.swift +// Pearcleaner +// +// Created by Alin Lupascu on 11/14/23. +// + +import Foundation +import SwiftUI + +struct TopBarMini: View { + @Binding var reload: Bool + @AppStorage("displayMode") var displayMode: DisplayMode = .system + @AppStorage("settings.sentinel.enable") private var sentinel: Bool = false + @AppStorage("settings.general.mini") private var mini: Bool = false + @Binding var search: String + @EnvironmentObject var appState: AppState + + var body: some View { + HStack(alignment: .center, spacing: 5) { + Spacer() + if appState.currentView == .apps { + HStack(alignment: .center, spacing: 0) { + Button("") { + withAnimation(.easeInOut(duration: 0.5)) { + appState.currentView = .empty + appState.appInfo = AppInfo.empty + } + } + .buttonStyle(SimpleButtonStyle(icon: "arrow.down.app", help: "Drop", color: Color("mode"))) + + + } + + } else if appState.currentView == .empty { + Button("") { + withAnimation(.easeInOut(duration: 0.5)) { + appState.currentView = .apps + } + } + .buttonStyle(SimpleButtonStyle(icon: "list.triangle", help: "Apps", color: Color("mode"))) + } else if appState.currentView == .files { + Button("") { + withAnimation(.easeInOut(duration: 0.5)) { + appState.currentView = .empty + appState.appInfo = AppInfo.empty + } + } + .buttonStyle(SimpleButtonStyle(icon: "arrow.down.app", help: "Drop", color: Color("mode"))) + Button("") { + withAnimation(.easeInOut(duration: 0.5)) { + appState.currentView = .apps + } + } + .buttonStyle(SimpleButtonStyle(icon: "list.triangle", help: "Apps", color: Color("mode"))) + } + + if appState.currentView == .apps { + HStack { + Spacer() + + SearchBarMini(search: $search) + + Spacer() + + Button("") { + withAnimation(.easeInOut(duration: 0.5)) { + // Refresh Apps list + reload.toggle() + let sortedApps = getSortedApps() + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + appState.sortedApps.userApps = sortedApps.userApps + appState.sortedApps.systemApps = sortedApps.systemApps + reload.toggle() + } + + } + } + .buttonStyle(SimpleButtonStyle(icon: "arrow.triangle.2.circlepath", help: "Refresh app list", color: Color("mode"))) + } + } + + + Spacer() + +// if sentinel { +// Button("") { +// // +// } +// .buttonStyle(SimpleButtonStyle(icon: "lock.shield", help: "Sentinel enabled", color: .green, shield: true)) +// } + + } + .edgesIgnoringSafeArea(.all) + .padding(.horizontal) + .padding(.top, 30) + } +} + + +struct SearchBarMini: View { + @Binding var search: String + + var body: some View { + HStack { + TextField("Search", text: $search) + .textFieldStyle(SimpleSearchStyle(trash: true, text: $search)) + } + .frame(height: 30) + } +}