diff --git a/Pearcleaner/Logic/AppState.swift b/Pearcleaner/Logic/AppState.swift index 9cc8e08..1ffe08c 100644 --- a/Pearcleaner/Logic/AppState.swift +++ b/Pearcleaner/Logic/AppState.swift @@ -18,7 +18,6 @@ class AppState: ObservableObject @Published var sortedApps: (userApps: [AppInfo], systemApps: [AppInfo]) = ([], []) @Published var selectedItems = Set() @Published var selectedZombieItems = Set() - @Published var trashedFiles: [URL] = [] @Published var alertType = AlertType.off @Published var currentView = CurrentDetailsView.empty @Published var showAlert: Bool = false @@ -107,16 +106,16 @@ struct ZombieFile: Identifiable, Equatable, Hashable { enum CurrentTabView:Int { case general - case permissions - case sentinel +// case permissions +// case sentinel case update case about var title: String { switch self { case .general: return "General" - case .permissions: return "Permissions" - case .sentinel: return "Sentinel" +// case .permissions: return "Permissions" +// case .sentinel: return "Sentinel" case .update: return "Update" case .about: return "About" } diff --git a/Pearcleaner/Logic/Logic.swift b/Pearcleaner/Logic/Logic.swift index 66b9614..32e3427 100644 --- a/Pearcleaner/Logic/Logic.swift +++ b/Pearcleaner/Logic/Logic.swift @@ -477,27 +477,27 @@ func showAppInFiles(appInfo: AppInfo, mini: Bool, appState: AppState, locations: if let storedAppInfo = appState.appInfoStore.first(where: { $0.path == appInfo.path }) { appState.appInfo = storedAppInfo appState.selectedItems = Set(storedAppInfo.files) -// withAnimation(Animation.easeIn(duration: 0.3)) { + withAnimation(Animation.easeIn(duration: 0.3)) { if mini { appState.currentView = .files showPopover.wrappedValue.toggle() } else { appState.currentView = .files } -// } + } } else { updateOnMain { appState.showProgress = true } // Handle the case where the appInfo is not found in the store -// withAnimation(Animation.easeIn(duration: 0.4)) { + withAnimation(Animation.easeIn(duration: 0.4)) { if mini { appState.currentView = .files showPopover.wrappedValue.toggle() } else { appState.currentView = .files } -// } + } printOS("AppInfo not found in the cached store, searching again") appState.appInfo = .empty appState.appInfo = appInfo diff --git a/Pearcleaner/Logic/Styles.swift b/Pearcleaner/Logic/Styles.swift index 03dd049..abcd821 100644 --- a/Pearcleaner/Logic/Styles.swift +++ b/Pearcleaner/Logic/Styles.swift @@ -31,20 +31,12 @@ struct SimpleButtonStyle: ButtonStyle { .foregroundColor(hovered ? color : color.opacity(0.5)) } .padding(5) -// .background { -// if hovered && !(shield ?? false) { -//// Circle() -//// .strokeBorder(Color("AccentColor"), lineWidth: 1) -// RoundedRectangle(cornerRadius: 8) -// .strokeBorder(Color("AccentColor"), lineWidth: 1) -// } -// -// } .onHover { hovering in withAnimation() { hovered = hovering } } + .scaleEffect(configuration.isPressed ? 0.95 : 1) .help(help) } } @@ -117,18 +109,18 @@ struct LabeledDivider: View { HStack(spacing: 0) { Rectangle() .frame(height: 1) - .foregroundColor(Color("AccentColor").opacity(0.2)) - + .foregroundColor(.gray.opacity(0.2)) + Text(label) .textCase(.uppercase) .font(.title2) - .foregroundColor(Color("AccentColor").opacity(0.6)) + .foregroundColor(.gray.opacity(0.6)) .padding(.horizontal, 10) .frame(minWidth: 80) Rectangle() .frame(height: 1) - .foregroundColor(Color("AccentColor").opacity(0.2)) + .foregroundColor(.gray.opacity(0.2)) } .frame(minHeight: 35) } @@ -577,8 +569,49 @@ struct PillPicker: View { - - +struct PearDropView: View { + + var body: some View { + VStack(alignment: .center, spacing: 0) { + HStack(spacing: 0) { + LinearGradient(gradient: Gradient(colors: [.pink, .orange]), startPoint: .leading, endPoint: .trailing) + .frame(width: 195) + LinearGradient(gradient: Gradient(colors: [.orange, .gray]), startPoint: .leading, endPoint: .trailing) + .frame(width: 10) + LinearGradient(gradient: Gradient(colors: [.gray, .gray]), startPoint: .leading, endPoint: .trailing) + .frame(width: 300) + } + .mask( + Image("logo_text_small") + .resizable() + .scaledToFit() + .frame(width: 500, height: 120) + .padding() + ) +// LinearGradient(gradient: Gradient(colors: [.gray, .gray]), startPoint: .leading, endPoint: .trailing) +// .mask( +// Image("logo_text_small") +// .resizable() +// .scaledToFit() +// .frame(minWidth: 300, maxWidth: 350) +// .frame(height: 100) +// .padding() +// ) + +// LinearGradient(gradient: Gradient(colors: [.pink, .orange]), startPoint: .leading, endPoint: .trailing) +// .mask( +// Image(systemName: "plus.square.dashed") +// .resizable() +// .scaledToFit() +// .frame(width: 50, height: 50) +// .padding() +// ) + } + .frame(height: 120) + + } +} + diff --git a/Pearcleaner/PearcleanerApp.swift b/Pearcleaner/PearcleanerApp.swift index 10cfa41..2f99b4b 100644 --- a/Pearcleaner/PearcleanerApp.swift +++ b/Pearcleaner/PearcleanerApp.swift @@ -85,16 +85,18 @@ struct PearcleanerApp: App { appState.sortedApps.userApps = sortedApps.userApps appState.sortedApps.systemApps = sortedApps.systemApps + + + +#if !DEBUG Task { // Find all app paths on load loadAllPaths(allApps: sortedApps.userApps + sortedApps.systemApps, appState: appState, locations: locations) -#if !DEBUG - // Make sure App Support folder exists in the future if needed for storage ensureApplicationSupportFolderExists(appState: appState) - + // Check for updates 1 minute after app launch if diskP { loadGithubReleases(appState: appState) @@ -105,10 +107,10 @@ struct PearcleanerApp: App { _ = checkAndRequestFullDiskAccess(appState: appState) hasLaunched = true } - - + + // 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 @@ -116,12 +118,10 @@ struct PearcleanerApp: App { loadGithubReleases(appState: appState) } } - -#endif } + +#endif } - - } .windowStyle(.hiddenTitleBar) .windowResizability(.contentMinSize) diff --git a/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128.png b/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128.png index 8f6af12..49165c5 100644 Binary files a/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128.png and b/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128.png differ diff --git a/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png b/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png index 97fdfb6..a913a26 100644 Binary files a/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png and b/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png differ diff --git a/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16.png b/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16.png index a7773ce..8127ccd 100644 Binary files a/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16.png and b/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16.png differ diff --git a/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png b/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png index b775f96..215a2ac 100644 Binary files a/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png and b/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png differ diff --git a/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256.png b/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256.png index 97fdfb6..a913a26 100644 Binary files a/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256.png and b/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256.png differ diff --git a/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png b/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png index 4d48a63..b47cc54 100644 Binary files a/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png and b/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png differ diff --git a/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32.png b/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32.png index b775f96..215a2ac 100644 Binary files a/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32.png and b/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32.png differ diff --git a/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png b/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png index 79ae243..596ad2b 100644 Binary files a/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png and b/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png differ diff --git a/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512.png b/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512.png index 4d48a63..b47cc54 100644 Binary files a/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512.png and b/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512.png differ diff --git a/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png b/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png index f10724c..80272cf 100644 Binary files a/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png and b/Pearcleaner/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png differ diff --git a/Pearcleaner/Resources/Assets.xcassets/logo_text_small.imageset/Contents.json b/Pearcleaner/Resources/Assets.xcassets/logo_text_small.imageset/Contents.json new file mode 100644 index 0000000..33a9993 --- /dev/null +++ b/Pearcleaner/Resources/Assets.xcassets/logo_text_small.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "logo_text_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/logo_text_small.imageset/logo_text_small.png b/Pearcleaner/Resources/Assets.xcassets/logo_text_small.imageset/logo_text_small.png new file mode 100644 index 0000000..81782ea Binary files /dev/null and b/Pearcleaner/Resources/Assets.xcassets/logo_text_small.imageset/logo_text_small.png differ diff --git a/Pearcleaner/Settings/About.swift b/Pearcleaner/Settings/About.swift index 5a55d72..ac79a76 100644 --- a/Pearcleaner/Settings/About.swift +++ b/Pearcleaner/Settings/About.swift @@ -9,148 +9,157 @@ import SwiftUI struct AboutSettingsTab: View { @EnvironmentObject var appState: AppState - + var body: some View { - - VStack { - - HStack(alignment: .center) { - VStack(alignment: .center, spacing: 10){ - Spacer() - - Image(nsImage: NSApp.applicationIconImage) - .padding() -// .padding(.bottom, 5) - - HStack(alignment: .center, spacing: 20) { - Button("") { - loadGithubReleases(appState: appState, manual: true) - } - .buttonStyle(SimpleButtonStyle(icon: "cloud", help: "Update application", color: Color("AccentColor"))) - - Button("") { - NSWorkspace.shared.open(URL(string: "https://github.com/alienator88/Pearcleaner")!) - } - .buttonStyle(SimpleButtonStyle(icon: "paperplane", help: "View repository", color: Color("AccentColor"))) - } - - Spacer() - - - } -// .padding() - // .padding(.top, 10) - .frame(width: 250) - - VStack(alignment: .center, spacing: 20) { - HStack(alignment: .firstTextBaseline) { - Text(Bundle.main.name) - .font(.title) - .bold() - Spacer() - HStack { - Text("v\(Bundle.main.version)") - Text(" (build \(Bundle.main.buildVersion))") - } - - } - Divider() - .padding(.top, -8) - - VStack(alignment: .leading) { - - HStack{ - Image(systemName: "applescript.fill") - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: 16, height: 16) - - VStack(alignment: .leading){ - Text("Privacy Guides") - Text("Inspired by open-source appcleaner script from Sun Knudsen").font(.footnote).foregroundStyle(.gray) - - } - Spacer() - - Button("") { - NSWorkspace.shared.open(URL(string: "https://sunknudsen.com/privacy-guides/how-to-clean-uninstall-macos-apps-using-appcleaner-open-source-alternative")!) - } - .buttonStyle(SimpleButtonStyle(icon: "paperplane", help: "View", color: Color("AccentColor"))) - } - .padding() - .background(Color("mode").opacity(0.05)) - .cornerRadius(8) - - - HStack{ - Image(systemName: "trash.fill") - .resizable() - .aspectRatio(contentMode: .fit) - .frame(width: 16, height: 16) - - VStack(alignment: .leading){ - Text("AppCleaner") - Text("Inspired by AppCleaner from Freemacsoft").font(.footnote).foregroundStyle(.gray) - - } - Spacer() - Button(""){ - NSWorkspace.shared.open(URL(string: "https://freemacsoft.net/appcleaner/")!) - } - .buttonStyle(SimpleButtonStyle(icon: "paperplane", help: "View", color: Color("AccentColor"))) + VStack(alignment: .center) { - } - .padding() - .background(Color("mode").opacity(0.05)) - .cornerRadius(8) - - -// HStack{ -// Image(systemName: "paintbrush.fill") -// .resizable() -// .aspectRatio(contentMode: .fit) -// .frame(width: 16, height: 16) -// VStack(alignment: .leading){ -// Text("Icon") -// Text("Created by Oviotti on DeviantArt").font(.footnote).foregroundStyle(.gray) -// } -// Spacer() -// -// Button("") { -// NSWorkspace.shared.open(URL(string: "https://www.deviantart.com/oviotti/art/AppCleaner-for-macOS-632260251")!) -// } -// .buttonStyle(SimpleButtonStyle(icon: "paperplane", help: "View", color: Color("AccentColor"))) -// -// } -// .padding() -// .background(Color("mode").opacity(0.05)) -// .cornerRadius(8) - - } - - Spacer() - + + + VStack(alignment: .center, spacing: 10) { + Image(nsImage: NSApp.applicationIconImage) + .padding(.top, 30) + Text(Bundle.main.name) + .font(.title) + .bold() + HStack { + Text("Version \(Bundle.main.version)") + Text("(Build \(Bundle.main.buildVersion))").font(.footnote) } - .padding(.trailing) -// .padding() -// .padding(.top, 30) + + + Divider() + .padding() + } - + + VStack(alignment: .leading) { + + HStack() { + Text("Credits and Inspiration").font(.title2) + Spacer() + } + .padding(.leading) + + HStack{ + Image(systemName: "paintbrush.pointed") + .resizable() + .scaledToFit() + .frame(width: 20, height: 20) + .padding(.trailing) + + VStack(alignment: .leading){ + Text("Microsoft Designer") + Text("Application icon resource") + .font(.callout) + .foregroundStyle(.gray) + + } + Spacer() + Button(""){ + NSWorkspace.shared.open(URL(string: "https://designer.microsoft.com/image-creator")!) + } + .buttonStyle(SimpleButtonStyle(icon: "link", help: "View", color: Color("mode"))) + + } + .padding(5) + .padding(.leading) + + + HStack{ + Image(systemName: "n.circle") + .resizable() + .scaledToFit() + .frame(width: 20, height: 20) + .padding(.trailing) + + VStack(alignment: .leading){ + Text("Namelix") + Text("Logo and branding generation") + .font(.callout) + .foregroundStyle(.gray) + + } + Spacer() + Button(""){ + NSWorkspace.shared.open(URL(string: "https://namelix.com/")!) + } + .buttonStyle(SimpleButtonStyle(icon: "link", help: "View", color: Color("mode"))) + + } + .padding(5) + .padding(.leading) + + + HStack{ + Image(systemName: "applescript") + .resizable() + .scaledToFit() + .frame(width: 20, height: 20) + .padding(.trailing) + + VStack(alignment: .leading){ + Text("Privacy Guides") + Text("Inspired by open-source appcleaner script from Sun Knudsen") + .font(.callout) + .foregroundStyle(.gray) + .lineLimit(2) + + } + Spacer() + + Button("") { + NSWorkspace.shared.open(URL(string: "https://sunknudsen.com/privacy-guides/how-to-clean-uninstall-macos-apps-using-appcleaner-open-source-alternative")!) + } + .buttonStyle(SimpleButtonStyle(icon: "link", help: "View", color: Color("mode"))) + + } + .padding(5) + .padding(.leading) + + + HStack{ + Image(systemName: "trash") + .resizable() + .scaledToFit() + .frame(width: 20, height: 20) + .padding(.trailing) + + VStack(alignment: .leading){ + Text("AppCleaner") + Text("Inspired by AppCleaner from Freemacsoft") + .font(.callout) + .foregroundStyle(.gray) + + } + Spacer() + Button(""){ + NSWorkspace.shared.open(URL(string: "https://freemacsoft.net/appcleaner/")!) + } + .buttonStyle(SimpleButtonStyle(icon: "link", help: "View", color: Color("mode"))) + + } + .padding(5) + .padding(.leading) + + Spacer() + + } + Spacer() - + Text("Made with ❤️ by Alin Lupascu (dev@itsalin.com)").font(.footnote).padding(.bottom) } .padding(20) - .frame(width: 750, height: 325) - + .frame(width: 500, height: 650) + } } extension Bundle { - + var name: String { func string(for key: String) -> String? { object(forInfoDictionaryKey: key) as? String @@ -159,14 +168,14 @@ extension Bundle { ?? string(for: "CFBundleName") ?? "N/A" } - + var version: String { infoDictionary?["CFBundleShortVersionString"] as? String ?? "N/A" } - + var buildVersion: String { infoDictionary?["CFBundleVersion"] as? String ?? "N/A" } - + } diff --git a/Pearcleaner/Settings/General.swift b/Pearcleaner/Settings/General.swift index c2c3808..40a6d6b 100644 --- a/Pearcleaner/Settings/General.swift +++ b/Pearcleaner/Settings/General.swift @@ -18,6 +18,9 @@ struct GeneralSettingsTab: View { @AppStorage("settings.general.miniview") private var miniView: Bool = true @AppStorage("settings.general.sidebarWidth") private var sidebarWidth: Double = 280 @AppStorage("displayMode") var displayMode: DisplayMode = .system + @AppStorage("settings.sentinel.enable") private var sentinel: Bool = false + @State private var diskStatus: Bool = false + @State private var accessStatus: Bool = false @State private var selectedTheme = "Auto" private let themes = ["Auto", "Dark", "Light"] @Binding var showPopover: Bool @@ -25,11 +28,23 @@ struct GeneralSettingsTab: View { var body: some View { Form { VStack { - HStack { + + HStack() { + Text("Appearance").font(.title2) + Spacer() + } + .padding(.leading) + + HStack(spacing: 0) { + Image(systemName: glass ? "cube.transparent" : "cube.transparent.fill") + .resizable() + .scaledToFit() + .frame(width: 20, height: 20) + .padding(.trailing) + .foregroundStyle(.gray) VStack(alignment: .leading, spacing: 5) { - Text("Transparency").font(.title2) - Text("Toggles transparent material") - .font(.footnote) + Text("\(glass ? "Transparent material enabled" : "Transparent material disabled")") + .font(.callout) .foregroundStyle(.gray) } Spacer() @@ -37,48 +52,55 @@ struct GeneralSettingsTab: View { }) .toggleStyle(.switch) } - .padding() - .background( - RoundedRectangle(cornerRadius: 8) - .fill(Color("mode").opacity(0.05)) - ) + .padding(5) + .padding(.leading) - HStack { - VStack(alignment: .leading, spacing: 5) { - Text("Sidebar").font(.title2) - Text("Adjust sidebar width") - .font(.footnote) - .foregroundStyle(.gray) - } + + HStack(spacing: 0) { + Image(systemName: "sidebar.left") + .resizable() + .scaledToFit() + .frame(width: 20, height: 20) + .padding(.trailing) + .foregroundStyle(.gray) + Text("Adjust sidebar width") + .font(.callout) + .foregroundStyle(.gray) Spacer() - Slider(value: $sidebarWidth, in: 200...400) { - Text("\(Int(sidebarWidth))") + Slider(value: $sidebarWidth, in: 200...360) { +// Text("\(Int(sidebarWidth))") } .padding(.horizontal) + .frame(width: 185) + Button("") { + sidebarWidth = 280 + } + .buttonStyle(SimpleButtonStyle(icon: "arrow.uturn.left.circle", help: "Reset to default size", color: Color("mode"))) } - .padding() - .background( - RoundedRectangle(cornerRadius: 8) - .fill(Color("mode").opacity(0.05)) - ) + .padding(5) + .padding(.leading) - HStack { + + HStack(spacing: 0) { + Image(systemName: displayMode.colorScheme == .dark ? "moon.fill" : "sun.max.fill") + .resizable() + .scaledToFit() + .frame(width: 20, height: 20) + .padding(.trailing) + .foregroundStyle(.gray) VStack(alignment: .leading, spacing: 5) { - Text("Appearance").font(.title2) - Text("Toggles color mode") - .font(.footnote) + Text("Set color mode") + .font(.callout) .foregroundStyle(.gray) } - Spacer() - Picker("", selection: $selectedTheme) { ForEach(themes, id: \.self) { theme in Text(theme) } } .pickerStyle(SegmentedPickerStyle()) -// .padding() + .frame(width: 200) .onChange(of: selectedTheme) { newTheme in switch newTheme { case "Auto": @@ -96,20 +118,33 @@ struct GeneralSettingsTab: View { break } } - } - .padding() - .background( - RoundedRectangle(cornerRadius: 8) - .fill(Color("mode").opacity(0.05)) - ) + .padding(5) + .padding(.leading) + + // ========================================================================================================= + + Divider() + .padding() - HStack { + + HStack() { + Text("Mini Configuration").font(.title2) + Spacer() + } + .padding(.leading) + + HStack(spacing: 0) { + Image(systemName: mini ? "square.resize.up" : "square.resize.down") + .resizable() + .scaledToFit() + .frame(width: 20, height: 20) + .padding(.trailing) + .foregroundStyle(.gray) VStack(alignment: .leading, spacing: 5) { - Text("Mini").font(.title2) - Text("Toggles a smaller, unified view with hidden app list") - .font(.footnote) + Text("\(mini ? "Mini window mode" : "Full size window mode")") + .font(.callout) .foregroundStyle(.gray) } Spacer() @@ -131,18 +166,20 @@ struct GeneralSettingsTab: View { } } } - .padding() - .background( - RoundedRectangle(cornerRadius: 8) - .fill(Color("mode").opacity(0.05)) - ) + .padding(5) + .padding(.leading) - HStack { + HStack(spacing: 0) { + Image(systemName: miniView ? "square.grid.3x3.square" : "plus.square.dashed") + .resizable() + .scaledToFit() + .frame(width: 20, height: 20) + .padding(.trailing) + .foregroundStyle(.gray) VStack(alignment: .leading, spacing: 5) { - Text("Mini - \(miniView ? "Apps List" : "Drop Target")").font(.title2) - Text("Toggles drop target or apps list view on launch") - .font(.footnote) + Text("\(miniView ? "Show apps list on startup" : "Show drop target on startup")") + .font(.callout) .foregroundStyle(.gray) } Spacer() @@ -153,17 +190,20 @@ struct GeneralSettingsTab: View { appState.currentView = newVal ? .apps : .empty } } - .padding() - .background( - RoundedRectangle(cornerRadius: 8) - .fill(Color("mode").opacity(0.05)) - ) + .padding(5) + .padding(.leading) - HStack { + + HStack(spacing: 0) { + Image(systemName: popoverStay ? "pin" : "pin.slash") + .resizable() + .scaledToFit() + .frame(width: 20, height: 20) + .padding(.trailing) + .foregroundStyle(.gray) VStack(alignment: .leading, spacing: 5) { - Text("Mini - \(popoverStay ? "Popover on Top" : "Popover not on Top")").font(.title2) - Text("Keeps file search popover on top in mini mode") - .font(.footnote) + Text("\(popoverStay ? "Popover window doesn't hide on outside click" : "Popover window hides on outside click")") + .font(.callout) .foregroundStyle(.gray) } Spacer() @@ -171,21 +211,130 @@ struct GeneralSettingsTab: View { }) .toggleStyle(.switch) } - .padding() - .background( - RoundedRectangle(cornerRadius: 8) - .fill(Color("mode").opacity(0.05)) - ) + .padding(5) + .padding(.leading) + + + // ========================================================================================================= + + + Divider() + .padding() + + + + + HStack() { + Text("Permissions").font(.title2) + Spacer() + } + .padding(.leading) + + HStack(spacing: 0) { + Image(systemName: diskStatus ? "externaldrive" : "externaldrive") + .resizable() + .scaledToFit() + .frame(width: 20, height: 20) + .padding(.trailing) + .foregroundStyle(diskStatus ? .green : .red) + .saturation(displayMode.colorScheme == .dark ? 0.5 : 1) + Text(diskStatus ? "Full Disk permission granted" : "Full Disk permission **NOT** granted") + .font(.callout) + .foregroundStyle(.gray) + Spacer() + + Button("") { + if let url = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_AllFiles") { + NSWorkspace.shared.open(url) + } + } + .buttonStyle(SimpleButtonStyle(icon: "folder", help: "View disk permissions pane", color: Color("mode"))) + + } + .padding(5) + .padding(.leading) + + + HStack(spacing: 0) { + Image(systemName: accessStatus ? "accessibility" : "accessibility") + .resizable() + .scaledToFit() + .frame(width: 20, height: 20) + .padding(.trailing) + .foregroundStyle(accessStatus ? .green : .red) + .saturation(displayMode.colorScheme == .dark ? 0.5 : 1) + Text(accessStatus ? "Accessibility permission granted" : "Accessibility permission **NOT** granted") + .font(.callout) + .foregroundStyle(.gray) + Spacer() + + Button("") { + if let url = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility") { + NSWorkspace.shared.open(url) + } + } + .buttonStyle(SimpleButtonStyle(icon: "folder", help: "View accessibility permissions pane", color: Color("mode"))) + + } + .padding(5) + .padding(.leading) + + + // ========================================================================================================= + + Divider() + .padding() + + HStack() { + Text("Sentinel Monitor").font(.title2) + Spacer() + } + .padding(.leading) + + HStack(spacing: 0) { + Image(systemName: sentinel ? "eye.circle" : "eye.slash.circle") + .resizable() + .scaledToFit() + .frame(width: 20, height: 20) + .padding(.trailing) + .foregroundStyle(sentinel ? .green : .red) + .saturation(displayMode.colorScheme == .dark ? 0.5 : 1) + Text(sentinel ? "Detecting when apps are moved to Trash" : "**NOT** detecting when apps are moved to Trash") + .font(.callout) + .foregroundStyle(.gray) + Spacer() + + Toggle(isOn: $sentinel, label: { + }) + .toggleStyle(.switch) + .onChange(of: sentinel) { newValue in + if newValue { + launchctl(load: true) + } else { + launchctl(load: false) + } + } + + } + .padding(5) + .padding(.leading) + + + Spacer() } + .onAppear { + diskStatus = checkAndRequestFullDiskAccess(appState: appState, skipAlert: true) + accessStatus = checkAndRequestAccessibilityAccess(appState: appState) + } } .padding(20) - .frame(width: 400, height: 500) + .frame(width: 500, height: 650) } diff --git a/Pearcleaner/Settings/Permissions.swift b/Pearcleaner/Settings/Permissions.swift index 1272121..3dd96a0 100644 --- a/Pearcleaner/Settings/Permissions.swift +++ b/Pearcleaner/Settings/Permissions.swift @@ -18,63 +18,109 @@ struct PermissionsSettingsTab: View { var body: some View { Form { VStack(alignment: .leading, spacing: 10) { - - HStack(spacing: 15) { - Image(systemName: "internaldrive") + + HStack(spacing: 0) { + Image(systemName: diskStatus ? "externaldrive" : "externaldrive") .resizable() .scaledToFit() - .frame(width: 20) - - VStack(alignment: .leading, spacing: 5) { - Text("Full Disk") - Text(diskStatus ? "Permission granted" : "Permission not granted") - .font(.footnote) - .foregroundStyle(diskStatus ? .green : .red) - } - + .frame(width: 20, height: 20) + .padding(.trailing) + .foregroundStyle(diskStatus ? .green : .red) + Text(diskStatus ? "Full Disk permission granted" : "Full Disk permission not granted") + .font(.callout) + .foregroundStyle(.gray) Spacer() - + Button("") { if let url = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_AllFiles") { NSWorkspace.shared.open(url) } } - .buttonStyle(SimpleButtonStyle(icon: "paperplane", help: "View disk permission pane", color: Color("AccentColor"))) + .buttonStyle(SimpleButtonStyle(icon: "gear", help: "View disk permissions pane", color: Color("mode"))) + } - .padding() - .background( - RoundedRectangle(cornerRadius: 8) - .fill(Color("mode").opacity(0.05)) - ) - - - HStack(spacing: 15) { - Image(systemName: "accessibility") + .padding(5) + + + HStack(spacing: 0) { + Image(systemName: accessStatus ? "accessibility" : "accessibility") .resizable() .scaledToFit() - .frame(width: 20) - - VStack(alignment: .leading, spacing: 5) { - Text("Accessibility") - Text(accessStatus ? "Permission granted" : "Permission not granted") - .font(.footnote) - .foregroundStyle(accessStatus ? .green : .red) - } - + .frame(width: 20, height: 20) + .padding(.trailing) + .foregroundStyle(accessStatus ? .green : .red) + Text(accessStatus ? "Accessibility permission granted" : "Accessibility permission not granted") + .font(.callout) + .foregroundStyle(.gray) Spacer() - + Button("") { if let url = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility") { NSWorkspace.shared.open(url) } } - .buttonStyle(SimpleButtonStyle(icon: "paperplane", help: "View accessibility pane", color: Color("AccentColor"))) + .buttonStyle(SimpleButtonStyle(icon: "gear", help: "View accessibility permissions pane", color: Color("mode"))) + } - .padding() - .background( - RoundedRectangle(cornerRadius: 8) - .fill(Color("mode").opacity(0.05)) - ) + .padding(5) + + +// HStack(spacing: 15) { +// Image(systemName: "internaldrive") +// .resizable() +// .scaledToFit() +// .frame(width: 20) +// +// VStack(alignment: .leading, spacing: 5) { +// Text("Full Disk") +// Text(diskStatus ? "Permission granted" : "Permission not granted") +// .font(.footnote) +// .foregroundStyle(diskStatus ? .green : .red) +// } +// +// Spacer() +// +// Button("") { +// if let url = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_AllFiles") { +// NSWorkspace.shared.open(url) +// } +// } +// .buttonStyle(SimpleButtonStyle(icon: "paperplane", help: "View disk permission pane", color: Color("AccentColor"))) +// } +// .padding() +// .background( +// RoundedRectangle(cornerRadius: 8) +// .fill(Color("mode").opacity(0.05)) +// ) + + +// HStack(spacing: 15) { +// Image(systemName: "accessibility") +// .resizable() +// .scaledToFit() +// .frame(width: 20) +// +// VStack(alignment: .leading, spacing: 5) { +// Text("Accessibility") +// Text(accessStatus ? "Permission granted" : "Permission not granted") +// .font(.footnote) +// .foregroundStyle(accessStatus ? .green : .red) +// } +// +// Spacer() +// +// Button("") { +// if let url = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility") { +// NSWorkspace.shared.open(url) +// } +// } +// .buttonStyle(SimpleButtonStyle(icon: "paperplane", help: "View accessibility pane", color: Color("AccentColor"))) +// } +// .padding() +// .background( +// RoundedRectangle(cornerRadius: 8) +// .fill(Color("mode").opacity(0.05)) +// ) diff --git a/Pearcleaner/Settings/SettingsWindow.swift b/Pearcleaner/Settings/SettingsWindow.swift index 3bdec53..5d69537 100644 --- a/Pearcleaner/Settings/SettingsWindow.swift +++ b/Pearcleaner/Settings/SettingsWindow.swift @@ -20,21 +20,21 @@ struct SettingsView: View { } .tag(CurrentTabView.general) - PermissionsSettingsTab() - .tabItem { - Label(CurrentTabView.permissions.title, systemImage: "lock") - } - .tag(CurrentTabView.permissions) +// PermissionsSettingsTab() +// .tabItem { +// Label(CurrentTabView.permissions.title, systemImage: "lock") +// } +// .tag(CurrentTabView.permissions) - SentinelSettingsTab() - .tabItem { - Label(CurrentTabView.sentinel.title, systemImage: "eye.circle") - } - .tag(CurrentTabView.sentinel) +// SentinelSettingsTab() +// .tabItem { +// Label(CurrentTabView.sentinel.title, systemImage: "eye.circle") +// } +// .tag(CurrentTabView.sentinel) UpdateSettingsTab() .tabItem { - Label(CurrentTabView.update.title, systemImage: "tray.and.arrow.down") + Label(CurrentTabView.update.title, systemImage: "cloud") } .tag(CurrentTabView.update) diff --git a/Pearcleaner/Settings/Update.swift b/Pearcleaner/Settings/Update.swift index cc60274..d792687 100644 --- a/Pearcleaner/Settings/Update.swift +++ b/Pearcleaner/Settings/Update.swift @@ -63,24 +63,31 @@ struct UpdateSettingsTab: View { .frame(minWidth: 0, maxWidth: .infinity) .padding() - Text("Showing last 3").opacity(0.5).font(.footnote) + Text("Showing last 3 releases") + .font(.callout) + .foregroundStyle(.gray) + - - HStack(alignment: .center, spacing: 5) { + HStack(alignment: .center, spacing: 20) { Spacer() - Button("Check"){ + Button("Update Notes"){ loadGithubReleases(appState: appState) - }.buttonStyle(BorderedButtonStyle()) - + } + .buttonStyle(SimpleButtonStyle(icon: "list.bullet", help: "Check release notes", color: Color("mode"))) + + Button("Force Update"){ loadGithubReleases(appState: appState, manual: true) - }.buttonStyle(BorderedButtonStyle()) - + } + .buttonStyle(SimpleButtonStyle(icon: "arrow.down.square", help: "Check for updates", color: Color("mode"))) + + Button("GitHub"){ NSWorkspace.shared.open(URL(string: "https://github.com/alienator88/Pearcleaner/releases")!) - }.buttonStyle(BorderedButtonStyle()) - + } + .buttonStyle(SimpleButtonStyle(icon: "link", help: "View releases on GitHub", color: Color("mode"))) + Spacer() } @@ -90,7 +97,7 @@ struct UpdateSettingsTab: View { } .padding(20) - .frame(width: 500, height: 400) + .frame(width: 500, height: 650) } } diff --git a/Pearcleaner/Views/AppListView.swift b/Pearcleaner/Views/AppListView.swift index a150824..586e032 100644 --- a/Pearcleaner/Views/AppListView.swift +++ b/Pearcleaner/Views/AppListView.swift @@ -56,25 +56,9 @@ struct AppListView: View { VStack(alignment: .center, spacing: 20) { HStack { SearchBarMiniBottom(search: $search) -// 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) .padding(.bottom) @@ -120,7 +104,7 @@ struct AppListView: View { } - Divider() + Divider().foregroundStyle(.red) } } .background(glass ? GlassEffect(material: .sidebar, blendingMode: .behindWindow).edgesIgnoringSafeArea(.all) : nil) @@ -145,36 +129,12 @@ struct AppListView: View { .id(appState.appInfo.id) } } -// .padding(.leading, appState.sidebar ? 0 : 10) .transition(.move(edge: .leading)) Spacer() } - .frame(minWidth: 700, minHeight: 500) + .frame(minWidth: 900, minHeight: 600) .edgesIgnoringSafeArea(.all) -// .onOpenURL(perform: { url in -// let deeplinkManager = DeeplinkManager() -// deeplinkManager.manage(url: url, appState: appState) -// }) -// .onDrop(of: ["public.file-url"], isTargeted: nil) { providers, _ in -// for provider in providers { -// provider.loadItem(forTypeIdentifier: "public.file-url") { data, error in -// if let data = data as? Data, let url = URL(dataRepresentation: data, relativeTo: nil) { -// let deeplinkManager = DeeplinkManager() -// deeplinkManager.manage(url: url, appState: appState) -// // // Check if the file URL has a ".app" extension -// // if url.pathExtension.lowercased() == "app" { -// // // Handle the dropped file URL here -// // printOS("Dropped .app file URL: \(url)") -// // } else { -// // // Print a message for non-.app files -// // printOS("Unsupported file type. Only .app files are accepted.") -// // } -// } -// } -// } -// return true -// } // MARK: Background for whole app // .background(Color("bg").opacity(1)) // .background(VisualEffect(material: .sidebar, blendingMode: .behindWindow).edgesIgnoringSafeArea(.all)) @@ -194,30 +154,15 @@ struct AppDetailsEmptyView: View { @Binding var showPopover: Bool var body: some View { - VStack() { - - Spacer() - - DropTarget(appState: appState, locations: locations, showPopover: $showPopover) + VStack(alignment: .center) { 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") + PearDropView() + + Spacer() + + Text("Drop your app here or select one from the list") .font(.title3) .padding(.bottom, 25) .opacity(0.5) diff --git a/Pearcleaner/Views/FilesView.swift b/Pearcleaner/Views/FilesView.swift index c8e393b..0d3de5c 100644 --- a/Pearcleaner/Views/FilesView.swift +++ b/Pearcleaner/Views/FilesView.swift @@ -227,16 +227,12 @@ struct FilesView: View { if appFolderURL.path == "/Applications" || appFolderURL.path == "\(home)/Applications" { // Do nothing, skip insertion - } else if appFolderURL.pathComponents.count > 2 { + } else if appFolderURL.pathComponents.count > 2 && appFolderURL.path.contains("Applications") { // Insert into selectedItemsArray only if there is an intermediary folder selectedItemsArray.insert(appFolderURL, at: 0) } } - // Save trashed files for undo operation -// updateOnMain { -// appState.trashedFiles = selectedItemsArray -// } killApp(appId: appState.appInfo.bundleIdentifier) { moveFilesToTrash(at: selectedItemsArray) { diff --git a/Pearcleaner/Views/MiniMode.swift b/Pearcleaner/Views/MiniMode.swift index ffa2161..d4f186c 100644 --- a/Pearcleaner/Views/MiniMode.swift +++ b/Pearcleaner/Views/MiniMode.swift @@ -28,13 +28,7 @@ struct MiniMode: View { if appState.currentView == .empty { TopBarMini(search: $search, showPopover: $showPopover) MiniEmptyView(showPopover: $showPopover) - } else if appState.currentView == .files { - TopBarMini(search: $search, showPopover: $showPopover) - MiniAppView(search: $search, showPopover: $showPopover) - } else if appState.currentView == .zombie { - TopBarMini(search: $search, showPopover: $showPopover) - MiniAppView(search: $search, showPopover: $showPopover) - } else if appState.currentView == .apps { + } else { TopBarMini(search: $search, showPopover: $showPopover) MiniAppView(search: $search, showPopover: $showPopover) } @@ -68,30 +62,6 @@ struct MiniMode: View { .frame(minWidth: 300, minHeight: 335) .edgesIgnoringSafeArea(.all) .background(glass ? GlassEffect(material: .sidebar, blendingMode: .behindWindow).edgesIgnoringSafeArea(.all) : nil) - -// .onOpenURL(perform: { url in -// let deeplinkManager = DeeplinkManager() -// deeplinkManager.manage(url: url, appState: appState) -// }) -// .onDrop(of: ["public.file-url"], isTargeted: nil) { providers, _ in -// for provider in providers { -// provider.loadItem(forTypeIdentifier: "public.file-url") { data, error in -// if let data = data as? Data, let url = URL(dataRepresentation: data, relativeTo: nil) { -// let deeplinkManager = DeeplinkManager() -// deeplinkManager.manage(url: url, appState: appState) -//// // Check if the file URL has a ".app" extension -//// if url.pathExtension.lowercased() == "app" { -//// // Handle the dropped file URL here -//// printOS("Dropped .app file URL: \(url)") -//// } else { -//// // Print a message for non-.app files -//// printOS("Unsupported file type. Only .app files are accepted.") -//// } -// } -// } -// } -// return true -// } // MARK: Background for whole app // .background(Color("bg").opacity(1)) // .background(VisualEffect(material: .sidebar, blendingMode: .behindWindow).edgesIgnoringSafeArea(.all)) @@ -116,16 +86,31 @@ struct MiniEmptyView: View { Spacer() - DropTarget(appState: appState, locations: locations, showPopover: $showPopover) - .frame(maxWidth: mini ? 300 : 500) + ZStack { + LinearGradient(gradient: Gradient(colors: [.pink, .orange]), startPoint: .leading, endPoint: .trailing) + .mask( + Image(systemName: "plus.square.dashed") + .resizable() + .scaledToFit() + .frame(width: 150, height: 150) + .padding() + ) + } + + - Text("Drop an app to begin") +// DropTarget(appState: appState, locations: locations, showPopover: $showPopover) +// .frame(maxWidth: mini ? 300 : 500) + + Text("Drop your app here") .font(.title3) .padding(.bottom, 25) .opacity(0.5) + Spacer() + if appState.isReminderVisible { Text("CMD + Z to undo") .font(.title2) @@ -142,7 +127,9 @@ struct MiniEmptyView: View { } Spacer() } - + + Spacer() + } // .padding() diff --git a/Pearcleaner/Views/TopBar.swift b/Pearcleaner/Views/TopBar.swift index e92d737..afb533f 100644 --- a/Pearcleaner/Views/TopBar.swift +++ b/Pearcleaner/Views/TopBar.swift @@ -19,7 +19,7 @@ struct TopBar: View { @EnvironmentObject var locations: Locations var body: some View { - HStack(alignment: .center, spacing: 10) { + HStack(alignment: .center, spacing: 0) { Spacer() @@ -39,55 +39,49 @@ struct TopBar: View { Spacer() - if appState.currentView != .empty {//|| appState.currentView != .apps { - Button("") { - withAnimation(.easeInOut(duration: 0.5)) { - appState.currentView = .empty - appState.appInfo = AppInfo.empty - } - } - .buttonStyle(SimpleButtonStyle(icon: "plus.square.dashed", help: "Drop Target", color: Color("mode"))) - - } + HStack() { + Spacer() - if appState.currentView != .zombie { - Button("") { - withAnimation(.easeInOut(duration: 0.5)) { - updateOnMain { - if appState.zombieFile.fileSize.keys.count == 0 { - appState.currentView = .zombie - appState.showProgress.toggle() - showPopover.toggle() - reversePathsSearch(appState: appState, locations: locations) - } else { - appState.currentView = .zombie - showPopover.toggle() + if appState.currentView != .zombie { + Button("") { + withAnimation(.easeInOut(duration: 0.5)) { + updateOnMain { + if appState.zombieFile.fileSize.keys.count == 0 { + appState.currentView = .zombie + appState.showProgress.toggle() + showPopover.toggle() + reversePathsSearch(appState: appState, locations: locations) + } else { + appState.currentView = .zombie + showPopover.toggle() + } } - } + } } + .buttonStyle(SimpleButtonStyle(icon: "clock.arrow.circlepath", help: "Leftover Files", color: Color("mode"))) } - .buttonStyle(SimpleButtonStyle(icon: "clock.arrow.circlepath", help: "Leftover Files", color: Color("mode"))) + + + // if appState.currentView != .empty || appState.currentView != .apps { + if appState.currentView == .files || appState.currentView == .zombie { + Button("") { + withAnimation(.easeInOut(duration: 0.5)) { + appState.currentView = .empty + appState.appInfo = AppInfo.empty + } + } + .buttonStyle(SimpleButtonStyle(icon: "plus.square.dashed", help: "Drop Target", color: Color("mode"))) + + } + + } - - -// Spacer() - - - -// if sentinel { -// Button("") { -// // -// } -// .buttonStyle(SimpleButtonStyle(icon: "lock.shield", help: "Sentinel enabled", color: .green, shield: true)) -// } - - - + } - .padding(.horizontal, 5) - .padding(.top, 10) + .padding(.horizontal, 10) + .padding(.top, 15) } } diff --git a/Pearcleaner/Views/TopBarMini.swift b/Pearcleaner/Views/TopBarMini.swift index 67fb7a6..e9c174e 100644 --- a/Pearcleaner/Views/TopBarMini.swift +++ b/Pearcleaner/Views/TopBarMini.swift @@ -18,74 +18,15 @@ struct TopBarMini: View { @EnvironmentObject var locations: Locations var body: some View { - HStack(alignment: .center, spacing: 5) { + HStack(alignment: .center, spacing: 0) { Spacer() -// if appState.currentView == .apps { -// Button("") { -// withAnimation(.easeInOut(duration: 0.5)) { -// // updateOnMain { -// appState.currentView = .empty -// appState.appInfo = AppInfo.empty -// showPopover = false -// // } -// } -// } -// .buttonStyle(SimpleButtonStyle(icon: "arrow.backward.square", help: "Back to Drop Zone", color: Color("mode"))) -// } else if appState.currentView == .empty { - Button("") { - withAnimation(.easeInOut(duration: 0.5)) { - // updateOnMain { - appState.currentView = .apps - // } - } - } - .buttonStyle(SimpleButtonStyle(icon: "list.dash", help: "Apps List", color: Color("mode"))) - } -// else if appState.currentView == .files { -// Button("") { -// withAnimation(.easeInOut(duration: 0.5)) { -// // updateOnMain { -// appState.currentView = .empty -// appState.appInfo = AppInfo.empty -// // } -// -// } -// } -// .buttonStyle(SimpleButtonStyle(icon: "plus.square.dashed", help: "Drop Target", color: Color("mode"))) -// Button("") { -// withAnimation(.easeInOut(duration: 0.5)) { -// // updateOnMain { -// appState.currentView = .apps -// // } -// } -// } -// .buttonStyle(SimpleButtonStyle(icon: "list.dash", help: "Apps List", color: Color("mode"))) -// } - if appState.currentView != .empty { HStack { Spacer() -// SearchBarMini(search: $search) -// .frame(width: 150) -// .offset(x: 20) -// .padding(.horizontal, 30) -// .padding(.top, 5) - - Button("") { - withAnimation(.easeInOut(duration: 0.5)) { - // updateOnMain { - appState.currentView = .empty - appState.appInfo = AppInfo.empty - showPopover = false - // } - } - } - .buttonStyle(SimpleButtonStyle(icon: "plus.square.dashed", help: "Drop Target", color: Color("mode"))) - Button("") { withAnimation(.easeInOut(duration: 0.5)) { showPopover = false @@ -105,6 +46,49 @@ struct TopBarMini: View { } .buttonStyle(SimpleButtonStyle(icon: "clock.arrow.circlepath", help: "Leftover Files", color: Color("mode"))) + Button("") { + withAnimation(.easeInOut(duration: 0.5)) { + appState.currentView = .apps + } + } + .buttonStyle(SimpleButtonStyle(icon: "square.grid.3x3.square", help: "Apps List", color: Color("mode"))) + + + } + + } + + if appState.currentView != .empty { + HStack { + Spacer() + + Button("") { + withAnimation(.easeInOut(duration: 0.5)) { + showPopover = false + updateOnMain { + if appState.zombieFile.fileSize.keys.count == 0 { + appState.currentView = .zombie + appState.showProgress.toggle() + showPopover.toggle() + reversePathsSearch(appState: appState, locations: locations) + } else { + appState.currentView = .zombie + showPopover.toggle() + } + } + + } + } + .buttonStyle(SimpleButtonStyle(icon: "clock.arrow.circlepath", help: "Leftover Files", color: Color("mode"))) + + Button("") { + withAnimation(.easeInOut(duration: 0.5)) { + appState.currentView = .empty + appState.appInfo = AppInfo.empty + showPopover = false + } + } + .buttonStyle(SimpleButtonStyle(icon: "plus.square.dashed", help: "Drop Target", color: Color("mode"))) } }