mirror of
https://github.com/exituser/Pearcleaner.git
synced 2026-09-17 09:38:51 +00:00
v3.5.4
This commit is contained in:
@@ -177,7 +177,7 @@ class AppPathFinder {
|
||||
|
||||
|
||||
private func getAllContainers(bundleURL: URL) -> [URL] {
|
||||
var containers = [URL]()
|
||||
var containers: [URL] = []
|
||||
|
||||
// Extract bundle identifier from bundleURL
|
||||
let bundleIdentifier = Bundle(url: bundleURL)?.bundleIdentifier
|
||||
@@ -190,7 +190,9 @@ class AppPathFinder {
|
||||
|
||||
// Get the regular container URL for the extracted bundle identifier
|
||||
if let groupContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: containerBundleIdentifier) {
|
||||
containers.append(groupContainer)
|
||||
if FileManager.default.fileExists(atPath: groupContainer.path) {
|
||||
containers.append(groupContainer)
|
||||
}
|
||||
} else {
|
||||
printOS("Get Containers: Failed to retrieve container URL for bundle identifier: \(containerBundleIdentifier)")
|
||||
}
|
||||
@@ -221,23 +223,6 @@ class AppPathFinder {
|
||||
printOS("Error accessing the Containers directory: \(error)")
|
||||
}
|
||||
|
||||
|
||||
// let fileURL = URL(fileURLWithPath: "/Users/alin/Library/Containers/2792352D-95FE-43AE-947D-FF4BF31DE4E6")
|
||||
//
|
||||
// do {
|
||||
// // Retrieve the localized name
|
||||
// let resourceValues = try fileURL.resourceValues(forKeys: [.localizedNameKey])
|
||||
// if let localizedName = resourceValues.localizedName {
|
||||
// print("Localized Name: \(localizedName)")
|
||||
// } else {
|
||||
// print("Localized name not available.")
|
||||
// }
|
||||
// } catch {
|
||||
// print("Error retrieving localized name: \(error)")
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// Return all found containers
|
||||
return containers
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ class AppState: ObservableObject
|
||||
@Published var currentView = CurrentDetailsView.empty
|
||||
@Published var showAlert: Bool = false
|
||||
@Published var sidebar: Bool = true
|
||||
@Published var isReminderVisible: Bool = false
|
||||
// @Published var isReminderVisible: Bool = false
|
||||
@Published var releases = [Release]()
|
||||
@Published var progressBar: (String, Double) = ("Ready", 0.0)
|
||||
@Published var reload: Bool = false
|
||||
@@ -55,6 +55,7 @@ class AppState: ObservableObject
|
||||
fileSizeLogical: [:],
|
||||
fileIcon: [:]
|
||||
)
|
||||
|
||||
updateExtensionStatus()
|
||||
NotificationCenter.default.addObserver(
|
||||
self,
|
||||
@@ -66,9 +67,9 @@ class AppState: ObservableObject
|
||||
}
|
||||
|
||||
@objc func updateExtensionStatus() {
|
||||
let extentionStatus = FIFinderSyncController.isExtensionEnabled
|
||||
let extensionStatus = FIFinderSyncController.isExtensionEnabled
|
||||
DispatchQueue.main.async {
|
||||
self.finderExtensionEnabled = extentionStatus
|
||||
self.finderExtensionEnabled = extensionStatus
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,80 @@ struct SimpleButtonStyle: ButtonStyle {
|
||||
}
|
||||
|
||||
|
||||
struct RegularButtonStyle: ButtonStyle {
|
||||
let icon: String
|
||||
let label: String
|
||||
let help: String
|
||||
@State private var hovered = false
|
||||
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
|
||||
HStack(alignment: .center) {
|
||||
Image(systemName: icon).foregroundColor(Color("mode")).padding(.leading, 2).padding(.trailing, 0)
|
||||
Text(label).textCase(.uppercase).foregroundColor(Color("mode")).fontWeight(.bold).padding(.trailing, 2)
|
||||
|
||||
}
|
||||
.padding(8)
|
||||
.background(!configuration.isPressed ? hovered ? Color("mode").opacity(0.4) : Color("mode").opacity(0) : Color("mode").opacity(0.5))
|
||||
.cornerRadius(6)
|
||||
.scaleEffect(configuration.isPressed ? 0.95 : 1)
|
||||
.animation(.easeOut(duration: 0.2), value: configuration.isPressed)
|
||||
.onHover { hovering in
|
||||
withAnimation(Animation.easeIn(duration: 0.15)) {
|
||||
hovered = hovering
|
||||
}
|
||||
}
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 6)
|
||||
.strokeBorder(Color("mode").opacity(0.5), lineWidth: 1)
|
||||
.scaleEffect(configuration.isPressed ? 0.95 : 1)
|
||||
)
|
||||
.help(help)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct ResetSettingsButtonStyle: ButtonStyle {
|
||||
@Binding var isResetting: Bool
|
||||
let label: String
|
||||
let help: String
|
||||
@State private var hovered = false
|
||||
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
HStack(alignment: .center) {
|
||||
if isResetting {
|
||||
ProgressView()
|
||||
.progressViewStyle(CircularProgressViewStyle())
|
||||
.controlSize(.small)
|
||||
.frame(width: 15)
|
||||
} else {
|
||||
Image(systemName: "gear")
|
||||
.foregroundColor(Color("mode")).padding(.leading, 2).padding(.trailing, 0)
|
||||
}
|
||||
Text(label)
|
||||
.textCase(.uppercase).foregroundColor(Color("mode")).fontWeight(.bold).padding(.trailing, 2)
|
||||
}
|
||||
.padding(8)
|
||||
.background(!configuration.isPressed ? hovered ? Color("mode").opacity(0.4) : Color("mode").opacity(0) : Color("mode").opacity(0.5))
|
||||
.cornerRadius(6)
|
||||
.scaleEffect(configuration.isPressed ? 0.95 : 1)
|
||||
.animation(.easeOut(duration: 0.2), value: configuration.isPressed)
|
||||
.onHover { hovering in
|
||||
withAnimation(Animation.easeIn(duration: 0.15)) {
|
||||
hovered = hovering
|
||||
}
|
||||
}
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 6)
|
||||
.strokeBorder(Color("mode").opacity(0.5), lineWidth: 1)
|
||||
.scaleEffect(configuration.isPressed ? 0.95 : 1)
|
||||
)
|
||||
.help(help)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct InfoButton: View {
|
||||
@State private var isPopoverPresented: Bool = false
|
||||
@@ -769,7 +843,6 @@ func backgroundView(themeSettings: ThemeSettings, darker: Bool = false, glass: B
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct PresetColor: ButtonStyle {
|
||||
var fillColor: Color
|
||||
var label: String
|
||||
|
||||
@@ -22,13 +22,13 @@ class ThemeSettings: ObservableObject {
|
||||
|
||||
// light - Color(.sRGB, red: 1.0, green: 1.0, blue: 1.0, opacity: 1)
|
||||
// dark - Color(.sRGB, red: 0.149, green: 0.149, blue: 0.149, opacity: 1)
|
||||
// slate - Color(.sRGB, red: 0.188143, green: 0.208556, blue: 0.262679, opacity: 1)
|
||||
|
||||
init() {
|
||||
// Initialize color from UserDefaults or use a default value
|
||||
if let components = UserDefaults.standard.object(forKey: colorKey) as? [CGFloat], components.count >= 4 {
|
||||
themeColor = Color(.sRGB, red: components[0], green: components[1], blue: components[2], opacity: components[3])
|
||||
} else {
|
||||
|
||||
themeColor = Color.clear
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,8 @@ class ThemeSettings: ObservableObject {
|
||||
}
|
||||
|
||||
func resetToDefault(dark: Bool = true) {
|
||||
themeColor = dark ? Color(.sRGB, red: 0.149, green: 0.149, blue: 0.149, opacity: 1) : Color(.sRGB, red: 1.0, green: 1.0, blue: 1.0, opacity: 1)
|
||||
themeColor = dark ? Color(.sRGB, red: 0.188143, green: 0.208556, blue: 0.262679, opacity: 1) : Color(.sRGB, red: 1.0, green: 1.0, blue: 1.0, opacity: 1)
|
||||
// themeColor = dark ? Color(.sRGB, red: 0.149, green: 0.149, blue: 0.149, opacity: 1) : Color(.sRGB, red: 1.0, green: 1.0, blue: 1.0, opacity: 1)
|
||||
saveThemeColor()
|
||||
}
|
||||
|
||||
@@ -55,6 +56,7 @@ class ThemeSettings: ObservableObject {
|
||||
let slate = colorScheme.colorScheme == .light ? Color(.sRGB, red: 0.499549, green: 0.545169, blue: 0.682028, opacity: 1) : Color(.sRGB, red: 0.188143, green: 0.208556, blue: 0.262679, opacity: 1)
|
||||
let solarized = colorScheme.colorScheme == .light ? Color(.sRGB, red: 0.554372, green: 0.6557, blue: 0.734336, opacity: 1) : Color(.sRGB, red: 0.117257, green: 0.22506, blue: 0.249171, opacity: 1)
|
||||
let dracula = colorScheme.colorScheme == .light ? Color(.sRGB, red: 0.567094, green: 0.562125, blue: 0.81285, opacity: 1) : Color(.sRGB, red: 0.268614, green: 0.264737, blue: 0.383503, opacity: 1)
|
||||
let macOS = colorScheme.colorScheme == .light ? Color(.sRGB, red: 1.0, green: 1.0, blue: 1.0, opacity: 1) : Color(.sRGB, red: 0.149, green: 0.149, blue: 0.149, opacity: 1)
|
||||
|
||||
switch preset {
|
||||
case "slate":
|
||||
@@ -63,6 +65,8 @@ class ThemeSettings: ObservableObject {
|
||||
return solarized
|
||||
case "dracula":
|
||||
return dracula
|
||||
case "macOS":
|
||||
return macOS
|
||||
default:
|
||||
return themeColor
|
||||
}
|
||||
|
||||
@@ -312,17 +312,14 @@ func convertICNSToPNG(icon: NSImage, size: NSSize) -> NSImage? {
|
||||
|
||||
// Get icon for files and folders
|
||||
func getIconForFileOrFolder(atPath path: URL) -> Image? {
|
||||
let icon = NSWorkspace.shared.icon(forFile: path.path)
|
||||
let nsImage = icon
|
||||
return Image(nsImage: nsImage)
|
||||
return Image(nsImage: NSWorkspace.shared.icon(forFile: path.path))
|
||||
}
|
||||
|
||||
func getIconForFileOrFolderNS(atPath path: URL) -> NSImage? {
|
||||
let icon = NSWorkspace.shared.icon(forFile: path.path)
|
||||
let nsImage = icon
|
||||
return nsImage
|
||||
return NSWorkspace.shared.icon(forFile: path.path)
|
||||
}
|
||||
|
||||
|
||||
// Get average color from image
|
||||
extension NSImage {
|
||||
var averageColor: NSColor? {
|
||||
@@ -393,6 +390,60 @@ func removeApp(appState: AppState, withId id: UUID) {
|
||||
}
|
||||
|
||||
|
||||
// Check if file/folder name has localized variant
|
||||
func showLocalized(url: URL) -> String {
|
||||
guard FileManager.default.fileExists(atPath: url.path) else {
|
||||
return url.lastPathComponent
|
||||
}
|
||||
do {
|
||||
// Retrieve the localized name
|
||||
let resourceValues = try url.resourceValues(forKeys: [.localizedNameKey])
|
||||
if let localizedName = resourceValues.localizedName {
|
||||
return localizedName
|
||||
}
|
||||
} catch {
|
||||
printOS("Error retrieving localized name: \(error)")
|
||||
}
|
||||
// Return the last path component as a fallback
|
||||
return url.lastPathComponent
|
||||
}
|
||||
|
||||
// Return image for different folders
|
||||
func folderImages(for path: String) -> AnyView? {
|
||||
if path.contains("/Library/Containers/") || path.contains("/Library/Group Containers/") {
|
||||
return AnyView(
|
||||
Image(systemName: "shippingbox.fill")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 13)
|
||||
.foregroundStyle(Color("mode").opacity(0.5))
|
||||
.help("Container")
|
||||
)
|
||||
} else if path.contains("/Library/Application Scripts/") {
|
||||
return AnyView(
|
||||
Image(systemName: "applescript.fill")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 13)
|
||||
.foregroundStyle(Color("mode").opacity(0.5))
|
||||
.help("Application Script")
|
||||
)
|
||||
} else if path.contains(".plist") {
|
||||
return AnyView(
|
||||
Image(systemName: "doc.badge.gearshape.fill")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 13)
|
||||
.foregroundStyle(Color("mode").opacity(0.5))
|
||||
.help("Plist File")
|
||||
)
|
||||
}
|
||||
|
||||
// Return nil if no conditions are met
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
// Check if app bundle is nested
|
||||
func isNested(path: URL) -> Bool {
|
||||
let applicationsPath = "/Applications"
|
||||
|
||||
Reference in New Issue
Block a user