This commit is contained in:
Alin
2024-04-09 10:50:01 -06:00
parent 00ce0e5015
commit 5062320650
10 changed files with 254 additions and 158 deletions
+4 -4
View File
@@ -575,7 +575,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 30;
CURRENT_PROJECT_VERSION = 31;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = BK8443AXLU;
@@ -593,7 +593,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 3.3.4;
MARKETING_VERSION = 3.4.0;
PRODUCT_BUNDLE_IDENTIFIER = com.alienator88.Pearcleaner;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
@@ -610,7 +610,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 30;
CURRENT_PROJECT_VERSION = 31;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = BK8443AXLU;
@@ -628,7 +628,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 13.0;
MARKETING_VERSION = 3.3.4;
MARKETING_VERSION = 3.4.0;
PRODUCT_BUNDLE_IDENTIFIER = com.alienator88.Pearcleaner;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
-1
View File
@@ -186,4 +186,3 @@ enum DisplayMode: Int, CaseIterable {
}
+38
View File
@@ -123,6 +123,44 @@ struct InfoButton: View {
}
struct UninstallButton: ButtonStyle {
var isEnabled: Bool
func makeBody(configuration: Configuration) -> some View {
HStack(alignment: .center, spacing: 10) {
Image(systemName: "trash")
.foregroundColor(isEnabled ? .white.opacity(1) : .white.opacity(0.3))
Divider()
.frame(height: 24)
.opacity(0.5)
configuration.label
.foregroundColor(isEnabled ? .white.opacity(1) : .white.opacity(0.3))
}
.frame(height: 24)
.frame(minWidth: 75)
.padding(.horizontal)
.padding(.vertical, 4)
.background(configuration.isPressed ? Color("uninstall").opacity(0.8) : Color("uninstall"))
// .background(
// configuration.isPressed ? Color("uninstall").opacity(0.8) :
// (isEnabled ? Color("uninstall") : Color.gray)
// )
.cornerRadius(8)
.onHover { over in
if over {
NSCursor.pointingHand.push()
} else {
NSCursor.pop()
}
}
}
}
struct WarningPopoverView: View {
var label: String
var bodyText: String
@@ -0,0 +1,38 @@
{
"colors" : [
{
"color" : {
"color-space" : "display-p3",
"components" : {
"alpha" : "1.000",
"blue" : "0x4D",
"green" : "0x58",
"red" : "0xD7"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "display-p3",
"components" : {
"alpha" : "1.000",
"blue" : "0x3E",
"green" : "0x47",
"red" : "0xB0"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
+50 -1
View File
@@ -24,6 +24,8 @@ struct GeneralSettingsTab: View {
@AppStorage("settings.general.brew") private var brew: Bool = false
@AppStorage("settings.general.instant") private var instantSearch: Bool = true
@AppStorage("settings.general.selectedTheme") var selectedTheme: String = "Auto"
@AppStorage("settings.general.selectedSort") var selectedSortAlpha: Bool = true
@State private var diskStatus: Bool = false
@State private var accessStatus: Bool = false
private let themes = ["Auto", "Dark", "Light"]
@@ -89,6 +91,53 @@ struct GeneralSettingsTab: View {
.padding(.leading)
HStack(spacing: 0) {
Image(systemName: selectedSortAlpha ? "textformat.abc" : "textformat.123")
.resizable()
.scaledToFit()
.frame(width: 20, height: 20)
.padding(.trailing)
.foregroundStyle(.gray)
VStack(alignment: .leading, spacing: 5) {
Text("File list sorting mode")
.font(.callout)
.foregroundStyle(.gray)
}
InfoButton(text: "When searching for app files or leftover files, the list will be sorted based on this choice", color: nil, label: "")
Spacer()
Picker("", selection: $selectedSortAlpha) {
Text("Alphabetical").tag(true)
Text("Size").tag(false)
}
.pickerStyle(SegmentedPickerStyle())
.frame(width: 200)
}
.padding(5)
.padding(.leading)
// HStack(spacing: 0) {
// Image(systemName: selectedSortAlpha ? "textformat.abc" : "textformat.123")
// .resizable()
// .scaledToFit()
// .frame(width: 20, height: 20)
// .padding(.trailing)
// .foregroundStyle(.gray)
// VStack(alignment: .leading, spacing: 5) {
// Text("\(selectedSortAlpha ? "File list sorted alphabetically" : "File list sorted by size")")
// .font(.callout)
// .foregroundStyle(.gray)
// }
//
// InfoButton(text: "When searching for app files or leftover files, the list will be sorted based on this choice", color: nil, label: "")
//
// Spacer()
// Toggle(isOn: $selectedSortAlpha, label: {
// })
// .toggleStyle(.switch)
// }
// .padding(5)
// .padding(.leading)
// === Perms ================================================================================================
@@ -208,7 +257,7 @@ struct GeneralSettingsTab: View {
}
.padding(20)
.frame(width: 500, height: 420)
.frame(width: 500, height: 460)
}
+26 -11
View File
@@ -18,18 +18,18 @@ struct InterfaceSettingsTab: View {
@AppStorage("settings.menubar.enabled") private var menubarEnabled: Bool = false
@AppStorage("settings.general.mini") private var mini: Bool = false
@AppStorage("displayMode") var displayMode: DisplayMode = .system
@AppStorage("settings.general.selectedTab") private var selectedTab: CurrentTabView = .general
@AppStorage("settings.general.glass") private var glass: Bool = true
@AppStorage("settings.general.dark") var isDark: Bool = true
@AppStorage("settings.general.popover") private var popoverStay: Bool = true
@AppStorage("settings.general.miniview") private var miniView: Bool = true
@AppStorage("settings.general.selectedTheme") var selectedTheme: String = "Auto"
@AppStorage("settings.interface.selectedMenubarIcon") var selectedMenubarIcon: String = "pear-4"
private let themes = ["Auto", "Dark", "Light"]
@State private var isLaunchAtLoginEnabled: Bool = false
let icons = ["externaldrive", "trash", "folder", "pear-1", "pear-1.5", "pear-2", "pear-3", "pear-4"]
@Binding var showPopover: Bool
@Binding var search: String
let icons = ["externaldrive", "trash", "folder", "pear-1", "pear-1.5", "pear-2", "pear-3", "pear-4"]
private let themes = ["Auto", "Dark", "Light"]
var body: some View {
Form {
@@ -67,7 +67,16 @@ struct InterfaceSettingsTab: View {
HStack(spacing: 0) {
Image(systemName: displayMode.colorScheme == .dark ? "moon.fill" : "sun.max.fill")
Image(systemName: {
switch displayMode {
case .dark:
return "moon.fill"
case .light:
return "sun.max.fill"
case .system:
return "circle.righthalf.filled"
}
}())
.resizable()
.scaledToFit()
.frame(width: 20, height: 20)
@@ -90,19 +99,23 @@ struct InterfaceSettingsTab: View {
switch newTheme {
case "Auto":
displayMode.colorScheme = nil
if isDarkModeEnabled() {
displayMode.colorScheme = .dark
MenuBarExtraManager.shared.restartMenuBarExtra()
} else {
displayMode.colorScheme = .light
// Refresh foreground colors
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.selectedTab = .interface
}
if menubarEnabled{
MenuBarExtraManager.shared.restartMenuBarExtra()
}
case "Dark":
displayMode.colorScheme = .dark
MenuBarExtraManager.shared.restartMenuBarExtra()
if menubarEnabled{
MenuBarExtraManager.shared.restartMenuBarExtra()
}
case "Light":
displayMode.colorScheme = .light
MenuBarExtraManager.shared.restartMenuBarExtra()
if menubarEnabled{
MenuBarExtraManager.shared.restartMenuBarExtra()
}
default:
break
}
@@ -148,6 +161,7 @@ struct InterfaceSettingsTab: View {
if mini {
appState.currentView = miniView ? .apps : .empty
showPopover = false
findAndHideWindows(named: ["Pearcleaner"])
windowSettings.newWindow {
MiniMode(search: $search, showPopover: $showPopover)
.environmentObject(locations)
@@ -164,6 +178,7 @@ struct InterfaceSettingsTab: View {
} else {
appState.currentView = .files
}
findAndHideWindows(named: ["Pearcleaner"])
windowSettings.newWindow {
RegularMode(search: $search, showPopover: $showPopover)
.environmentObject(locations)
+3 -4
View File
@@ -14,10 +14,11 @@ struct SettingsView: View {
@Binding var search: String
@Binding var showFeature: Bool
@AppStorage("settings.general.glass") private var glass: Bool = true
@AppStorage("settings.general.selectedTab") private var selectedTab: CurrentTabView = .general
var body: some View {
TabView() {
TabView(selection: $selectedTab) {
GeneralSettingsTab(showPopover: $showPopover, search: $search)
.tabItem {
Label(CurrentTabView.general.title, systemImage: "gear")
@@ -47,13 +48,11 @@ struct SettingsView: View {
Label(CurrentTabView.about.title, systemImage: "info.circle")
}
.tag(CurrentTabView.about)
}
.background(glass ? GlassEffect(material: .sidebar, blendingMode: .behindWindow).edgesIgnoringSafeArea(.all) : nil)
}
}
+67 -88
View File
@@ -17,15 +17,22 @@ struct FilesView: View {
@AppStorage("settings.general.instant") var instantSearch: Bool = true
@AppStorage("settings.general.brew") private var brew: Bool = false
@AppStorage("settings.menubar.enabled") private var menubarEnabled: Bool = false
@AppStorage("settings.general.selectedSort") var selectedSortAlpha: Bool = true
@Environment(\.colorScheme) var colorScheme
@Binding var showPopover: Bool
@Binding var search: String
var regularWin: Bool
@State private var selectedOption = "Default"
// @State private var selectedOption = "Alpha"
@State private var elapsedTime = 0
@State private var timer: Timer? = nil
var body: some View {
let totalSelectedSize = appState.selectedItems.reduce(Int64(0)) { (result, url) in
result + (appState.appInfo.fileSize[url] ?? 0)
}
VStack(alignment: .center) {
if appState.showProgress {
VStack {
@@ -131,7 +138,9 @@ struct FilesView: View {
}
}
Text("\(appState.appInfo.bundleIdentifier)").font(.title3)
Text("\(appState.appInfo.bundleIdentifier)")
.lineLimit(1)
.font(.title3)
.foregroundStyle((.gray.opacity(0.8)))
}
.padding(.leading)
@@ -140,7 +149,8 @@ struct FilesView: View {
VStack(alignment: .trailing, spacing: 5) {
Text("\(formatByte(size: appState.appInfo.totalSize))").font(.title).fontWeight(.bold)
Text("\(appState.appInfo.fileSize.count > 1 ? "\(appState.appInfo.fileSize.count) items" : "\(appState.appInfo.fileSize.count) item")").font(.callout).underline().foregroundStyle((.gray.opacity(0.8)))
Text("\(appState.appInfo.fileSize.count == 1 ? "\(appState.selectedItems.count) / \(appState.appInfo.fileSize.count) item" : "\(appState.selectedItems.count) / \(appState.appInfo.fileSize.count) items")")
.font(.callout).foregroundStyle((.gray.opacity(0.8)))
}
}
@@ -205,9 +215,10 @@ struct FilesView: View {
Spacer()
Button("") {
selectedOption = selectedOption == "Default" ? "Size" : "Default"
selectedSortAlpha.toggle()
// selectedOption = selectedOption == "Alpha" ? "Size" : "Alpha"
}
.buttonStyle(SimpleButtonStyle(icon: selectedOption == "Default" ? "textformat.abc" : "textformat.123", help: selectedOption == "Default" ? "Sorted alphabetically" : "Sorted by size", color: Color("mode")))
.buttonStyle(SimpleButtonStyle(icon: selectedSortAlpha ? "textformat.abc" : "textformat.123", help: selectedSortAlpha ? "Sorted alphabetically" : "Sorted by size", color: Color("mode")))
}
.padding()
@@ -237,19 +248,20 @@ struct FilesView: View {
}
}
let sort = selectedOption == "Default" ? sortedFilesAlpha : sortedFilesSize
let sort = selectedSortAlpha ? sortedFilesAlpha : sortedFilesSize
ForEach(sort, id: \.self) { path in
ForEach(Array(sort.enumerated()), id: \.element) { index, path in
if let fileSize = appState.appInfo.fileSize[path], let fileIcon = appState.appInfo.fileIcon[path] {
let iconImage = fileIcon.map(Image.init(nsImage:))
VStack {
FileDetailsItem(size: fileSize, icon: iconImage, path: path)
if path != appState.appInfo.files.last {
if index < sort.count - 1 {
Divider().padding(.leading, 40).opacity(0.5)
}
}
}
}
}
.padding()
}
@@ -261,97 +273,64 @@ struct FilesView: View {
Spacer()
if !appState.selectedItems.isEmpty {
Button("Uninstall") {
Task {
updateOnMain {
search = ""
if !regularWin {
appState.currentView = .apps
Button("\(formatByte(size: totalSelectedSize))") {
Task {
updateOnMain {
search = ""
if !regularWin {
appState.currentView = .apps
showPopover = false
} else {
appState.currentView = .empty
}
}
let selectedItemsArray = Array(appState.selectedItems)
killApp(appId: appState.appInfo.bundleIdentifier) {
moveFilesToTrash(at: selectedItemsArray) {
withAnimation {
showPopover = false
updateOnMain {
appState.currentView = mini ? .apps : .empty
appState.isReminderVisible.toggle()
}
if sentinel {
launchctl(load: true)
}
}
// Brew cleanup if enabled
if brew {
caskCleanup(app: appState.appInfo.appName)
}
// Remove app from app list if main app bundle is removed
if selectedItemsArray.contains(where: { $0.absoluteString == appState.appInfo.path.absoluteString }) {
removeApp(appState: appState, withId: appState.appInfo.id)
} else {
appState.currentView = .empty
// Add deleted appInfo object to trashed array
appState.appInfo.files = []
appState.appInfo.fileSize = [:]
appState.trashedFiles.append(appState.appInfo)
// Clear out appInfoStore object
if let index = appState.appInfoStore.firstIndex(where: { $0.path == appState.appInfo.path }) {
appState.appInfoStore[index] = .empty
}
}
appState.appInfo = AppInfo.empty
}
let selectedItemsArray = Array(appState.selectedItems)
// Delete all folders above app bundle between /Applications and app bundle file
// if let url = URL(string: appState.appInfo.path.absoluteString) {
// var parentURL = url.deletingLastPathComponent() // Immediate parent of the .app bundle
//
// // Traverse up the path components until just below /Applications or ~/Applications
// while parentURL.pathComponents.count > 2 && parentURL.path.contains("Applications") && parentURL.deletingLastPathComponent().path != "/Applications" && parentURL.deletingLastPathComponent().path != "\(home)/Applications" {
// parentURL = parentURL.deletingLastPathComponent()
// }
//
// // Now, parentURL should be the directory just below /Applications or ~/Applications
// if parentURL.path != "/Applications" && parentURL.path != "\(home)/Applications" {
// selectedItemsArray.insert(parentURL, at: 0) // Add the correct parent directory to the array
// }
// }
// Delete folder only 1 up from app bundle between /Applications and app bundle file
// if let url = URL(string: appState.appInfo.path.absoluteString) {
// let appFolderURL = appState.appInfo.path.absoluteString.contains("Wrapper") ? url.deletingLastPathComponent().deletingLastPathComponent().deletingLastPathComponent() : url.deletingLastPathComponent() // Get the immediate parent directory of regular and wrapped apps
//
// if appFolderURL.path == "/Applications" || appFolderURL.path == "\(home)/Applications" {
// // Do nothing, skip insertion
// } 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)
// }
// }
killApp(appId: appState.appInfo.bundleIdentifier) {
moveFilesToTrash(at: selectedItemsArray) {
withAnimation {
showPopover = false
updateOnMain {
appState.currentView = mini ? .apps : .empty
appState.isReminderVisible.toggle()
}
if sentinel {
launchctl(load: true)
}
}
// Brew cleanup if enabled
if brew {
caskCleanup(app: appState.appInfo.appName)
}
// Remove app from app list if main app bundle is removed
if selectedItemsArray.contains(where: { $0.absoluteString == appState.appInfo.path.absoluteString }) {
removeApp(appState: appState, withId: appState.appInfo.id)
} else {
// Add deleted appInfo object to trashed array
appState.appInfo.files = []
appState.appInfo.fileSize = [:]
appState.trashedFiles.append(appState.appInfo)
// Clear out appInfoStore object
if let index = appState.appInfoStore.firstIndex(where: { $0.path == appState.appInfo.path }) {
appState.appInfoStore[index] = .empty
}
}
appState.appInfo = AppInfo.empty
}
}
}
}
.buttonStyle(NavButtonBottomBarStyle(image: "trash.fill", help: "Uninstall"))
} else {
Text("No files selected to remove").font(.title).foregroundStyle(Color("mode")).opacity(0.2)
.padding(5)
}
.buttonStyle(UninstallButton(isEnabled: !appState.selectedItems.isEmpty))
.disabled(appState.selectedItems.isEmpty)
.padding(.top)
Spacer()
// Spacer()
}
+2
View File
@@ -29,6 +29,7 @@ struct RegularMode: View {
}
}
// let slate = Color(.sRGB, red: 0.188143, green: 0.208556, blue: 0.262679, opacity: 1)
var body: some View {
@@ -103,6 +104,7 @@ struct RegularMode: View {
}
.transition(.opacity)
}
// .background(slate)
// .onHover { hovering in
// withAnimation(Animation.easeInOut(duration: 0.4)) {
// isHovering = hovering
+26 -49
View File
@@ -16,24 +16,29 @@ struct ZombieView: View {
@AppStorage("settings.sentinel.enable") private var sentinel: Bool = false
@AppStorage("settings.general.instant") private var instantSearch: Bool = true
@AppStorage("settings.menubar.enabled") private var menubarEnabled: Bool = false
@AppStorage("settings.general.selectedSort") var selectedSortAlpha: Bool = true
@Environment(\.colorScheme) var colorScheme
@Binding var showPopover: Bool
@Binding var search: String
@State private var searchZ: String = ""
@State private var selectedOption = "Default"
// @State private var selectedOption = "Alpha"
var regularWin: Bool
@State private var elapsedTime = 0
@State private var timer: Timer? = nil
var body: some View {
let totalSelectedZombieSize = appState.selectedZombieItems.reduce(Int64(0)) { (result, url) in
result + (appState.zombieFile.fileSize[url] ?? 0)
}
let filteredAndSortedFiles: ([URL], Int64) = {
let filteredFiles = appState.zombieFile.fileSize.filter { (url, _) in
searchZ.isEmpty || url.lastPathComponent.localizedCaseInsensitiveContains(searchZ)
}
let sortedFilteredFiles = filteredFiles.sorted(by: {
if selectedOption == "Default" {
if selectedSortAlpha {
return $0.key.lastPathComponent.pearFormat() < $1.key.lastPathComponent.pearFormat()
} else {
return $0.value > $1.value
@@ -148,7 +153,9 @@ struct ZombieView: View {
VStack(alignment: .trailing, spacing: 5) {
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)))
Text("\(appState.zombieFile.fileSize.count == 1 ? "\(appState.selectedZombieItems.count) / \(appState.zombieFile.fileSize.count) item" : "\(appState.selectedZombieItems.count) / \(appState.zombieFile.fileSize.count) items")")
.font(.callout).foregroundStyle((.gray.opacity(0.8)))
}
}
@@ -158,10 +165,6 @@ struct ZombieView: View {
.padding(.top, 0)
}
// SearchBarMiniBottom(search: $searchZ)
// .padding(.top)
// .padding(.horizontal)
// Item selection and sorting toolbar
HStack {
Toggle("", isOn: Binding(
@@ -177,12 +180,11 @@ struct ZombieView: View {
// .padding(.top)
.padding(.horizontal)
// Spacer()
Button("") {
selectedOption = selectedOption == "Default" ? "Size" : "Default"
selectedSortAlpha.toggle()
}
.buttonStyle(SimpleButtonStyle(icon: selectedOption == "Default" ? "textformat.abc" : "textformat.123", help: selectedOption == "Default" ? "Sorted alphabetically" : "Sorted by size", color: Color("mode")))
.buttonStyle(SimpleButtonStyle(icon: selectedSortAlpha ? "textformat.abc" : "textformat.123", help: selectedSortAlpha ? "Sorted alphabetically" : "Sorted by size", color: Color("mode")))
}
@@ -193,22 +195,22 @@ struct ZombieView: View {
Divider()
.padding(.horizontal)
ScrollView() {
LazyVStack {
ForEach(filteredAndSortedFiles.0, id: \.self) { file in
ForEach(Array(filteredAndSortedFiles.0.enumerated()), id: \.element) { index, file in
if let fileSize = appState.zombieFile.fileSize[file], let fileIcon = appState.zombieFile.fileIcon[file] {
let iconImage = fileIcon.map(Image.init(nsImage:))
VStack {
ZombieFileDetailsItem(size: fileSize, icon: iconImage, path: file)
.padding(.trailing)
ZombieFileDetailsItem(size: fileSize, icon: iconImage, path: file)
.padding(.trailing)
if file != appState.zombieFile.fileSize.keys.sorted(by: { $0.absoluteString < $1.absoluteString }).last {
Divider().padding(.leading, 40).opacity(0.5)
if index < filteredAndSortedFiles.0.count - 1 {
Divider().padding(.leading, 40).opacity(0.5)
}
}
}
}
}
.padding()
}
@@ -217,26 +219,9 @@ struct ZombieView: View {
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) : []
// }
// }
// )) {
// Image(systemName: "checkmark.square").tag(true)
// Image(systemName: "square").tag(false)
// }
// .pickerStyle(SegmentedPickerStyle())
// .frame(width: 100)
// .offset(x: -8)
// .help("Item Selection")
Spacer()
if !appState.selectedZombieItems.isEmpty {
Button("Remove") {
Button("\(formatByte(size: totalSelectedZombieSize))") {
Task {
updateOnMain {
appState.zombieFile = .empty
@@ -265,21 +250,13 @@ struct ZombieView: View {
}
}
.buttonStyle(NavButtonBottomBarStyle(image: "trash.fill", help: "Remove"))
} else {
Text("No files selected to remove").font(.title).foregroundStyle(Color("mode")).opacity(0.2)
.padding(5)
}
.buttonStyle(UninstallButton(isEnabled: !appState.selectedZombieItems.isEmpty))
.disabled(appState.selectedZombieItems.isEmpty)
.padding(.top)
Spacer()
// Picker("", selection: $selectedOption) {
// Image(systemName: "textformat.abc").tag("Default")
// Image(systemName: "number").tag("Size")
// }
// .pickerStyle(SegmentedPickerStyle())
// .frame(width: 100)
// .help("Sorting alphabetically or by size")
// Spacer()
}
}