This commit is contained in:
Alin
2024-03-12 11:55:32 -06:00
parent f62148d08a
commit dc26407957
9 changed files with 58 additions and 22 deletions
+1 -1
View File
@@ -553,7 +553,7 @@ func reversePathsSearch(appState: AppState, locations: Locations, completion: @e
let dispatchGroup = DispatchGroup()
let allPaths = appState.appInfoStore.flatMap { $0.files.map { $0.path.pearFormat() } }
let allNames = appState.appInfoStore.map { $0.appName.pearFormat() }
let skipped = ["apple", "comapple", "temporary", "btserver", "proapps", "scripteditor", "ilife", "livefsd", "siritoday", "addressbook", "animoji", "appstore", "askpermission", "callhistory", "clouddocs", "diskimages", "dock", "facetime", "fileprovider", "instruments", "knowledge", "mobilesync", "syncservices", "homeenergyd", "icloud", "icdd", "networkserviceproxy", "familycircle", "geoservices", "installation", "passkit", "sharedimagecache", "desktop", "mbuseragent", "swiftpm", "baseband", "coresimulator", "photoslegacyupgrade", "photosupgrade", "siritts", "ipod", "globalpreferences", "apmanalytics", "apmexperiment", "avatarcache", "byhost", "contextstoreagent", "mobilemeaccounts", "intentbuilderc", "loginwindow", "momc", "replayd", "sharedfilelistd", "clang", "audiocomponent", "csexattrcryptoservice", "livetranscriptionagent", "sandobxhelper", "statuskitagent", "betaenrollmentd", "contentlinkingd", "diagnosticextensionsd", "gamed", "heard", "homed", "itunescloudd", "lldb", "mds", "mediaanalysisd", "metrickitd", "mobiletimerd", "proactived", "ptpcamerad", "studentd", "talagent", "watchlistd", "apptranslocation", "xcrun", "ds_store", "caches", "crashreporter", "trash"] // Skip system folders
let skipped = ["apple", "temporary", "btserver", "proapps", "scripteditor", "ilife", "livefsd", "siritoday", "addressbook", "animoji", "appstore", "askpermission", "callhistory", "clouddocs", "diskimages", "dock", "facetime", "fileprovider", "instruments", "knowledge", "mobilesync", "syncservices", "homeenergyd", "icloud", "icdd", "networkserviceproxy", "familycircle", "geoservices", "installation", "passkit", "sharedimagecache", "desktop", "mbuseragent", "swiftpm", "baseband", "coresimulator", "photoslegacyupgrade", "photosupgrade", "siritts", "ipod", "globalpreferences", "apmanalytics", "apmexperiment", "avatarcache", "byhost", "contextstoreagent", "mobilemeaccounts", "intentbuilderc", "loginwindow", "momc", "replayd", "sharedfilelistd", "clang", "audiocomponent", "csexattrcryptoservice", "livetranscriptionagent", "sandboxhelper", "statuskitagent", "betaenrollmentd", "contentlinkingd", "diagnosticextensionsd", "gamed", "heard", "homed", "itunescloudd", "lldb", "mds", "mediaanalysisd", "metrickitd", "mobiletimerd", "proactived", "ptpcamerad", "studentd", "talagent", "watchlistd", "apptranslocation", "xcrun", "ds_store", "caches", "crashreporter", "trash", "pearcleaner", "amsdatamigratortool", "arfilecache", "assistant", "chromium", "cloudkit", "webkit", "databases", "diagnostic", "cache", "gamekit", "homebrew", "logi", "microsoft", "mozilla", "sync", "google"] // Skip system folders
// Skip locations that might not exist
+15 -5
View File
@@ -75,16 +75,26 @@ struct InfoButton: View {
@State private var isPopoverPresented: Bool = false
let text: String
let color: Color?
let label: String?
var body: some View {
Button(action: {
self.isPopoverPresented.toggle()
}) {
Image(systemName: "info.circle.fill")
.resizable()
.scaledToFit()
.frame(width: 14, height: 14)
.foregroundColor(color?.opacity(0.7) ?? Color("mode").opacity(0.7))
HStack {
Image(systemName: "info.circle.fill")
.resizable()
.scaledToFit()
.frame(width: 14, height: 14)
.foregroundColor(color?.opacity(0.7) ?? Color("mode").opacity(0.7))
if !label!.isEmpty {
Text(label!)
.font(.callout)
.foregroundColor(color?.opacity(0.7) ?? Color("mode").opacity(0.7))
}
}
}
.buttonStyle(PlainButtonStyle())
.onHover { isHovered in
+1 -1
View File
@@ -329,7 +329,7 @@ extension Int {
// --- Extend String to remove periods, spaces and lowercase the string
extension String {
func pearFormat() -> String {
return self.replacingOccurrences(of: ".", with: "").replacingOccurrences(of: " ", with: "").lowercased()
return self.replacingOccurrences(of: ".", with: "").replacingOccurrences(of: " ", with: "").replacingOccurrences(of: "-", with: "").lowercased()
}
}
+1
View File
@@ -100,6 +100,7 @@ struct PearcleanerApp: App {
loadAllPaths(allApps: sortedApps, appState: appState, locations: locations)
}
#if !DEBUG
Task {
+4 -4
View File
@@ -72,7 +72,7 @@ struct GeneralSettingsTab: View {
.foregroundStyle(.gray)
}
InfoButton(text: "When instant search is enabled, all application files are gathered and cached for later use on startup instead of on each app click. There might be a slight delay of a few seconds when launching Pearcleaner depending on the amount of apps you have installed.", color: nil)
InfoButton(text: "When instant search is enabled, all application files are gathered and cached for later use on startup instead of on each app click. There might be a slight delay of a few seconds when launching Pearcleaner depending on the amount of apps you have installed.", color: nil, label: "")
Spacer()
Toggle(isOn: $instantSearch, label: {
@@ -96,7 +96,7 @@ struct GeneralSettingsTab: View {
.foregroundStyle(.gray)
}
InfoButton(text: "When homebrew cleanup is enabled, Pearcleaner will check if the app you are removing was installed via homebrew and execute a brew uninstall and brew cleanup command as well to let homebrew know that the app is removed. This way your homebrew list will be synced up correctly and caching will be removed.\n\nNOTE: If you undo the file delete with CMD+Z, the files will be put back but homebrew will not be aware of it. To get the homebrew list back in sync you'd need to run:\n brew install APPNAME --force", color: nil)
InfoButton(text: "When homebrew cleanup is enabled, Pearcleaner will check if the app you are removing was installed via homebrew and execute a brew uninstall and brew cleanup command as well to let homebrew know that the app is removed. This way your homebrew list will be synced up correctly and caching will be removed.\n\nNOTE: If you undo the file delete with CMD+Z, the files will be put back but homebrew will not be aware of it. To get the homebrew list back in sync you'd need to run:\n brew install APPNAME --force", color: nil, label: "")
Spacer()
Toggle(isOn: $brew, label: {
@@ -209,7 +209,7 @@ struct GeneralSettingsTab: View {
.foregroundStyle(.gray)
}
InfoButton(text: "In mini window mode, you can have Pearcleaner startup to the Apps List view or the Drop Target view.", color: nil)
InfoButton(text: "In mini window mode, you can have Pearcleaner startup to the Apps List view or the Drop Target view.", color: nil, label: "")
Spacer()
Toggle(isOn: $miniView, label: {
@@ -236,7 +236,7 @@ struct GeneralSettingsTab: View {
.foregroundStyle(.gray)
}
InfoButton(text: "In mini window mode, if you pin the Files popover on top, clicking away from the window will not dismiss it. Otherwise, it will dismiss by clicking anywhere outside the popover.", color: nil)
InfoButton(text: "In mini window mode, if you pin the Files popover on top, clicking away from the window will not dismiss it. Otherwise, it will dismiss by clicking anywhere outside the popover.", color: nil, label: "")
Spacer()
Toggle(isOn: $popoverStay, label: {
+1 -1
View File
@@ -77,7 +77,7 @@ struct FilesView: View {
Text("").foregroundStyle(Color("AccentColor"))
Text("\(appState.appInfo.appVersion)").font(.title3)
if appState.appInfo.appName.count < 5 {
InfoButton(text: "Pearcleaner searches for files via a combination of bundle id and app name. \(appState.appInfo.appName) has a common or short app name so there might be unrelated files found. Please check the list thoroughly before uninstalling.", color: nil)
InfoButton(text: "Pearcleaner searches for files via a combination of bundle id and app name. \(appState.appInfo.appName) has a common or short app name so there might be unrelated files found. Please check the list thoroughly before uninstalling.", color: nil, label: "")
}
}
+1
View File
@@ -46,6 +46,7 @@ struct TopBar: View {
Button("") {
withAnimation(.easeInOut(duration: 0.5)) {
updateOnMain {
appState.appInfo = .empty
if appState.zombieFile.fileSize.keys.count == 0 {
appState.currentView = .zombie
appState.showProgress.toggle()
+1
View File
@@ -71,6 +71,7 @@ struct TopBarMini: View {
withAnimation(.easeInOut(duration: 0.5)) {
showPopover = false
updateOnMain {
appState.appInfo = .empty
if appState.zombieFile.fileSize.keys.count == 0 {
appState.currentView = .zombie
appState.showProgress.toggle()
+33 -10
View File
@@ -18,9 +18,36 @@ struct ZombieView: View {
@Environment(\.colorScheme) var colorScheme
@Binding var showPopover: Bool
@Binding var search: String
@State private var searchZ: String = ""
@State private var selectedOption = "Default"
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)
}
let sortedFilteredFiles = filteredFiles.sorted(by: {
selectedOption == "Default" ?
$0.key.lastPathComponent < $1.key.lastPathComponent :
$0.value > $1.value
}).map { $0.key }
let totalSize = filteredFiles.values.reduce(0, +)
return (sortedFilteredFiles, totalSize)
}()
VStack(alignment: .center) {
if appState.showProgress {
VStack {
@@ -88,7 +115,7 @@ struct ZombieView: View {
VStack(alignment: .leading, spacing: 10){
HStack {
Text("Leftover Files").font(.title).fontWeight(.bold)
InfoButton(text: "Leftover file search is not 100% accurate as it doesn't have any app bundles to check against. This searches for files/folders and excludes the ones that have overlap with your currently installed apps. Make sure to confirm files marked for removal are correct.", color: .red)
InfoButton(text: "Leftover file search is not 100% accurate as it doesn't have any app bundles to check against. This searches for files/folders and excludes the ones that have overlap with your currently installed apps. Make sure to confirm files marked for removal are correct.", color: .red, label: "READ")
Spacer()
}
@@ -99,8 +126,8 @@ struct ZombieView: View {
Spacer()
VStack(alignment: .trailing, spacing: 5) {
Text("\(formatByte(size: appState.zombieFile.totalSize))").font(.title).fontWeight(.bold)
Text("\(appState.zombieFile.fileSize.count == 1 ? "\(appState.zombieFile.fileSize.count) item" : "\(appState.zombieFile.fileSize.count) items")").font(.callout).underline().foregroundStyle((.gray.opacity(0.8)))
Text("\(formatByte(size: filteredAndSortedFiles.1))").font(.title).fontWeight(.bold)
Text("\(filteredAndSortedFiles.0.count == 1 ? "\(filteredAndSortedFiles.0.count) item" : "\(filteredAndSortedFiles.0.count) items")").font(.callout).underline().foregroundStyle((.gray.opacity(0.8)))
}
}
@@ -110,19 +137,15 @@ struct ZombieView: View {
.padding(.top, 0)
}
SearchBarMiniBottom(search: $searchZ)
Divider()
.padding()
ScrollView() {
LazyVStack {
let sortedFilesSize = appState.zombieFile.fileSize.keys.sorted(by: { appState.zombieFile.fileSize[$0, default: 0] > appState.zombieFile.fileSize[$1, default: 0] })
let sortedFilesAlpha = appState.zombieFile.fileSize.keys.sorted(by: { $0.lastPathComponent < $1.lastPathComponent })
let sort = selectedOption == "Default" ? sortedFilesAlpha : sortedFilesSize
ForEach(sort, id: \.self) { file in
ForEach(filteredAndSortedFiles.0, id: \.self) { file in
if let fileSize = appState.zombieFile.fileSize[file], let fileIcon = appState.zombieFile.fileIcon[file] {
let iconImage = fileIcon.map(Image.init(nsImage:))