mirror of
https://github.com/exituser/Pearcleaner.git
synced 2026-09-17 04:58:56 +00:00
3.3.4
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
C71848442B8D2D600046CB13 /* ZombieView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C71848432B8D2D600046CB13 /* ZombieView.swift */; };
|
||||
C72893052AFD42E600C8C1CD /* DeepLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = C72893042AFD42E600C8C1CD /* DeepLink.swift */; };
|
||||
C72893122AFD51EA00C8C1CD /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = C72893112AFD51EA00C8C1CD /* main.swift */; };
|
||||
C74412C72BBF249000DDFCA8 /* AppPathsFetch.swift in Sources */ = {isa = PBXBuildFile; fileRef = C74412C62BBF249000DDFCA8 /* AppPathsFetch.swift */; };
|
||||
C7575D392B0182DE006A600A /* PearcleanerSentinel in CopyFiles */ = {isa = PBXBuildFile; fileRef = C728930F2AFD51EA00C8C1CD /* PearcleanerSentinel */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
C76D08482AF83C3F00D07867 /* Update.swift in Sources */ = {isa = PBXBuildFile; fileRef = C76D08472AF83C3F00D07867 /* Update.swift */; };
|
||||
C76D084A2AF83C6E00D07867 /* General.swift in Sources */ = {isa = PBXBuildFile; fileRef = C76D08492AF83C6E00D07867 /* General.swift */; };
|
||||
@@ -38,7 +39,6 @@
|
||||
C7D31D512AFF00F300C7ED9E /* Locations.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7D31D502AFF00F300C7ED9E /* Locations.swift */; };
|
||||
C7DC1FEE2B9F7D3D009AC317 /* features.json in Resources */ = {isa = PBXBuildFile; fileRef = C7DC1FED2B9F7D3D009AC317 /* features.json */; };
|
||||
C7DD49EA2BAB4D8100CCBA16 /* AppInfoFetch.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7DD49E92BAB4D8100CCBA16 /* AppInfoFetch.swift */; };
|
||||
C7DD49EC2BAB58AA00CCBA16 /* AppPathsFetch.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7DD49EB2BAB58AA00CCBA16 /* AppPathsFetch.swift */; };
|
||||
C7DD49EE2BAB7F6000CCBA16 /* ReversePathsFetch.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7DD49ED2BAB7F6000CCBA16 /* ReversePathsFetch.swift */; };
|
||||
C7DD49F02BABA14400CCBA16 /* Folders.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7DD49EF2BABA14400CCBA16 /* Folders.swift */; };
|
||||
C7DE672B2BA6343D00EB1633 /* MenuBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7DE672A2BA6343D00EB1633 /* MenuBarItem.swift */; };
|
||||
@@ -81,6 +81,7 @@
|
||||
C72893042AFD42E600C8C1CD /* DeepLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeepLink.swift; sourceTree = "<group>"; };
|
||||
C728930F2AFD51EA00C8C1CD /* PearcleanerSentinel */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = PearcleanerSentinel; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C72893112AFD51EA00C8C1CD /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
|
||||
C74412C62BBF249000DDFCA8 /* AppPathsFetch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppPathsFetch.swift; sourceTree = "<group>"; };
|
||||
C76D08472AF83C3F00D07867 /* Update.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Update.swift; sourceTree = "<group>"; };
|
||||
C76D08492AF83C6E00D07867 /* General.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = General.swift; sourceTree = "<group>"; };
|
||||
C76D08502AF850F300D07867 /* About.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = About.swift; sourceTree = "<group>"; };
|
||||
@@ -106,7 +107,6 @@
|
||||
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; };
|
||||
C7DD49E92BAB4D8100CCBA16 /* AppInfoFetch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppInfoFetch.swift; sourceTree = "<group>"; };
|
||||
C7DD49EB2BAB58AA00CCBA16 /* AppPathsFetch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppPathsFetch.swift; sourceTree = "<group>"; };
|
||||
C7DD49ED2BAB7F6000CCBA16 /* ReversePathsFetch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReversePathsFetch.swift; sourceTree = "<group>"; };
|
||||
C7DD49EF2BABA14400CCBA16 /* Folders.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Folders.swift; sourceTree = "<group>"; };
|
||||
C7DE672A2BA6343D00EB1633 /* MenuBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuBarItem.swift; sourceTree = "<group>"; };
|
||||
@@ -153,7 +153,7 @@
|
||||
children = (
|
||||
C77B90192AF1938F009CC655 /* Logic.swift */,
|
||||
C7DD49E92BAB4D8100CCBA16 /* AppInfoFetch.swift */,
|
||||
C7DD49EB2BAB58AA00CCBA16 /* AppPathsFetch.swift */,
|
||||
C74412C62BBF249000DDFCA8 /* AppPathsFetch.swift */,
|
||||
C7DD49ED2BAB7F6000CCBA16 /* ReversePathsFetch.swift */,
|
||||
C77B90172AF19382009CC655 /* AppCommands.swift */,
|
||||
C77B90152AF19377009CC655 /* AppState.swift */,
|
||||
@@ -392,8 +392,8 @@
|
||||
C77B90182AF19382009CC655 /* AppCommands.swift in Sources */,
|
||||
C7D31D4A2AFEB26700C7ED9E /* AppListItems.swift in Sources */,
|
||||
C77B901E2AF1A9DB009CC655 /* SettingsWindow.swift in Sources */,
|
||||
C74412C72BBF249000DDFCA8 /* AppPathsFetch.swift in Sources */,
|
||||
C7D31D482AFEB23700C7ED9E /* TopBar.swift in Sources */,
|
||||
C7DD49EC2BAB58AA00CCBA16 /* AppPathsFetch.swift in Sources */,
|
||||
C7ACADE62B92A737000B5845 /* Features.swift in Sources */,
|
||||
C7F539382AF60865007DF1B2 /* Utilities.swift in Sources */,
|
||||
C76D08552AF89CDE00D07867 /* RegularMode.swift in Sources */,
|
||||
@@ -575,7 +575,7 @@
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 28;
|
||||
CURRENT_PROJECT_VERSION = 30;
|
||||
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.2;
|
||||
MARKETING_VERSION = 3.3.4;
|
||||
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 = 28;
|
||||
CURRENT_PROJECT_VERSION = 30;
|
||||
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.2;
|
||||
MARKETING_VERSION = 3.3.4;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.alienator88.Pearcleaner;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
|
||||
@@ -46,9 +46,11 @@ class AppInfoFetcher {
|
||||
return nil
|
||||
}
|
||||
|
||||
let appName = bundle.localizedInfoDictionary?[kCFBundleNameKey as String] as? String
|
||||
?? bundle.infoDictionary?["CFBundleName"] as? String
|
||||
?? path.deletingPathExtension().lastPathComponent
|
||||
// let appName = bundle.localizedInfoDictionary?[kCFBundleNameKey as String] as? String
|
||||
// ?? bundle.infoDictionary?["CFBundleName"] as? String
|
||||
// ?? path.deletingPathExtension().lastPathComponent
|
||||
|
||||
let appName = path.deletingPathExtension().lastPathComponent.capitalized
|
||||
|
||||
let appVersion = bundle.infoDictionary?["CFBundleShortVersionString"] as? String
|
||||
?? bundle.infoDictionary?["CFBundleVersion"] as? String
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
//
|
||||
// AppPathsFetch.swift
|
||||
// AppPathsFetch-NEW.swift
|
||||
// Pearcleaner
|
||||
//
|
||||
// Created by Alin Lupascu on 3/20/24.
|
||||
// Created by Alin Lupascu on 4/4/24.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
@@ -14,35 +14,27 @@ class AppPathFinder {
|
||||
private var appState: AppState
|
||||
private var locations: Locations
|
||||
private var backgroundRun: Bool
|
||||
private var reverseAddon: Bool
|
||||
private var completion: () -> Void = {}
|
||||
private var collection: [URL] = []
|
||||
private let collectionAccessQueue = DispatchQueue(label: "com.alienator88.Pearcleaner.appPathFinder.collectionAccess")
|
||||
@AppStorage("settings.general.instant") var instantSearch: Bool = true
|
||||
|
||||
init(appInfo: AppInfo = .empty, appState: AppState, locations: Locations, backgroundRun: Bool = false, completion: @escaping () -> Void = {}) {
|
||||
init(appInfo: AppInfo = .empty, appState: AppState, locations: Locations, backgroundRun: Bool = false, reverseAddon: Bool = false, completion: @escaping () -> Void = {}) {
|
||||
self.appInfo = appInfo
|
||||
self.appState = appState
|
||||
self.locations = locations
|
||||
self.backgroundRun = backgroundRun
|
||||
self.reverseAddon = reverseAddon
|
||||
self.completion = completion
|
||||
}
|
||||
|
||||
func findPaths() {
|
||||
Task(priority: .background) {
|
||||
self.initialURLProcessing()
|
||||
let dispatchGroup = DispatchGroup()
|
||||
|
||||
for location in self.locations.apps.paths {
|
||||
dispatchGroup.enter()
|
||||
DispatchQueue.global(qos: .userInitiated).async {
|
||||
self.processLocation(location, with: dispatchGroup)
|
||||
dispatchGroup.leave()
|
||||
}
|
||||
}
|
||||
|
||||
dispatchGroup.notify(queue: .main) {
|
||||
self.finalizeCollection()
|
||||
}
|
||||
self.collectDirectories()
|
||||
self.collectFiles()
|
||||
self.finalizeCollection()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,33 +45,93 @@ class AppPathFinder {
|
||||
}
|
||||
}
|
||||
|
||||
private func processLocation(_ location: String, with dispatchGroup: DispatchGroup) {
|
||||
// Check if the directory exists before attempting to read its contents
|
||||
if FileManager.default.fileExists(atPath: location) {
|
||||
do {
|
||||
let contents = try FileManager.default.contentsOfDirectory(atPath: location)
|
||||
private func collectDirectories() {
|
||||
let dispatchGroup = DispatchGroup()
|
||||
|
||||
for item in contents {
|
||||
let itemURL = URL(fileURLWithPath: location).appendingPathComponent(item)
|
||||
let itemL = item.replacingOccurrences(of: ".", with: "").replacingOccurrences(of: " ", with: "").lowercased()
|
||||
for location in self.locations.apps.paths {
|
||||
dispatchGroup.enter()
|
||||
DispatchQueue.global(qos: .userInitiated).async {
|
||||
self.processDirectoryLocation(location)
|
||||
dispatchGroup.leave()
|
||||
}
|
||||
}
|
||||
|
||||
if shouldSkipItem(itemL, at: itemURL) { continue }
|
||||
dispatchGroup.wait()
|
||||
}
|
||||
|
||||
if specificCondition(itemL: itemL, itemURL: itemURL) {
|
||||
collectionAccessQueue.async {
|
||||
private func processDirectoryLocation(_ location: String) {
|
||||
if let contents = try? FileManager.default.contentsOfDirectory(atPath: location) {
|
||||
for item in contents {
|
||||
let itemURL = URL(fileURLWithPath: location).appendingPathComponent(item)
|
||||
let itemL = item.replacingOccurrences(of: ".", with: "").replacingOccurrences(of: " ", with: "").lowercased()
|
||||
|
||||
var isDirectory: ObjCBool = false
|
||||
if FileManager.default.fileExists(atPath: itemURL.path, isDirectory: &isDirectory), isDirectory.boolValue {
|
||||
// Perform the check to skip the item if needed
|
||||
if shouldSkipItem(itemL, at: itemURL) {
|
||||
continue
|
||||
}
|
||||
|
||||
collectionAccessQueue.sync {
|
||||
let alreadyIncluded = self.collection.contains { existingURL in
|
||||
itemURL.path.hasPrefix(existingURL.path)
|
||||
}
|
||||
|
||||
if !alreadyIncluded && specificCondition(itemL: itemL, itemURL: itemURL) {
|
||||
self.collection.append(itemURL)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// If an error occurs while trying to read the directory's contents, log or handle it here if needed
|
||||
printOS("Error processing location: \(location), \(error)")
|
||||
// if FileManager.default.fileExists(atPath: itemURL.path, isDirectory: &isDirectory),
|
||||
// isDirectory.boolValue,
|
||||
// !shouldSkipItem(itemL, at: itemURL),
|
||||
// specificCondition(itemL: itemL, itemURL: itemURL) {
|
||||
// collectionAccessQueue.sync {
|
||||
// self.collection.append(itemURL)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
} else {
|
||||
// The directory does not exist; skip it
|
||||
}
|
||||
}
|
||||
|
||||
private func collectFiles() {
|
||||
let dispatchGroup = DispatchGroup()
|
||||
|
||||
for location in self.locations.apps.paths {
|
||||
dispatchGroup.enter()
|
||||
DispatchQueue.global(qos: .userInitiated).async {
|
||||
self.processFileLocation(location)
|
||||
dispatchGroup.leave()
|
||||
}
|
||||
}
|
||||
|
||||
dispatchGroup.wait()
|
||||
}
|
||||
|
||||
private func processFileLocation(_ location: String) {
|
||||
if let contents = try? FileManager.default.contentsOfDirectory(atPath: location) {
|
||||
for item in contents {
|
||||
let itemURL = URL(fileURLWithPath: location).appendingPathComponent(item)
|
||||
let itemL = item.replacingOccurrences(of: ".", with: "").replacingOccurrences(of: " ", with: "").lowercased()
|
||||
|
||||
var isDirectory: ObjCBool = false
|
||||
if FileManager.default.fileExists(atPath: itemURL.path, isDirectory: &isDirectory),
|
||||
!isDirectory.boolValue,
|
||||
!shouldSkipItem(itemL, at: itemURL),
|
||||
specificCondition(itemL: itemL, itemURL: itemURL) {
|
||||
collectionAccessQueue.sync {
|
||||
let parentDirectory = itemURL.deletingLastPathComponent()
|
||||
if !self.collection.contains(parentDirectory) {
|
||||
self.collection.append(itemURL)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private func shouldSkipItem(_ itemL: String, at itemURL: URL) -> Bool {
|
||||
var containsItem = false
|
||||
collectionAccessQueue.sync {
|
||||
@@ -88,6 +140,10 @@ class AppPathFinder {
|
||||
return itemL.hasPrefix("comapple") && !["comappleconfigurator", "comappledt", "comappleiwork"].contains(where: itemL.hasPrefix) || containsItem || !isSupportedFileType(at: itemURL.path)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private func specificCondition(itemL: String, itemURL: URL) -> Bool {
|
||||
let bundleIdentifierL = self.appInfo.bundleIdentifier.pearFormat()
|
||||
let bundleComponents = self.appInfo.bundleIdentifier.components(separatedBy: ".").compactMap { $0 != "-" ? $0.lowercased() : nil }
|
||||
@@ -95,44 +151,57 @@ class AppPathFinder {
|
||||
let nameL = self.appInfo.appName.pearFormat()
|
||||
let nameP = self.appInfo.path.lastPathComponent.replacingOccurrences(of: ".app", with: "")
|
||||
|
||||
let exclusions = [
|
||||
"comappledtxcode": ["comrobotsandpencilsxcodesapp", "comoneminutegamesxcodecleaner", "iohyperappxcodecleaner", "xcodesjson"],
|
||||
"comrobotsandpencilsxcodesapp": ["comappledtxcode", "comoneminutegamesxcodecleaner", "iohyperappxcodecleaner"],
|
||||
"iohyperappxcodecleaner": ["comrobotsandpencilsxcodesapp", "comoneminutegamesxcodecleaner", "comappledtxcode", "xcodesjson"]
|
||||
]
|
||||
|
||||
if let excludedApps = exclusions[bundleIdentifierL], excludedApps.contains(where: { itemL.contains($0) }) {
|
||||
return false
|
||||
}
|
||||
|
||||
if bundleIdentifierL.contains("comappledtxcode") {
|
||||
// Include items that are part of the Xcode ecosystem
|
||||
if itemL.contains("comappledt") || itemL.contains("xcode") || itemL.contains("simulator") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if bundleIdentifierL.contains("uszoomxos") {
|
||||
// Include items for Zoom that are not similar to the app name and/or bundle id
|
||||
if itemL.contains("zoom") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if bundleIdentifierL.contains("combravebrowser") {
|
||||
// Include items for Zoom that are not similar to the app name and/or bundle id
|
||||
if itemL.contains("bravesoftware") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if bundleIdentifierL.contains("comlogioptionsplus") {
|
||||
// Include items for Zoom that are not similar to the app name and/or bundle id
|
||||
if itemL.contains("logi") && !itemL.contains("login") && !itemL.contains("logic") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if bundleIdentifierL.contains("commicrosoftvscode") {
|
||||
// Include items for vscode
|
||||
if itemL.contains("vscode") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if self.appInfo.webApp {
|
||||
return itemL.contains(bundleIdentifierL)
|
||||
} else {
|
||||
if itemL.contains("xcode") && bundleIdentifierL.contains("comappledt") {
|
||||
return !(itemURL.path.contains("comrobotsandpencilsxcodesapp") || itemURL.path.contains("comoneminutegamesxcodecleaner") || itemURL.path.contains("iohyperappxcodecleaner") || itemURL.path.contains("xcodesjson")) && (itemL.contains(bundle) || itemL.contains(bundleIdentifierL) || (nameL.count < 6 && itemL.contains(nameL)))
|
||||
} else if itemL.contains("xcodes") && bundleIdentifierL.contains("comrobotsandpencilsxcodesapp") {
|
||||
return !(itemURL.path.contains("comappledt")) && (itemL.contains(bundle) || itemL.contains(bundleIdentifierL) || (nameL.count > 4 && itemL.contains(nameL)))
|
||||
} else {
|
||||
return itemL.contains(bundleIdentifierL) || itemL.contains(bundle) || (nameL.count > 3 && itemL.contains(nameL)) || (nameP.count > 3 && itemL.contains(nameP))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private func filterParentDirectories(in collection: [URL]) -> [URL] {
|
||||
// Normalize URLs by removing percent encoding and trailing slashes for accurate comparison
|
||||
var filteredURLs: [URL] = []
|
||||
let normalizedURLs = collection.map { url -> URL in
|
||||
let path = url.path.removingPercentEncoding?.trimmingCharacters(in: CharacterSet(charactersIn: "/")) ?? ""
|
||||
return URL(fileURLWithPath: path)
|
||||
}
|
||||
|
||||
for url in normalizedURLs {
|
||||
// Determine if 'url' is a parent of any path in 'filteredURLs'
|
||||
if !filteredURLs.contains(where: { $0.absoluteString.hasPrefix(url.absoluteString) }) {
|
||||
filteredURLs.append(url)
|
||||
}
|
||||
}
|
||||
return itemL.contains(bundleIdentifierL) || itemL.contains(bundle) || (nameL.count > 3 && itemL.contains(nameL)) || (nameP.count > 3 && itemL.contains(nameP))
|
||||
|
||||
// Remove URLs that are parents of another URL in the list
|
||||
filteredURLs = filteredURLs.filter { parentUrl in
|
||||
!filteredURLs.contains { childUrl in
|
||||
childUrl != parentUrl && childUrl.absoluteString.hasPrefix(parentUrl.absoluteString)
|
||||
}
|
||||
}
|
||||
|
||||
return filteredURLs
|
||||
}
|
||||
|
||||
|
||||
@@ -166,20 +235,44 @@ class AppPathFinder {
|
||||
return existingGroupContainers
|
||||
}
|
||||
|
||||
|
||||
private func handleOutliers() -> [URL] {
|
||||
var outliers: [URL] = []
|
||||
|
||||
// Handle VSCode folder
|
||||
if self.appInfo.bundleIdentifier.pearFormat().contains("commicrosoftvscode") {
|
||||
let appSupportCodePath = "\(home)/Library/Application Support/Code"
|
||||
if let codeDirectoryURL = URL(string: appSupportCodePath), FileManager.default.fileExists(atPath: codeDirectoryURL.path) {
|
||||
outliers.append(codeDirectoryURL)
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Xcode folder
|
||||
if self.appInfo.bundleIdentifier.pearFormat().contains("comappledtxcode") {
|
||||
let simulators = "\(home)/Library/Containers/com.apple.iphonesimulator.ShareExtension"
|
||||
if let simulatorsURL = URL(string: simulators), FileManager.default.fileExists(atPath: simulatorsURL.path) {
|
||||
outliers.append(simulatorsURL)
|
||||
}
|
||||
}
|
||||
|
||||
// Add other outlier cases here as needed
|
||||
|
||||
return outliers
|
||||
}
|
||||
|
||||
private func finalizeCollection() {
|
||||
DispatchQueue.global(qos: .userInitiated).async {
|
||||
let groupContainers = self.getGroupContainers(bundleURL: self.appInfo.path)
|
||||
let outliers = self.handleOutliers()
|
||||
var tempCollection: [URL] = []
|
||||
self.collectionAccessQueue.sync {
|
||||
tempCollection = self.collection
|
||||
}
|
||||
tempCollection.append(contentsOf: groupContainers)
|
||||
tempCollection.append(contentsOf: outliers)
|
||||
|
||||
// Apply the filter to remove parent directories
|
||||
let filteredCollection = self.filterParentDirectories(in: tempCollection)
|
||||
|
||||
// Continue with the sorted collection
|
||||
let sortedCollection = filteredCollection.sorted(by: { $0.absoluteString < $1.absoluteString })
|
||||
let sortedCollection = tempCollection.sorted(by: { $0.absoluteString < $1.absoluteString })
|
||||
self.handlePostProcessing(sortedCollection: sortedCollection)
|
||||
}
|
||||
|
||||
@@ -217,11 +310,12 @@ class AppPathFinder {
|
||||
self.appState.instantProgress += 1
|
||||
}
|
||||
|
||||
// Append object to store if running reverse search with empty store
|
||||
if self.reverseAddon {
|
||||
self.appState.appInfoStore.append(self.appInfo)
|
||||
}
|
||||
|
||||
self.completion()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//assert(!Thread.isMainThread, "This method should not run on the main thread")
|
||||
|
||||
@@ -123,30 +123,41 @@ func loadAllPaths(allApps: [AppInfo], appState: AppState, locations: Locations,
|
||||
for app in allApps {
|
||||
dispatchGroup.enter()
|
||||
DispatchQueue.global(qos: .background).async {
|
||||
let pathFinder = AppPathFinder(appInfo: app, appState: appState, locations: locations, backgroundRun: true)
|
||||
let pathFinder = AppPathFinder(appInfo: app, appState: appState, locations: locations, backgroundRun: true, reverseAddon: reverseAddon)
|
||||
pathFinder.findPaths()
|
||||
dispatchGroup.leave()
|
||||
}
|
||||
}
|
||||
|
||||
DispatchQueue.global(qos: .background).async {
|
||||
_ = dispatchGroup.wait(timeout: .now() + 60)
|
||||
dispatchGroup.notify(queue: DispatchQueue.global(qos: .background)) {
|
||||
|
||||
func checkAllAppsProcessed(retryCount: Int = 0, maxRetry: Int = 120) {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
if appState.appInfoStore.count == allApps.count {
|
||||
if reverseAddon {
|
||||
let reverse = ReversePathsSearcher(appState: appState, locations: locations)
|
||||
reverse.reversePathsSearch()
|
||||
reverse.reversePathsSearch() {
|
||||
updateOnMain {
|
||||
appState.showProgress = false
|
||||
}
|
||||
}
|
||||
}
|
||||
// Reset progress values to 0
|
||||
appState.instantProgress = 0
|
||||
appState.instantTotal = 0
|
||||
|
||||
updateOnMain {
|
||||
appState.instantProgress = 0
|
||||
appState.instantTotal = 0
|
||||
appState.showProgress = false
|
||||
}
|
||||
completion()
|
||||
} else if retryCount < maxRetry {
|
||||
checkAllAppsProcessed(retryCount: retryCount + 1, maxRetry: maxRetry)
|
||||
} else {
|
||||
// Reset progress values to 0
|
||||
updateOnMain {
|
||||
appState.instantProgress = 0
|
||||
appState.instantTotal = 0
|
||||
appState.showProgress = false
|
||||
}
|
||||
printOS("loadAllPaths - Retry limit reached. Not all paths were loaded.")
|
||||
completion()
|
||||
}
|
||||
|
||||
@@ -206,7 +206,6 @@ struct Header: View {
|
||||
if instantSearch {
|
||||
loadAllPaths(allApps: sortedApps, appState: appState, locations: locations) {
|
||||
appState.reload.toggle()
|
||||
|
||||
}
|
||||
} else {
|
||||
appState.reload.toggle()
|
||||
|
||||
@@ -82,7 +82,6 @@ struct TopBarMini: View {
|
||||
if instantSearch {
|
||||
let reverse = ReversePathsSearcher(appState: appState, locations: locations)
|
||||
reverse.reversePathsSearch()
|
||||
// reversePathsSearch(appState: appState, locations: locations)
|
||||
} else {
|
||||
loadAllPaths(allApps: appState.sortedApps, appState: appState, locations: locations, reverseAddon: true)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user