mirror of
https://github.com/exituser/Pearcleaner.git
synced 2026-09-17 10:48:52 +00:00
Updates
This commit is contained in:
@@ -15,6 +15,7 @@ struct AppCommands: Commands {
|
||||
let fsm: FolderSettingsManager
|
||||
let updater: Updater
|
||||
let themeManager: ThemeManager
|
||||
@AppStorage("settings.interface.animationEnabled") private var animationEnabled: Bool = true
|
||||
|
||||
init(appState: AppState, locations: Locations, fsm: FolderSettingsManager, updater: Updater, themeManager: ThemeManager) {
|
||||
self.appState = appState
|
||||
@@ -37,7 +38,7 @@ struct AppCommands: Commands {
|
||||
.keyboardShortcut("u", modifiers: .command)
|
||||
|
||||
Button {
|
||||
withAnimation(.easeInOut(duration: 0.5)) {
|
||||
withAnimation(Animation.easeInOut(duration: animationEnabled ? 0.35 : 0)) {
|
||||
reloadAppsList(appState: appState, fsm: fsm)
|
||||
}
|
||||
} label: {
|
||||
|
||||
@@ -110,6 +110,7 @@ func listAppSupportDirectories() -> [String] {
|
||||
|
||||
// Load app paths on launch
|
||||
func reversePreloader(allApps: [AppInfo], appState: AppState, locations: Locations, fsm: FolderSettingsManager, completion: @escaping () -> Void = {}) {
|
||||
@AppStorage("settings.interface.animationEnabled") var animationEnabled: Bool = true
|
||||
// appState.operationQueueLeftover.maxConcurrentOperationCount = 10 // Adjust this value as needed
|
||||
// appState.shouldCancelOperations = false
|
||||
// appState.appInfoStore.removeAll()
|
||||
@@ -122,7 +123,7 @@ func reversePreloader(allApps: [AppInfo], appState: AppState, locations: Locatio
|
||||
updateOnMain {
|
||||
printOS("Reverse search processed successfully")
|
||||
appState.showProgress = false
|
||||
withAnimation {
|
||||
withAnimation(Animation.easeInOut(duration: animationEnabled ? 0.35 : 0)) {
|
||||
appState.leftoverProgress.1 = 0.0
|
||||
}
|
||||
appState.leftoverProgress.0 = "Reverse search completed successfully"
|
||||
@@ -218,6 +219,8 @@ func reversePreloader(allApps: [AppInfo], appState: AppState, locations: Locatio
|
||||
|
||||
// Load item in Files view
|
||||
func showAppInFiles(appInfo: AppInfo, appState: AppState, locations: Locations, showPopover: Binding<Bool>) {
|
||||
@AppStorage("settings.interface.animationEnabled") var animationEnabled: Bool = true
|
||||
|
||||
showPopover.wrappedValue = false
|
||||
|
||||
updateOnMain {
|
||||
@@ -238,7 +241,7 @@ func showAppInFiles(appInfo: AppInfo, appState: AppState, locations: Locations,
|
||||
appState.appInfo = appInfo
|
||||
|
||||
// Animate the view change and popover display.
|
||||
withAnimation(Animation.easeIn(duration: 0.4)) {
|
||||
withAnimation(Animation.easeInOut(duration: animationEnabled ? 0.35 : 0)) {
|
||||
appState.currentView = .files
|
||||
showPopover.wrappedValue.toggle()
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ class ReversePathsSearcher {
|
||||
|
||||
guard !skipReverse.contains(where: { itemName.pearFormat().contains($0) }),
|
||||
isSupportedFileType(at: itemURL.path),
|
||||
!isRelatedToInstalledApp(itemPath: itemPath),
|
||||
!isRelatedToInstalledApp(itemPath: itemPath, itemPathOG: itemURL),
|
||||
!isExcludedByConditions(itemPath: itemPath) else {
|
||||
|
||||
return
|
||||
@@ -80,9 +80,9 @@ class ReversePathsSearcher {
|
||||
collection.append(itemURL)
|
||||
}
|
||||
|
||||
private func isRelatedToInstalledApp(itemPath: String) -> Bool {
|
||||
private func isRelatedToInstalledApp(itemPath: String, itemPathOG: URL) -> Bool {
|
||||
for app in sortedApps {
|
||||
if itemPath.contains(app.bundleIdentifier.pearFormat()) || itemPath.contains(app.appName.pearFormat()) {
|
||||
if itemPath.contains(app.bundleIdentifier.pearFormat()) || itemPath.contains(app.appName.pearFormat()) || itemPathOG.containerNameByUUID().pearFormat().contains(app.bundleIdentifier.pearFormat()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ struct ResetSettingsButtonStyle: ButtonStyle {
|
||||
let label: String
|
||||
let help: String
|
||||
@State private var hovered = false
|
||||
@AppStorage("settings.interface.animationEnabled") private var animationEnabled: Bool = true
|
||||
|
||||
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
HStack(alignment: .center) {
|
||||
@@ -35,7 +37,7 @@ struct ResetSettingsButtonStyle: ButtonStyle {
|
||||
.scaleEffect(configuration.isPressed ? 0.95 : 1)
|
||||
.animation(.easeOut(duration: 0.2), value: configuration.isPressed)
|
||||
.onHover { hovering in
|
||||
withAnimation(Animation.easeIn(duration: 0.15)) {
|
||||
withAnimation(Animation.easeInOut(duration: animationEnabled ? 0.35 : 0)) {
|
||||
hovered = hovering
|
||||
}
|
||||
}
|
||||
@@ -52,6 +54,7 @@ struct ResetSettingsButtonStyle: ButtonStyle {
|
||||
struct SimpleCheckboxToggleStyle: ToggleStyle {
|
||||
@EnvironmentObject private var themeManager: ThemeManager
|
||||
@State private var isHovered: Bool = false
|
||||
@AppStorage("settings.interface.animationEnabled") private var animationEnabled: Bool = true
|
||||
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
HStack {
|
||||
@@ -66,7 +69,7 @@ struct SimpleCheckboxToggleStyle: ToggleStyle {
|
||||
}
|
||||
}
|
||||
.onTapGesture {
|
||||
withAnimation(.smooth()) {
|
||||
withAnimation(Animation.easeInOut(duration: animationEnabled ? 0.35 : 0)) {
|
||||
configuration.isOn.toggle()
|
||||
}
|
||||
}
|
||||
@@ -240,6 +243,7 @@ struct GlassEffect: NSViewRepresentable {
|
||||
|
||||
|
||||
struct SimpleButtonBrightStyle: ButtonStyle {
|
||||
@AppStorage("settings.interface.animationEnabled") private var animationEnabled: Bool = true
|
||||
@State private var hovered = false
|
||||
let icon: String
|
||||
let label: String
|
||||
@@ -266,7 +270,7 @@ struct SimpleButtonBrightStyle: ButtonStyle {
|
||||
}
|
||||
.padding(5)
|
||||
.onHover { hovering in
|
||||
withAnimation() {
|
||||
withAnimation(Animation.easeInOut(duration: animationEnabled ? 0.35 : 0)) {
|
||||
hovered = hovering
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,6 @@ func saveURLsToFile(urls: Set<URL>, appState: AppState) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Open trash folder
|
||||
func openTrash() {
|
||||
if let trashURL = try? FileManager.default.url(for: .trashDirectory, in: .userDomainMask, appropriateFor: nil, create: false) {
|
||||
@@ -240,6 +239,83 @@ func showLocalized(url: URL) -> String {
|
||||
return url.lastPathComponent
|
||||
}
|
||||
|
||||
extension URL {
|
||||
func localizedName() -> String? {
|
||||
do {
|
||||
let resourceValues = try self.resourceValues(forKeys: [.localizedNameKey])
|
||||
return resourceValues.localizedName
|
||||
} catch {
|
||||
print("Error getting localized name: \(error)")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension String {
|
||||
func localizedName() -> String? {
|
||||
let url = URL(fileURLWithPath: self)
|
||||
do {
|
||||
let resourceValues = try url.resourceValues(forKeys: [.localizedNameKey])
|
||||
return resourceValues.localizedName
|
||||
} catch {
|
||||
print("Error getting localized name: \(error)")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension URL {
|
||||
/// Returns the bundle name of the container by its UUID if found.
|
||||
func containerNameByUUID() -> String {
|
||||
// Extract the last path component, which should be the UUID
|
||||
let uuid = self.lastPathComponent
|
||||
|
||||
// Ensure the UUID matches the expected pattern.
|
||||
let uuidRegex = try! NSRegularExpression(
|
||||
pattern: "^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$",
|
||||
options: .caseInsensitive
|
||||
)
|
||||
let range = NSRange(location: 0, length: uuid.utf16.count)
|
||||
guard uuidRegex.firstMatch(in: uuid, options: [], range: range) != nil else {
|
||||
// print("The URL does not point to a valid UUID container.")
|
||||
return ""
|
||||
}
|
||||
|
||||
// Path to the Containers directory.
|
||||
let containersPath = FileManager.default.homeDirectoryForCurrentUser
|
||||
.appendingPathComponent("Library/Containers")
|
||||
|
||||
do {
|
||||
// List all directories in the Containers folder.
|
||||
let containerDirectories = try FileManager.default.contentsOfDirectory(
|
||||
at: containersPath,
|
||||
includingPropertiesForKeys: nil,
|
||||
options: .skipsHiddenFiles
|
||||
)
|
||||
|
||||
// Iterate over each directory to find a match with the UUID.
|
||||
for directory in containerDirectories {
|
||||
let directoryName = directory.lastPathComponent
|
||||
|
||||
if directoryName == uuid {
|
||||
// Attempt to read the metadata plist file.
|
||||
let metadataPlistURL = directory.appendingPathComponent(".com.apple.containermanagerd.metadata.plist")
|
||||
|
||||
if let metadataDict = NSDictionary(contentsOf: metadataPlistURL),
|
||||
let applicationBundleID = metadataDict["MCMMetadataIdentifier"] as? String {
|
||||
return applicationBundleID
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
print("Error accessing the Containers directory: \(error)")
|
||||
}
|
||||
|
||||
// Return nil if no matching UUID is found.
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// Return image for different folders
|
||||
func folderImages(for path: String) -> AnyView? {
|
||||
if path.contains("/Library/Containers/") || path.contains("/Library/Group Containers/") {
|
||||
|
||||
Reference in New Issue
Block a user