mirror of
https://github.com/exituser/Pearcleaner.git
synced 2026-09-17 04:58:56 +00:00
3.1.0
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
C7D31D482AFEB23700C7ED9E /* TopBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7D31D472AFEB23700C7ED9E /* TopBar.swift */; };
|
||||
C7D31D4A2AFEB26700C7ED9E /* AppListItems.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7D31D492AFEB26700C7ED9E /* AppListItems.swift */; };
|
||||
C7D31D512AFF00F300C7ED9E /* Locations.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7D31D502AFF00F300C7ED9E /* Locations.swift */; };
|
||||
C7DC1FEE2B9F7D3D009AC317 /* features.json in Resources */ = {isa = PBXBuildFile; fileRef = C7DC1FED2B9F7D3D009AC317 /* features.json */; };
|
||||
C7F539382AF60865007DF1B2 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F539372AF60865007DF1B2 /* Utilities.swift */; };
|
||||
C7FB173B2B96321300B96F9A /* AppsListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7FB173A2B96321300B96F9A /* AppsListView.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
@@ -95,6 +96,7 @@
|
||||
C7D31D472AFEB23700C7ED9E /* TopBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopBar.swift; sourceTree = "<group>"; };
|
||||
C7D31D492AFEB26700C7ED9E /* AppListItems.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppListItems.swift; sourceTree = "<group>"; };
|
||||
C7D31D502AFF00F300C7ED9E /* Locations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Locations.swift; sourceTree = "<group>"; };
|
||||
C7DC1FED2B9F7D3D009AC317 /* features.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = features.json; sourceTree = SOURCE_ROOT; };
|
||||
C7F539372AF60865007DF1B2 /* Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utilities.swift; sourceTree = "<group>"; };
|
||||
C7FB173A2B96321300B96F9A /* AppsListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppsListView.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
@@ -175,6 +177,7 @@
|
||||
C76D084F2AF84E0100D07867 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
C7DC1FED2B9F7D3D009AC317 /* features.json */,
|
||||
C7A27E802AFD7C4600166168 /* com.alienator88.PearcleanerSentinel.plist */,
|
||||
C77B90142AF18E7C009CC655 /* Info.plist */,
|
||||
C77B90072AF18E2F009CC655 /* Assets.xcassets */,
|
||||
@@ -320,6 +323,7 @@
|
||||
files = (
|
||||
C77B90082AF18E2F009CC655 /* Assets.xcassets in Resources */,
|
||||
C7A27E812AFD7C4600166168 /* com.alienator88.PearcleanerSentinel.plist in Resources */,
|
||||
C7DC1FEE2B9F7D3D009AC317 /* features.json in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -539,7 +543,7 @@
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 21;
|
||||
CURRENT_PROJECT_VERSION = 22;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
DEVELOPMENT_TEAM = BK8443AXLU;
|
||||
@@ -557,7 +561,7 @@
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||
MARKETING_VERSION = 3.0.2;
|
||||
MARKETING_VERSION = 3.1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.alienator88.Pearcleaner;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
@@ -574,7 +578,7 @@
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 21;
|
||||
CURRENT_PROJECT_VERSION = 22;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_ASSET_PATHS = "";
|
||||
DEVELOPMENT_TEAM = BK8443AXLU;
|
||||
@@ -592,7 +596,7 @@
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||
MARKETING_VERSION = 3.0.2;
|
||||
MARKETING_VERSION = 3.1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.alienator88.Pearcleaner;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
|
||||
@@ -30,7 +30,6 @@ class AppState: ObservableObject
|
||||
@Published var popCount: Int = 0
|
||||
|
||||
|
||||
|
||||
init() {
|
||||
self.appInfo = AppInfo(
|
||||
id: UUID(),
|
||||
|
||||
@@ -157,6 +157,52 @@ func isDarkModeEnabled() -> Bool {
|
||||
}
|
||||
|
||||
|
||||
// Check if appearance is dark mode
|
||||
//func getCasks() -> [String] {
|
||||
// let process = Process()
|
||||
//#if arch(x86_64)
|
||||
// let cmd = "/usr/local/bin/brew"
|
||||
//#elseif arch(arm64)
|
||||
// let cmd = "/opt/homebrew/bin/brew"
|
||||
//#endif
|
||||
// process.executableURL = URL(fileURLWithPath: cmd)
|
||||
// process.arguments = ["list", "--cask"]
|
||||
// let pipe = Pipe()
|
||||
// process.standardOutput = pipe
|
||||
// process.standardError = pipe
|
||||
// try? process.run()
|
||||
// process.waitUntilExit() // Ensure the process completes
|
||||
// let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||
// if let output = String(data: data, encoding: .utf8), !output.isEmpty {
|
||||
// return output.components(separatedBy: "\n").filter { !$0.isEmpty }.map { $0.replacingOccurrences(of: "-", with: " ") }
|
||||
// } else {
|
||||
// return []
|
||||
// }
|
||||
//}
|
||||
|
||||
// Brew cleanup
|
||||
func caskCleanup(app: String) {
|
||||
Task(priority: .high) {
|
||||
let process = Process()
|
||||
#if arch(x86_64)
|
||||
let cmd = "/usr/local/bin/brew"
|
||||
#elseif arch(arm64)
|
||||
let cmd = "/opt/homebrew/bin/brew"
|
||||
#endif
|
||||
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
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check if symlink
|
||||
func isSymlink(atPath path: URL) -> Bool {
|
||||
do {
|
||||
@@ -218,22 +264,6 @@ func getIconForFileOrFolderNS(atPath path: URL) -> NSImage? {
|
||||
}
|
||||
|
||||
// Get average color from image
|
||||
//extension NSImage {
|
||||
// var averageColor2: NSColor? {
|
||||
// guard let inputImage = CIImage(image: self) else { return nil }
|
||||
// let extentVector = CIVector(x: inputImage.extent.origin.x, y: inputImage.extent.origin.y, z: inputImage.extent.size.width, w: inputImage.extent.size.height)
|
||||
//
|
||||
// guard let filter = CIFilter(name: "CIAreaAverage", parameters: [kCIInputImageKey: inputImage, kCIInputExtentKey: extentVector]) else { return nil }
|
||||
// guard let outputImage = filter.outputImage else { return nil }
|
||||
//
|
||||
// var bitmap = [UInt8](repeating: 0, count: 4)
|
||||
// let context = CIContext(options: [.workingColorSpace: kCFNull!])
|
||||
// context.render(outputImage, toBitmap: &bitmap, rowBytes: 4, bounds: CGRect(x: 0, y: 0, width: 1, height: 1), format: .RGBA8, colorSpace: nil)
|
||||
//
|
||||
// return NSColor(red: CGFloat(bitmap[0]) / 255, green: CGFloat(bitmap[1]) / 255, blue: CGFloat(bitmap[2]) / 255, alpha: CGFloat(bitmap[3]) / 255)
|
||||
// }
|
||||
//}
|
||||
|
||||
extension NSImage {
|
||||
var averageColor: NSColor? {
|
||||
guard let tiffData = self.tiffRepresentation, let bitmapImage = NSBitmapImageRep(data: tiffData), let inputImage = CIImage(bitmapImageRep: bitmapImage) else { return nil }
|
||||
@@ -279,13 +309,10 @@ func removeApp(appState: AppState, withId id: UUID) {
|
||||
appState.sortedApps.remove(at: index)
|
||||
return // Exit the function if the app was found and removed
|
||||
}
|
||||
|
||||
// Remove from appInfoStore if found
|
||||
if let index = appState.appInfoStore.firstIndex(where: { $0.id == id }) {
|
||||
appState.appInfoStore.remove(at: index)
|
||||
}
|
||||
// Clear out AppInfo state
|
||||
appState.appInfo = AppInfo.empty
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ struct PearcleanerApp: App {
|
||||
@AppStorage("settings.general.miniview") private var miniView: Bool = true
|
||||
@AppStorage("settings.general.instant") private var instantSearch: Bool = true
|
||||
@AppStorage("settings.general.features") private var features: String = ""
|
||||
@AppStorage("settings.general.brew") private var brew: Bool = false
|
||||
@State private var search = ""
|
||||
@State private var showPopover: Bool = false
|
||||
@State private var showFeature: Bool = false
|
||||
@@ -94,14 +95,11 @@ struct PearcleanerApp: App {
|
||||
appState.sortedApps = sortedApps
|
||||
|
||||
|
||||
// Find all app paths on load
|
||||
// Find all app paths/information on load if instantSearch is enabled
|
||||
if instantSearch {
|
||||
// startEnd {
|
||||
loadAllPaths(allApps: sortedApps, appState: appState, locations: locations)
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
#if !DEBUG
|
||||
Task {
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ struct GeneralSettingsTab: View {
|
||||
@AppStorage("settings.general.sidebarWidth") private var sidebarWidth: Double = 280
|
||||
@AppStorage("displayMode") var displayMode: DisplayMode = .system
|
||||
@AppStorage("settings.sentinel.enable") private var sentinel: Bool = false
|
||||
@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"
|
||||
@State private var diskStatus: Bool = false
|
||||
@@ -82,6 +83,30 @@ struct GeneralSettingsTab: View {
|
||||
.padding(.leading)
|
||||
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Image(systemName: brew ? "mug.fill" : "mug")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 20, height: 20)
|
||||
.padding(.trailing)
|
||||
.foregroundStyle(.gray)
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("\(brew ? "Homebrew cleanup is enabled" : "Homebrew cleanup is disabled")")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.gray)
|
||||
}
|
||||
|
||||
InfoButton(text: "When homebrew cleanup is enabled, Pearcleaner will check if the app you are removing was installed via homebrew and execute a brew uninstall and brew cleanup command as well to let homebrew know that the app is removed. This way your homebrew list will be synced up correctly and caching will be removed.\n\nNOTE: If you undo the file delete with CMD+Z, the files will be put back but homebrew will not be aware of it. To get the homebrew list back in sync you'd need to run:\n brew install APPNAME --force", color: nil)
|
||||
|
||||
Spacer()
|
||||
Toggle(isOn: $brew, label: {
|
||||
})
|
||||
.toggleStyle(.switch)
|
||||
}
|
||||
.padding(5)
|
||||
.padding(.leading)
|
||||
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Image(systemName: displayMode.colorScheme == .dark ? "moon.fill" : "sun.max.fill")
|
||||
.resizable()
|
||||
@@ -346,7 +371,7 @@ struct GeneralSettingsTab: View {
|
||||
|
||||
}
|
||||
.padding(20)
|
||||
.frame(width: 500, height: 650)
|
||||
.frame(width: 500, height: 690)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import SwiftUI
|
||||
struct SettingsView: View {
|
||||
@EnvironmentObject var appState: AppState
|
||||
@Binding var showPopover: Bool
|
||||
@AppStorage("settings.general.glass") private var glass: Bool = true
|
||||
|
||||
var body: some View {
|
||||
|
||||
@@ -33,6 +34,8 @@ struct SettingsView: View {
|
||||
.tag(CurrentTabView.about)
|
||||
|
||||
}
|
||||
.background(glass ? GlassEffect(material: .sidebar, blendingMode: .behindWindow).edgesIgnoringSafeArea(.all) : nil)
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ struct FilesView: View {
|
||||
@AppStorage("settings.general.mini") private var mini: Bool = false
|
||||
@AppStorage("settings.sentinel.enable") private var sentinel: Bool = false
|
||||
@AppStorage("settings.general.instant") var instantSearch: Bool = true
|
||||
@AppStorage("settings.general.brew") private var brew: Bool = false
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
@Binding var showPopover: Bool
|
||||
@Binding var search: String
|
||||
@@ -216,12 +217,18 @@ struct FilesView: View {
|
||||
withAnimation {
|
||||
showPopover = false
|
||||
updateOnMain {
|
||||
appState.currentView = mini ? .apps : .empty
|
||||
appState.isReminderVisible.toggle()
|
||||
}
|
||||
}
|
||||
// Remove app from app list
|
||||
removeApp(appState: appState, withId: appState.appInfo.id)
|
||||
|
||||
// refreshAppList(appState.appInfo)
|
||||
// Brew cleanup if enabled
|
||||
if brew {
|
||||
caskCleanup(app: appState.appInfo.appName)
|
||||
}
|
||||
// Clear out AppInfo state
|
||||
appState.appInfo = AppInfo.empty
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ struct MiniAppView: View {
|
||||
AppsListView(search: $search, showPopover: $showPopover, filteredApps: filteredApps)
|
||||
|
||||
if appState.currentView != .empty {
|
||||
SearchBarMiniBottom(search: $search).background(.ultraThinMaterial)
|
||||
SearchBarMiniBottom(search: $search)
|
||||
}
|
||||
}
|
||||
.padding(.bottom)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{
|
||||
"3.1.0": "- Brew Cleanup: If you install apps using Homebrew, you can now enable brew cleanup in Pearcleaner settings to have it uninstall the app via brew as well to keep Homebrew synced up.",
|
||||
"3.0.0": "- Instant Search: Enable in settings to load app files on startup|- Semantic Versioning: Going forward will use semver (Ex. v0.0.0)|-Feature Alert: For each version, a feature alert will popup once on startup to show details|- Leftover File Cleaning: Search your mac for files leftover by uninstalled apps|- Sidebar Drag Handle: Resize the sidebar in regular mode|- Redesign UI/Settings/Icon: Some new buttons, layout changes, new official app icon and pear color theme accents|- File Sort: Sort files alphabetically or by size|- Socket File Removal: Finds socket files that aren't even visible in Finder with show hidden files enabled|- OSLog Output: Will print errors to the Console app for easier troubleshooting"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user