mirror of
https://github.com/exituser/Pearcleaner.git
synced 2026-09-17 09:38:51 +00:00
v3.7.0
This commit is contained in:
@@ -33,16 +33,7 @@ struct AppCommands: Commands {
|
||||
|
||||
Button {
|
||||
withAnimation(.easeInOut(duration: 0.5)) {
|
||||
// Refresh Apps list
|
||||
updateOnMain {
|
||||
appState.reload.toggle()
|
||||
}
|
||||
let sortedApps = getSortedApps(paths: fsm.folderPaths, appState: appState)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||
appState.sortedApps = []
|
||||
appState.sortedApps = sortedApps
|
||||
appState.reload.toggle()
|
||||
}
|
||||
reloadAppsList(appState: appState, fsm: fsm)
|
||||
}
|
||||
} label: {
|
||||
Text("Refresh Apps")
|
||||
@@ -65,12 +56,9 @@ struct AppCommands: Commands {
|
||||
Button
|
||||
{
|
||||
undoTrash(appState: appState) {
|
||||
let sortedApps = getSortedApps(paths: fsm.folderPaths, appState: appState)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
appState.sortedApps = sortedApps
|
||||
for app in appState.trashedFiles {
|
||||
AppPathFinder(appInfo: app, appState: appState, locations: locations, undo: true).findPaths()
|
||||
}
|
||||
reloadAppsList(appState: appState, fsm: fsm)
|
||||
for app in appState.trashedFiles {
|
||||
AppPathFinder(appInfo: app, appState: appState, locations: locations, undo: true).findPaths()
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
|
||||
@@ -46,22 +46,19 @@ class AppInfoFetcher {
|
||||
return nil
|
||||
}
|
||||
|
||||
// let appName = bundle.infoDictionary?["CFBundleDisplayName"] as? String ?? bundle.infoDictionary?["CFBundleName"] as? String
|
||||
// ?? bundle.localizedInfoDictionary?[kCFBundleNameKey as String] as? String ?? path.deletingPathExtension().lastPathComponent
|
||||
|
||||
let appName = wrapped ? path.deletingLastPathComponent().deletingLastPathComponent().deletingPathExtension().lastPathComponent.capitalizingFirstLetter() : path.deletingPathExtension().lastPathComponent.capitalizingFirstLetter()
|
||||
|
||||
let appVersion = bundle.infoDictionary?["CFBundleShortVersionString"] as? String
|
||||
?? bundle.infoDictionary?["CFBundleVersion"] as? String
|
||||
?? ""
|
||||
let appVersion = (bundle.infoDictionary?["CFBundleShortVersionString"] as? String)?.isEmpty ?? true
|
||||
? bundle.infoDictionary?["CFBundleVersion"] as? String ?? ""
|
||||
: bundle.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
|
||||
|
||||
let appIcon = fetchAppIcon(for: path, wrapped: wrapped)
|
||||
let webApp = (bundle.infoDictionary?["LSTemplateApplication"] as? Bool ?? false || bundle.infoDictionary?["CFBundleExecutable"] as? String == "app_mode_loader")
|
||||
|
||||
let webApp = bundle.infoDictionary?["LSTemplateApplication"] as? Bool ?? false
|
||||
let system = !path.path.contains(NSHomeDirectory())
|
||||
|
||||
return AppInfo(id: UUID(), path: path, bundleIdentifier: bundleIdentifier, appName: appName, appVersion: appVersion, appIcon: appIcon,
|
||||
webApp: webApp, wrapped: wrapped, system: system, files: [], fileSize: [:], fileSizeLogical: [:], fileIcon: [:])
|
||||
webApp: webApp, wrapped: wrapped, system: system, bundleSize: 0, files: [], fileSize: [:], fileSizeLogical: [:], fileIcon: [:])
|
||||
}
|
||||
|
||||
private static func fetchAppIcon(for path: URL, wrapped: Bool) -> NSImage? {
|
||||
|
||||
@@ -47,6 +47,7 @@ class AppState: ObservableObject {
|
||||
webApp: false,
|
||||
wrapped: false,
|
||||
system: false,
|
||||
bundleSize: 0,
|
||||
files: [],
|
||||
fileSize: [:],
|
||||
fileSizeLogical: [:],
|
||||
@@ -98,6 +99,7 @@ struct AppInfo: Identifiable, Equatable, Hashable {
|
||||
let webApp: Bool
|
||||
let wrapped: Bool
|
||||
let system: Bool
|
||||
var bundleSize: Int64
|
||||
var files: [URL]
|
||||
var fileSize: [URL:Int64]
|
||||
var fileSizeLogical: [URL:Int64]
|
||||
@@ -112,7 +114,7 @@ struct AppInfo: Identifiable, Equatable, Hashable {
|
||||
}
|
||||
|
||||
|
||||
static let empty = AppInfo(id: UUID(), path: URL(fileURLWithPath: ""), bundleIdentifier: "", appName: "", appVersion: "", appIcon: nil, webApp: false, wrapped: false, system: false, files: [], fileSize: [:], fileSizeLogical: [:], fileIcon: [:])
|
||||
static let empty = AppInfo(id: UUID(), path: URL(fileURLWithPath: ""), bundleIdentifier: "", appName: "", appVersion: "", appIcon: nil, webApp: false, wrapped: false, system: false, bundleSize: 0, files: [], fileSize: [:], fileSizeLogical: [:], fileIcon: [:])
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,6 @@ func getSortedApps(paths: [String], appState: AppState) -> [AppInfo] {
|
||||
// Get app info and sort
|
||||
let sortedApps = apps
|
||||
.compactMap { AppInfoFetcher.getAppInfo(atPath: $0) }
|
||||
.sorted { $0.appName.replacingOccurrences(of: ".", with: "").lowercased() < $1.appName.replacingOccurrences(of: ".", with: "").lowercased() }
|
||||
|
||||
|
||||
return sortedApps
|
||||
}
|
||||
|
||||
@@ -570,13 +570,7 @@ struct AnimatedSearchStyle: TextFieldStyle {
|
||||
.foregroundStyle(isHovered ? Color("mode").opacity(0.8) : Color("mode").opacity(0.5))
|
||||
.onTapGesture {
|
||||
withAnimation {
|
||||
// Refresh Apps list
|
||||
appState.reload.toggle()
|
||||
let sortedApps = getSortedApps(paths: fsm.folderPaths, appState: appState)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||
appState.sortedApps = sortedApps
|
||||
appState.reload.toggle()
|
||||
}
|
||||
reloadAppsList(appState: appState, fsm: fsm)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,19 +27,25 @@ func updateOnMain(after delay: Double? = nil, _ updates: @escaping () -> Void) {
|
||||
|
||||
// Execute functions on background thread
|
||||
func updateOnBackground(_ updates: @escaping () -> Void) {
|
||||
DispatchQueue.global(qos: .background).async {
|
||||
DispatchQueue.global(qos: .userInitiated).async {
|
||||
updates()
|
||||
}
|
||||
}
|
||||
|
||||
// Reload apps list
|
||||
func reloadAppsList(appState: AppState, fsm: FolderSettingsManager) {
|
||||
appState.reload = true
|
||||
updateOnBackground {
|
||||
let sortedApps = getSortedApps(paths: fsm.folderPaths, appState: appState)
|
||||
// Update UI on the main thread
|
||||
updateOnMain {
|
||||
appState.sortedApps = sortedApps
|
||||
appState.reload = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Resize window
|
||||
//func resizeWindow(width: CGFloat, height: CGFloat) {
|
||||
// if let window = NSApplication.shared.windows.first {
|
||||
// let newSize = NSSize(width: width, height: height)
|
||||
// window.setContentSize(newSize)
|
||||
// }
|
||||
//}
|
||||
|
||||
func resizeWindowAuto(windowSettings: WindowSettings, title: String) {
|
||||
if let window = NSApplication.shared.windows.first(where: { $0.title == title }) {
|
||||
@@ -160,16 +166,26 @@ func caskCleanup(app: String) {
|
||||
#elseif arch(arm64)
|
||||
let cmd = "/opt/homebrew/bin/brew"
|
||||
#endif
|
||||
let formattedApp = app.lowercased().replacingOccurrences(of: " ", with: "-")
|
||||
process.executableURL = URL(fileURLWithPath: "/bin/zsh")
|
||||
process.arguments = ["-c", "\(cmd) uninstall --cask \(app) --force; \(cmd) cleanup"]
|
||||
// let pipe = Pipe()
|
||||
process.standardOutput = FileHandle.nullDevice//pipe
|
||||
process.standardError = FileHandle.nullDevice//pipe
|
||||
// process.arguments = ["-c", "\(cmd) uninstall --cask \"\(formattedApp)\" --force; \(cmd) cleanup"]
|
||||
process.arguments = ["-c", """
|
||||
found_cask=$(\(cmd) list --cask | grep "\(formattedApp)")
|
||||
if [ -n "$found_cask" ]; then
|
||||
\(cmd) uninstall --cask "$found_cask" --force;
|
||||
\(cmd) cleanup;
|
||||
else
|
||||
echo "Cask not found for \(formattedApp)";
|
||||
fi
|
||||
"""]
|
||||
let pipe = Pipe()
|
||||
process.standardOutput = pipe
|
||||
process.standardError = pipe
|
||||
try? process.run()
|
||||
process.waitUntilExit() // Ensure the process completes
|
||||
// let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||
// let output = (String(data: data, encoding: .utf8) ?? "") as String
|
||||
// print(output)
|
||||
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||
let output = (String(data: data, encoding: .utf8) ?? "") as String
|
||||
print(output)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,6 +515,7 @@ func formatByte(size: Int64) -> (human: String, byte: String) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Only process supported files
|
||||
func isSupportedFileType(at path: String) -> Bool {
|
||||
let fileManager = FileManager.default
|
||||
|
||||
Reference in New Issue
Block a user