This commit is contained in:
Alin
2024-02-27 17:08:38 -07:00
parent 80a128a619
commit faa7ec9457
10 changed files with 177 additions and 140 deletions
+2 -9
View File
@@ -600,7 +600,7 @@ func reversePathsSearch(appState: AppState, locations: Locations, completion: @e
}
let sortedCollection = collection.sorted(by: { $0.absoluteString < $1.absoluteString })
// let sortedCollection = collection.sorted(by: { $0.absoluteString < $1.absoluteString })
// Calculate file details (sizes and icons)
var fileSize: [URL: Int64] = [:]
@@ -610,10 +610,8 @@ func reversePathsSearch(appState: AppState, locations: Locations, completion: @e
for path in collection {
var size: Int64
var icon: NSImage? = nil
// size = 0
size = totalSizeOnDisk(for: path)
icon = getIconForFileOrFolderNS(atPath: path)
// icon = nil
fileSize[path] = size
fileIcon[path] = icon
}
@@ -622,15 +620,10 @@ func reversePathsSearch(appState: AppState, locations: Locations, completion: @e
dispatchGroup.notify(queue: .main) {
updateOnMain {
// updatedZombieFile.files = sortedCollection
updatedZombieFile.fileSize = fileSize
updatedZombieFile.fileIcon = fileIcon
appState.selectedZombieItems = Set(sortedCollection)
// appState.selectedZombieItems = Set(sortedCollection)
appState.zombieFile = updatedZombieFile
// print(updatedZombieFile.fileSize.keys.count)
// print(updatedZombieFile)
appState.showProgress = false
}
+59
View File
@@ -50,6 +50,65 @@ struct SimpleButtonStyle: ButtonStyle {
}
struct NavButtonBottomBarStyle: ButtonStyle {
@State private var isHovered = false
var image: String
var help: String
func makeBody(configuration: Configuration) -> some View {
ZStack {
Image(systemName: image)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 20, height: 20)
.foregroundStyle(isHovered ? Color("mode").opacity(0.8) : Color("mode").opacity(0.5))
Rectangle()
.foregroundColor(.clear)
.frame(width: 36, height: 36)
.cornerRadius(6)
.contentShape(Rectangle())
}
.scaleEffect(configuration.isPressed ? 0.95 : 1)
.buttonStyle(.plain)
.onHover { inside in
isHovered = inside
}
.help(help)
}
}
struct WarningPopoverView: View {
var label: String
var bodyText: String
@Binding var isPresented: Bool
var body: some View {
HStack {
Image(systemName: "exclamationmark.triangle.fill")
.foregroundStyle(.red)
.popover(isPresented: $isPresented, arrowEdge: .top) {
VStack {
Text(bodyText)
.padding()
.font(.title2)
}
}
Text(label)
.foregroundStyle(Color.red)
Spacer()
}
.onTapGesture {
isPresented.toggle()
}
}
}
struct LabeledDivider: View {
let label: String
@EnvironmentObject var appState: AppState
+1 -1
View File
@@ -133,7 +133,7 @@ struct PearcleanerApp: App {
Settings {
SettingsView()
SettingsView(showPopover: $showPopover)
.environmentObject(appState)
.toolbarBackground(.clear)
.preferredColorScheme(displayMode.colorScheme)
+4 -3
View File
@@ -20,7 +20,8 @@ struct GeneralSettingsTab: View {
@AppStorage("displayMode") var displayMode: DisplayMode = .system
@State private var selectedTheme = "Auto"
private let themes = ["Auto", "Dark", "Light"]
@Binding var showPopover: Bool
var body: some View {
Form {
VStack {
@@ -117,9 +118,9 @@ struct GeneralSettingsTab: View {
.toggleStyle(.switch)
.onChange(of: mini) { newVal in
if mini {
appState.currentView = miniView ? .apps : .empty
showPopover = false
resizeWindowAuto(windowSettings: windowSettings)
// showPopover = false
// appState.currentView = miniView ? .apps : .empty
} else {
resizeWindowAuto(windowSettings: windowSettings)
if appState.appInfo.appName.isEmpty {
+3 -2
View File
@@ -9,11 +9,12 @@ import SwiftUI
struct SettingsView: View {
@EnvironmentObject var appState: AppState
@Binding var showPopover: Bool
var body: some View {
TabView() {
GeneralSettingsTab()
GeneralSettingsTab(showPopover: $showPopover)
.tabItem {
Label(CurrentTabView.general.title, systemImage: "gear")
}
+60 -85
View File
@@ -18,7 +18,6 @@ struct FilesView: View {
@Binding var showPopover: Bool
@Binding var search: String
@State private var selectedOption = "Default"
@State private var toggles: Bool = true
var body: some View {
VStack(alignment: .center) {
@@ -88,49 +87,35 @@ struct FilesView: View {
// .foregroundStyle(Color("AccentColor").opacity(0.7))
.underline()
}
if appState.appInfo.webApp {
HStack {
Text("web")
.font(.footnote)
.foregroundStyle(Color("mode").opacity(0.5))
.frame(minWidth: 30, minHeight: 15)
.padding(2)
.background(Color("mode").opacity(0.1))
.clipShape(.capsule)
Spacer()
}
}
if appState.appInfo.appName.count < 5 {
HStack(alignment: .center) {
Image(systemName: "exclamationmark.triangle.fill")
.foregroundStyle(.red)
.popover(isPresented: $showPop, arrowEdge: .top) {
VStack() {
Text("Pearcleaner searches for files via a combination of bundle id and app name.\n**\(appState.appInfo.appName)** has a common or short app name so there might be unrelated files found.\nPlease check the list thoroughly before uninstalling.")
.padding()
.font(.title2)
}
}
Text("Warning")
.foregroundStyle(Color.red)
Spacer()
HStack() {
if appState.appInfo.webApp {
HStack {
Text("web")
.font(.footnote)
.foregroundStyle(Color("mode").opacity(0.5))
.frame(minWidth: 30, minHeight: 15)
.padding(2)
.background(Color("mode").opacity(0.1))
.clipShape(.capsule)
Spacer()
}
}
.padding(.top)
.onTapGesture {
showPop = true
if appState.appInfo.appName.count < 5 {
WarningPopoverView(label: "Caution",
bodyText: "Pearcleaner searches for files via a combination of bundle id and app name.\n\(appState.appInfo.appName) has a common or short app name so there might be unrelated files found.\nPlease check the list thoroughly before uninstalling.",
isPresented: $showPop)
}
}
.padding(.vertical, 5)
}
.padding(20)
}
// .padding(.horizontal)
// .padding(.bottom)
.background(
RoundedRectangle(cornerRadius: 8)
// .strokeBorder(Color("AccentColor"), lineWidth: 0.5)
@@ -140,34 +125,15 @@ struct FilesView: View {
// .strokeBorder(Color("AccentColor").opacity(colorScheme == .dark ? 0.1 : 0.1), lineWidth: 1)
// )
)
HStack(alignment: .center) {
Spacer()
Text("\(toggles ? "Selected: All" : "Selected: None")").font(.subheadline)
Toggle("", isOn: $toggles)
.onChange(of: toggles) { value in
if value {
updateOnMain {
appState.selectedItems = Set(appState.appInfo.files)
}
} else {
updateOnMain {
appState.selectedItems.removeAll()
}
}
}
}
.padding(.top)
.padding(.bottom)
ScrollView() {
VStack {
let sortedFilesSize = appState.appInfo.files.sorted(by: { appState.appInfo.fileSize[$0, default: 0] > appState.appInfo.fileSize[$1, default: 0] })
// let sortedFilesAlpha = appState.appInfo.files.sorted(by: { $0.lastPathComponent < $1.lastPathComponent })
let sortedFilesAlpha = appState.appInfo.files
let sort = selectedOption == "Default" ? appState.appInfo.files : sortedFilesSize
let sort = selectedOption == "Default" ? sortedFilesAlpha : sortedFilesSize
ForEach(sort, id: \.self) { path in
if let fileSize = appState.appInfo.fileSize[path], let fileIcon = appState.appInfo.fileIcon[path] {
@@ -195,20 +161,35 @@ struct FilesView: View {
}
}
}
.padding()
}
.padding([.bottom])
// .background(
// RoundedRectangle(cornerRadius: 8)
// .fill(Color("mode").opacity(colorScheme == .dark ? 0.05 : 0.05))
// )
HStack() {
Picker(selection: $selectedOption, label: Text("Sort")) {
Text("Default").tag("Default")
Text("Size").tag("Size")
Picker("", selection: Binding(
get: { appState.selectedItems.count == appState.appInfo.files.count ? true : false },
set: { newValue in
updateOnMain {
appState.selectedItems = newValue ? Set(appState.appInfo.files) : []
}
}
)) {
Text("􀃲").tag(true)
Text("􀂒").tag(false)
}
.pickerStyle(SegmentedPickerStyle())
.frame(width: 150)
.frame(width: 100)
.offset(x: -8)
.help("Item Selection")
Spacer()
if mini {
Button("Close") {
updateOnMain {
appState.appInfo = AppInfo.empty
@@ -217,7 +198,8 @@ struct FilesView: View {
showPopover = false
}
}
// .buttonStyle(FilesViewActionButton(action: .close))
.buttonStyle(NavButtonBottomBarStyle(image: "x.circle.fill", help: "Close"))
}
@@ -274,15 +256,25 @@ struct FilesView: View {
}
}
.buttonStyle(NavButtonBottomBarStyle(image: "trash.fill", help: "Uninstall"))
.disabled(appState.selectedItems.isEmpty)
// .buttonStyle(FilesViewActionButton(action: .uninstall))
Spacer()
Picker("", selection: $selectedOption) {
Text("􀅐").tag("Default")
Text("􀆃").tag("Size")
}
.pickerStyle(SegmentedPickerStyle())
.frame(width: 100)
.help("Sorting Selection")
}
// .padding(.top)
.padding(.top)
}
.transition(.opacity)
.padding(20)
}
}
@@ -323,25 +315,8 @@ struct FileDetailsItem: View {
self.appState.selectedItems.remove(self.path)
}
}
// get: { self.appState.selectedItems.contains(self.path) },
// set: { isChecked in
// if isChecked {
// self.appState.selectedItems.insert(self.path)
// if self.path == appState.appInfo.path {
// self.appState.appInfo.fileSize.keys.forEach {
// self.appState.selectedItems.insert($0)
// }
// }
// } else {
// self.appState.selectedItems.remove(self.path)
// if self.path == appState.appInfo.path {
// self.appState.selectedItems.forEach {
// self.appState.selectedItems.remove($0)
// }
// }
// }
// }
))
.disabled(self.path.path.contains(".Trash"))
if let appIcon = icon {
+1 -1
View File
@@ -59,7 +59,7 @@ struct MiniMode: View {
.fill(Color("pop"))
.padding(-80)
)
.frame(width: 650, height: 500)
.frame(width: 650, height: 550)
}
+1 -1
View File
@@ -46,7 +46,7 @@ struct TopBar: View {
appState.appInfo = AppInfo.empty
}
}
.buttonStyle(SimpleButtonStyle(icon: "house", help: "Home", color: Color("mode")))
.buttonStyle(SimpleButtonStyle(icon: "plus.square.dashed", help: "Drop Target", color: Color("mode")))
}
+1
View File
@@ -88,6 +88,7 @@ struct TopBarMini: View {
Button("") {
withAnimation(.easeInOut(duration: 0.5)) {
showPopover = false
updateOnMain {
if appState.zombieFile.fileSize.keys.count == 0 {
appState.currentView = .zombie
+45 -38
View File
@@ -17,7 +17,7 @@ struct ZombieView: View {
@Environment(\.colorScheme) var colorScheme
@Binding var showPopover: Bool
@Binding var search: String
@State private var toggles: Bool = true
@State private var selectedOption = "Default"
var body: some View {
VStack(alignment: .center) {
@@ -87,43 +87,11 @@ struct ZombieView: View {
// .foregroundStyle(Color("AccentColor").opacity(0.7))
.underline()
}
HStack() {
Image(systemName: "exclamationmark.triangle.fill")
.foregroundStyle(.red)
.popover(isPresented: $showPop, arrowEdge: .top) {
VStack() {
Text("Leftover file search is not 100% accurate as it doesn't have any app bundles to check against.\nThis searches for files/folders and excludes the ones that have overlap with your currently installed apps. \nMake sure to confirm files marked for removal are correct.")
.padding()
.font(.title2)
}
}
Text("Warning")
.foregroundStyle(Color.red)
Spacer()
Toggle("\(toggles ? "Selected: All" : "Selected: None")", isOn: $toggles)
.controlSize(.small)
// .toggleStyle(.switch)
.onChange(of: toggles) { value in
if value {
updateOnMain {
appState.selectedZombieItems = Set(appState.zombieFile.fileSize.keys)
}
} else {
updateOnMain {
appState.selectedZombieItems.removeAll()
}
}
}
}
.padding(.top)
.onTapGesture {
showPop = true
}
WarningPopoverView(label: "Caution - Read",
bodyText: "Leftover file search is not 100% accurate as it doesn't have any app bundles to check against.\nThis searches for files/folders and excludes the ones that have overlap with your currently installed apps. \nMake sure to confirm files marked for removal are correct.",
isPresented: $showPop)
.padding(.vertical, 5)
}
@@ -144,7 +112,14 @@ struct ZombieView: View {
ScrollView() {
LazyVStack {
ForEach(appState.zombieFile.fileSize.keys.sorted(by: { $0.lastPathComponent < $1.lastPathComponent }), id: \.self) { file in
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
if let fileSize = appState.zombieFile.fileSize[file], let fileIcon = appState.zombieFile.fileIcon[file] {
let iconImage = fileIcon.map(Image.init(nsImage:))
@@ -162,6 +137,23 @@ struct ZombieView: View {
.padding()
HStack() {
Picker("", selection: Binding(
get: { appState.selectedZombieItems.count == appState.zombieFile.fileSize.count ? true : false },
set: { newValue in
updateOnMain {
appState.selectedZombieItems = newValue ? Set(appState.zombieFile.fileSize.keys) : []
}
}
)) {
Text("􀃲").tag(true)
Text("􀂒").tag(false)
}
.pickerStyle(SegmentedPickerStyle())
.frame(width: 100)
.offset(x: -8)
.help("Item Selection")
Spacer()
if mini {
@@ -173,6 +165,8 @@ struct ZombieView: View {
showPopover = false
}
}
.buttonStyle(NavButtonBottomBarStyle(image: "x.circle.fill", help: "Close"))
}
@@ -183,6 +177,8 @@ struct ZombieView: View {
reversePathsSearch(appState: appState, locations: locations)
}
}
.buttonStyle(NavButtonBottomBarStyle(image: "arrow.counterclockwise.circle.fill", help: "Rescan files"))
Button("Remove") {
Task {
@@ -217,7 +213,18 @@ struct ZombieView: View {
}
}
.buttonStyle(NavButtonBottomBarStyle(image: "trash.fill", help: "Remove"))
.disabled(appState.selectedZombieItems.isEmpty)
Spacer()
Picker("", selection: $selectedOption) {
Text("􀅐").tag("Default")
Text("􀆃").tag("Size")
}
.pickerStyle(SegmentedPickerStyle())
.frame(width: 100)
.help("Sorting Selection")
}
}