mirror of
https://github.com/exituser/Pearcleaner.git
synced 2026-09-17 03:48:55 +00:00
Restructure
This commit is contained in:
@@ -19,7 +19,7 @@ class AppState: ObservableObject {
|
||||
@Published var sortedApps: [AppInfo] = []
|
||||
@Published var selectedItems = Set<URL>()
|
||||
@Published var currentView = CurrentDetailsView.empty
|
||||
@Published var currentPage = CurrentPage.installed
|
||||
@Published var currentPage = CurrentPage.applications
|
||||
@Published var showAlert: Bool = false
|
||||
@Published var sidebar: Bool = true
|
||||
@Published var reload: Bool = false
|
||||
@@ -193,15 +193,17 @@ enum Arch {
|
||||
case empty
|
||||
}
|
||||
|
||||
enum CurrentPage:Int
|
||||
enum CurrentPage:Int, CaseIterable, Identifiable
|
||||
{
|
||||
case installed
|
||||
case uninstalled
|
||||
case applications
|
||||
case orphans
|
||||
|
||||
var id: Int { rawValue }
|
||||
|
||||
var title: String {
|
||||
switch self {
|
||||
case .installed: return "Installed"
|
||||
case .uninstalled: return "Uninstalled"
|
||||
case .applications: return "Applications"
|
||||
case .orphans: return "Orphaned Files"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ func reversePreloader(allApps: [AppInfo], appState: AppState, locations: Locatio
|
||||
@AppStorage("settings.interface.animationEnabled") var animationEnabled: Bool = true
|
||||
|
||||
updateOnMain {
|
||||
appState.leftoverProgress.0 = "Finding leftover files, please wait..."
|
||||
appState.leftoverProgress.0 = "Finding orphaned files, please wait..."
|
||||
}
|
||||
ReversePathsSearcher(appState: appState, locations: locations, fsm: fsm, sortedApps: allApps).reversePathsSearch {
|
||||
updateOnMain {
|
||||
|
||||
@@ -91,14 +91,14 @@ func processCLI(arguments: [String], appState: AppState, locations: Locations, f
|
||||
|
||||
}
|
||||
|
||||
// Private function to list leftover files for uninstall, using the provided path
|
||||
// Private function to list orphaned files for uninstall, using the provided path
|
||||
func listLeftoverFiles() {
|
||||
print("[BETA] Pearcleaner CLI | List Leftover Files:\n")
|
||||
print("[BETA] Pearcleaner CLI | List Orphaned Files:\n")
|
||||
|
||||
// Get installed apps for filtering
|
||||
let sortedApps = getSortedApps(paths: fsm.folderPaths)
|
||||
|
||||
// Find leftover files
|
||||
// Find orphaned files
|
||||
let foundPaths = ReversePathsSearcher(locations: locations, fsm: fsm, sortedApps: sortedApps)
|
||||
.reversePathsSearchCLI()
|
||||
|
||||
@@ -106,7 +106,7 @@ func processCLI(arguments: [String], appState: AppState, locations: Locations, f
|
||||
for path in foundPaths {
|
||||
print(path.path)
|
||||
}
|
||||
print("\nFound \(foundPaths.count) leftover files.\n")
|
||||
print("\nFound \(foundPaths.count) orphaned files.\n")
|
||||
}
|
||||
|
||||
// Private function to uninstall the application bundle at a given path
|
||||
@@ -163,23 +163,23 @@ func processCLI(arguments: [String], appState: AppState, locations: Locations, f
|
||||
}
|
||||
}
|
||||
|
||||
// Private function to remove the leftover files
|
||||
// Private function to remove the orphaned files
|
||||
func removeLeftoverFiles() {
|
||||
print("[BETA] Pearcleaner CLI | Remove Leftover Files:\n")
|
||||
print("[BETA] Pearcleaner CLI | Remove Orphaned Files:\n")
|
||||
|
||||
// Get installed apps for filtering
|
||||
let sortedApps = getSortedApps(paths: fsm.folderPaths)
|
||||
|
||||
// Find leftover files
|
||||
// Find orphaned files
|
||||
let foundPaths = ReversePathsSearcher(locations: locations, fsm: fsm, sortedApps: sortedApps)
|
||||
.reversePathsSearchCLI()
|
||||
|
||||
let success = moveFilesToTrashCLI(at: foundPaths)
|
||||
if success {
|
||||
print("Leftover files have been moved to the trash successfully.\n")
|
||||
print("Orphaned files have been moved to the trash successfully.\n")
|
||||
exit(0)
|
||||
} else {
|
||||
print("Failed to move leftover files to trash.\n")
|
||||
print("Failed to move orphaned files to trash.\n")
|
||||
exit(1)
|
||||
}
|
||||
}
|
||||
@@ -197,8 +197,8 @@ func processCLI(arguments: [String], appState: AppState, locations: Locations, f
|
||||
exit(0)
|
||||
}
|
||||
|
||||
// Handle --listlf or -lf option with a path argument for listing leftover files
|
||||
if options.contains("--list-leftover") || options.contains("-lf") {
|
||||
// Handle --listlf or -lf option with a path argument for listing orphaned files
|
||||
if options.contains("--list-orphaned") || options.contains("-lo") {
|
||||
listLeftoverFiles()
|
||||
exit(0)
|
||||
}
|
||||
@@ -217,8 +217,8 @@ func processCLI(arguments: [String], appState: AppState, locations: Locations, f
|
||||
exit(0)
|
||||
}
|
||||
|
||||
// Handle --uninstall-lf or -ulf option with a path argument for listing leftover files
|
||||
if options.contains("--remove-leftover") || options.contains("-rl") {
|
||||
// Handle --uninstall-lf or -ulf option with a path argument for listing orphaned files
|
||||
if options.contains("--remove-orphaned") || options.contains("-ro") {
|
||||
removeLeftoverFiles()
|
||||
exit(0)
|
||||
}
|
||||
@@ -235,10 +235,10 @@ func displayHelp() {
|
||||
[BETA] Pearcleaner CLI | Usage:
|
||||
|
||||
--list <path>, -l <path> List application files available for uninstall at the specified path
|
||||
--list-leftover, -lf List leftover files available for removal
|
||||
--list-orphaned, -lo List orphaned files available for removal
|
||||
--uninstall <path>, -u <path> Uninstall only the application bundle at the specified path
|
||||
--uninstall-all <path>, -ua <path> Uninstall application bundle and ALL related files at the specified path
|
||||
--remove-leftover, -rl Remove ALL leftover files (To ignore files, add them to the exception list within Pearcleaner settings)
|
||||
--remove-orphaned, -ro Remove ALL orphaned files (To ignore files, add them to the exception list within Pearcleaner settings)
|
||||
--help, -h Show this help message
|
||||
|
||||
""")
|
||||
|
||||
@@ -110,7 +110,7 @@ struct FolderSettingsTab: View {
|
||||
PearGroupBox(header: {
|
||||
HStack(spacing: 0) {
|
||||
Text("Exclude these files and folders from leftover search").font(.title2)
|
||||
InfoButton(text: "Add files or folders that will be ignored when searching for leftover files. Click a path to remove it from the list.")
|
||||
InfoButton(text: "Add files or folders that will be ignored when searching for orphaned files. Click a path to remove it from the list.")
|
||||
.padding(.leading, 5)
|
||||
Spacer()
|
||||
}
|
||||
@@ -287,7 +287,7 @@ class FolderSettingsManager: ObservableObject {
|
||||
|
||||
|
||||
|
||||
// Leftover files //////////////////////////////////////////////////////////////////////////////////
|
||||
// Orphaned files //////////////////////////////////////////////////////////////////////////////////
|
||||
func addPathZ(_ path: String) {
|
||||
let sanitizedPath = path.hasPrefix("/private") ? String(path.dropFirst(8)) : path
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ struct TipsSettingsTab: View {
|
||||
Text("6. On the Files view again, you can hit CMD + E to export a list of the found files or from the Tools menubar item")
|
||||
Text("7. CMD + U will check for updates manually")
|
||||
Text("8. CMD + R will refresh the app list. This can also be done from the refresh button in the search bar")
|
||||
Text("9. In the search bar menu button, you will also find Leftover Files which will find files leftover by previously uninstalled applications")
|
||||
Text("9. In the search bar menu button, you will also find Orphaned Files which will find files leftover by previously uninstalled applications")
|
||||
Text("10. You can enable a menubar icon from Settings")
|
||||
Text("11. You can enable mini mode version of the UI from Settings")
|
||||
Text("12. You can enable a Finder extension from Settings which allows you to uninstall apps by right clicking them in Finder")
|
||||
|
||||
@@ -88,7 +88,7 @@ struct AppSearchView: View {
|
||||
Button("More") {
|
||||
self.showMenu.toggle()
|
||||
}
|
||||
.buttonStyle(SimpleButtonStyle(icon: "ellipsis.circle", help: "More", size: 16, rotate: true))
|
||||
.buttonStyle(SimpleButtonStyle(icon: "ellipsis.circle", help: "More", size: 16, rotate: false))
|
||||
.popover(isPresented: $showMenu) {
|
||||
VStack(alignment: .leading) {
|
||||
|
||||
@@ -97,7 +97,7 @@ struct AppSearchView: View {
|
||||
selectedSortAlpha.toggle()
|
||||
}
|
||||
}
|
||||
.buttonStyle(SimpleButtonStyle(icon: "circle.fill", label: "Sorting: \(selectedSortAlpha ? "ABC" : "123")", help: "Can also click on User/System headers to toggle this", size: 5))
|
||||
.buttonStyle(SimpleButtonStyle(icon: "circle.fill", label: "Sorting: \(selectedSortAlpha ? "Name" : "Size")", help: "Sort app list alphabetically by name or by size", size: 5))
|
||||
|
||||
if mini && !menubarEnabled {
|
||||
Button("") {
|
||||
@@ -111,7 +111,7 @@ struct AppSearchView: View {
|
||||
}
|
||||
|
||||
|
||||
Button("Leftover Files") {
|
||||
Button("Orphaned Files") {
|
||||
showMenu = false
|
||||
withAnimation(Animation.easeInOut(duration: animationEnabled ? 0.35 : 0)) {
|
||||
showPopover = false
|
||||
@@ -127,7 +127,7 @@ struct AppSearchView: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
.buttonStyle(SimpleButtonStyle(icon: "circle.fill", label: "Leftover Files", help: "Leftover Files", size: 5))
|
||||
.buttonStyle(SimpleButtonStyle(icon: "circle.fill", label: "Orphaned Files", help: "Orphaned Files", size: 5))
|
||||
|
||||
|
||||
if #available(macOS 14.0, *) {
|
||||
@@ -155,6 +155,7 @@ struct AppSearchView: View {
|
||||
}
|
||||
.padding()
|
||||
.background(backgroundView(themeManager: themeManager, glass: glass).padding(-80))
|
||||
.frame(width: 150)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,6 @@ struct FilesView: View {
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
@Binding var showPopover: Bool
|
||||
@Binding var search: String
|
||||
// @State private var elapsedTime = 0
|
||||
// @State private var timer: Timer? = nil
|
||||
|
||||
var body: some View {
|
||||
|
||||
@@ -59,41 +57,18 @@ struct FilesView: View {
|
||||
ProgressView().controlSize(.small)
|
||||
}
|
||||
|
||||
// Text("Searching the file system").font(.title3)
|
||||
// .foregroundStyle((.primary.opacity(0.5)))
|
||||
//
|
||||
// ProgressView()
|
||||
// .progressViewStyle(.linear)
|
||||
// .frame(width: 400, height: 10)
|
||||
//
|
||||
// Text("\(elapsedTime)")
|
||||
// .font(.title).monospacedDigit()
|
||||
// .foregroundStyle((.primary.opacity(0.5)))
|
||||
// .opacity(elapsedTime == 0 ? 0 : 1)
|
||||
// .contentTransition(.numericText())
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.transition(.opacity)
|
||||
// .onAppear {
|
||||
// self.timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
|
||||
// withAnimation {
|
||||
// self.elapsedTime += 1
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// .onDisappear {
|
||||
// self.timer?.invalidate()
|
||||
// self.timer = nil
|
||||
// self.elapsedTime = 0
|
||||
// }
|
||||
} else {
|
||||
|
||||
// Titlebar
|
||||
HStack(spacing: 0) {
|
||||
|
||||
Spacer()
|
||||
|
||||
if mini || menubarEnabled {
|
||||
Button("Close") {
|
||||
updateOnMain {
|
||||
appState.appInfo = AppInfo.empty
|
||||
@@ -104,7 +79,10 @@ struct FilesView: View {
|
||||
}
|
||||
.buttonStyle(SimpleButtonStyle(icon: "x.circle", iconFlip: "x.circle.fill", help: "Close"))
|
||||
}
|
||||
.padding(.top, 6)
|
||||
|
||||
|
||||
}
|
||||
.padding(.top, (mini || menubarEnabled) ? 6 : 30)
|
||||
.padding(.trailing, (mini || menubarEnabled) ? 6 : 0)
|
||||
|
||||
VStack(spacing: 0) {
|
||||
|
||||
@@ -29,14 +29,9 @@ struct RegularMode: View {
|
||||
var body: some View {
|
||||
|
||||
// Main App Window
|
||||
VStack(spacing: 0) {
|
||||
ZStack() {
|
||||
|
||||
// Tab View
|
||||
CustomTabView(content: [
|
||||
(
|
||||
title: "Installed",
|
||||
icon: "externaldrive",
|
||||
view: AnyView (
|
||||
if appState.currentPage == .applications {
|
||||
HStack(alignment: .center, spacing: 0) {
|
||||
|
||||
// App List
|
||||
@@ -90,12 +85,8 @@ struct RegularMode: View {
|
||||
.zIndex(2)
|
||||
.background(backgroundView(themeManager: themeManager))
|
||||
}
|
||||
)
|
||||
),
|
||||
(
|
||||
title: "Uninstalled",
|
||||
icon: "externaldrive.badge.minus",
|
||||
view: AnyView(
|
||||
|
||||
} else if appState.currentPage == .orphans {
|
||||
ZombieView(showPopover: $showPopover, search: $search)
|
||||
.background(backgroundView(themeManager: themeManager))
|
||||
.onAppear {
|
||||
@@ -108,9 +99,31 @@ struct RegularMode: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
),
|
||||
])
|
||||
}
|
||||
|
||||
VStack(spacing: 0) {
|
||||
HStack {
|
||||
Spacer()
|
||||
Picker("", selection: $appState.currentPage) {
|
||||
ForEach(CurrentPage.allCases) { page in
|
||||
Text(page.title)
|
||||
.font(.title3)
|
||||
.tag(page)
|
||||
}
|
||||
}
|
||||
.buttonStyle(.borderless)
|
||||
.padding(2)
|
||||
.padding(.vertical, 2)
|
||||
.background {
|
||||
RoundedRectangle(cornerRadius: 8)
|
||||
.strokeBorder(.secondary.opacity(0.5), lineWidth: 1)
|
||||
}
|
||||
}
|
||||
.padding(6)
|
||||
|
||||
|
||||
Spacer()
|
||||
}
|
||||
|
||||
}
|
||||
.frame(minWidth: 900, minHeight: 600)
|
||||
|
||||
@@ -64,6 +64,7 @@ struct ZombieView: View {
|
||||
HStack(spacing: 0) {
|
||||
Spacer()
|
||||
|
||||
if mini || menubarEnabled {
|
||||
Button("Close") {
|
||||
updateOnMain {
|
||||
appState.appInfo = AppInfo.empty
|
||||
@@ -74,7 +75,8 @@ struct ZombieView: View {
|
||||
}
|
||||
.buttonStyle(SimpleButtonStyle(icon: "x.circle", iconFlip: "x.circle.fill", help: "Close"))
|
||||
}
|
||||
.padding(.top, 6)
|
||||
}
|
||||
.padding(.top, (mini || menubarEnabled) ? 6 : 30)
|
||||
.padding(.trailing, (mini || menubarEnabled) ? 6 : 0)
|
||||
|
||||
|
||||
@@ -94,7 +96,7 @@ struct ZombieView: View {
|
||||
|
||||
VStack(alignment: .leading, spacing: 10){
|
||||
HStack {
|
||||
Text("Leftover Files").font(.title).fontWeight(.bold)
|
||||
Text("Orphaned Files").font(.title).fontWeight(.bold)
|
||||
Spacer()
|
||||
}
|
||||
Text("Remaining files and folders from previous applications")
|
||||
|
||||
Reference in New Issue
Block a user