Restructure

This commit is contained in:
Alin
2024-10-04 13:15:16 -06:00
parent 512a325c4b
commit b4d676d8a4
9 changed files with 142 additions and 146 deletions
+8 -6
View File
@@ -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"
}
}
}
+1 -1
View File
@@ -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 {
+15 -15
View File
@@ -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
""")
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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")
+5 -4
View File
@@ -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)
}
}
+13 -35
View File
@@ -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,52 +57,32 @@ 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()
Button("Close") {
updateOnMain {
appState.appInfo = AppInfo.empty
search = ""
appState.currentView = .apps
showPopover = false
if mini || menubarEnabled {
Button("Close") {
updateOnMain {
appState.appInfo = AppInfo.empty
search = ""
appState.currentView = .apps
showPopover = false
}
}
.buttonStyle(SimpleButtonStyle(icon: "x.circle", iconFlip: "x.circle.fill", help: "Close"))
}
.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) {
+86 -73
View File
@@ -29,88 +29,101 @@ struct RegularMode: View {
var body: some View {
// Main App Window
VStack(spacing: 0) {
ZStack() {
// Tab View
CustomTabView(content: [
(
title: "Installed",
icon: "externaldrive",
view: AnyView (
HStack(alignment: .center, spacing: 0) {
if appState.currentPage == .applications {
HStack(alignment: .center, spacing: 0) {
// App List
HStack(spacing: 0){
// App List
HStack(spacing: 0){
if appState.reload {
VStack {
Spacer()
ProgressView() {
Text("Gathering app details")
.font(.callout)
.foregroundStyle(.primary.opacity(0.5))
.padding(5)
}
Spacer()
}
.frame(width: sidebarWidth)
.padding(.vertical)
} else {
AppSearchView(glass: glass, menubarEnabled: menubarEnabled, mini: mini, search: $search, showPopover: $showPopover, isMenuBar: $isMenuBar)
.frame(width: sidebarWidth)
}
}
.background(backgroundView(themeManager: themeManager, darker: true, glass: glass))
.transition(.opacity)
SlideableDivider(dimension: $sidebarWidth)
.background(backgroundView(themeManager: themeManager))
.zIndex(3)
// Details View
HStack(spacing: 0) {
if appState.reload {
VStack {
Spacer()
Group {
if appState.currentView == .empty || appState.currentView == .apps {
AppDetailsEmptyView(showPopover: $showPopover)
} else if appState.currentView == .files {
FilesView(showPopover: $showPopover, search: $search)
.id(appState.appInfo.id)
} else if appState.currentView == .zombie {
ZombieView(showPopover: $showPopover, search: $search)
.id(appState.appInfo.id)
}
ProgressView() {
Text("Gathering app details")
.font(.callout)
.foregroundStyle(.primary.opacity(0.5))
.padding(5)
}
.transition(.opacity)
Spacer()
}
.zIndex(2)
.background(backgroundView(themeManager: themeManager))
.frame(width: sidebarWidth)
.padding(.vertical)
} else {
AppSearchView(glass: glass, menubarEnabled: menubarEnabled, mini: mini, search: $search, showPopover: $showPopover, isMenuBar: $isMenuBar)
.frame(width: sidebarWidth)
}
)
),
(
title: "Uninstalled",
icon: "externaldrive.badge.minus",
view: AnyView(
ZombieView(showPopover: $showPopover, search: $search)
.background(backgroundView(themeManager: themeManager))
.onAppear {
if appState.zombieFile.fileSize.keys.isEmpty {
appState.showProgress.toggle()
}
withAnimation(Animation.easeInOut(duration: animationEnabled ? 0.35 : 0)) {
if appState.zombieFile.fileSize.keys.isEmpty {
reversePreloader(allApps: appState.sortedApps, appState: appState, locations: locations, fsm: fsm)
}
}
}
.background(backgroundView(themeManager: themeManager, darker: true, glass: glass))
.transition(.opacity)
SlideableDivider(dimension: $sidebarWidth)
.background(backgroundView(themeManager: themeManager))
.zIndex(3)
// Details View
HStack(spacing: 0) {
Spacer()
Group {
if appState.currentView == .empty || appState.currentView == .apps {
AppDetailsEmptyView(showPopover: $showPopover)
} else if appState.currentView == .files {
FilesView(showPopover: $showPopover, search: $search)
.id(appState.appInfo.id)
} else if appState.currentView == .zombie {
ZombieView(showPopover: $showPopover, search: $search)
.id(appState.appInfo.id)
}
)
),
])
}
.transition(.opacity)
Spacer()
}
.zIndex(2)
.background(backgroundView(themeManager: themeManager))
}
} else if appState.currentPage == .orphans {
ZombieView(showPopover: $showPopover, search: $search)
.background(backgroundView(themeManager: themeManager))
.onAppear {
if appState.zombieFile.fileSize.keys.isEmpty {
appState.showProgress.toggle()
}
withAnimation(Animation.easeInOut(duration: animationEnabled ? 0.35 : 0)) {
if appState.zombieFile.fileSize.keys.isEmpty {
reversePreloader(allApps: appState.sortedApps, appState: appState, locations: locations, fsm: fsm)
}
}
}
}
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)
+11 -9
View File
@@ -64,17 +64,19 @@ struct ZombieView: View {
HStack(spacing: 0) {
Spacer()
Button("Close") {
updateOnMain {
appState.appInfo = AppInfo.empty
search = ""
appState.currentView = .apps
showPopover = false
if mini || menubarEnabled {
Button("Close") {
updateOnMain {
appState.appInfo = AppInfo.empty
search = ""
appState.currentView = .apps
showPopover = false
}
}
.buttonStyle(SimpleButtonStyle(icon: "x.circle", iconFlip: "x.circle.fill", help: "Close"))
}
.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")