### Tilde Expansion Example Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/locations.md Demonstrates that paths starting with '~' are automatically expanded to the user's home directory. ```swift let locations = Locations() // locations.userApplicationsDirectory returns actual path, not "~/Applications" ``` -------------------------------- ### Check and Install Helper Tool Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/helper-tool.md Checks if the helper tool is installed and attempts to reinstall it if it's not. Logs the last error if installation fails. ```swift // Check installation status if !HelperToolManager.shared.helperInstalled { // Try reinstalling HelperToolManager.shared.installHelper { success in if !success { print("Last error: \(HelperToolManager.shared.lastError ?? \"")") } } } ``` -------------------------------- ### Install Privileged Helper Tool Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/helper-tool.md Installs the privileged helper tool. This method must be called before executing any privileged operations. It may prompt the user for authentication. ```swift helperToolMgr.installHelper { success in if success { print("Helper tool installed") // Can now perform privileged operations } else { print("Failed to install helper tool") } } ``` -------------------------------- ### Example: Async Load Apps with Streaming Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/logic.md Example of using the asynchronous loadAppsAsync function with streaming enabled within a Task. Prints a confirmation message after loading. ```swift Task { await loadAppsAsync(folderPaths: folderPaths, useStreaming: true) print("Apps loaded and displayed") } ``` -------------------------------- ### Load Installed Homebrew Packages Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/homebrew-manager.md Asynchronously loads all installed Homebrew packages, including formulae and casks. Use this to get a list of all installed software managed by Homebrew. ```swift HomebrewManager.loadInstalledPackages { packages in let casks = packages.filter { $0.isCask } let formulae = packages.filter { !$0.isCask } print("Installed: \(casks.count) casks, \(formulae.count) formulae") } ``` -------------------------------- ### Install Pearcleaner via Homebrew Source: https://github.com/alienator88/pearcleaner/blob/main/README.md Use this command to install Pearcleaner using the Homebrew package manager. ```bash brew install --cask pearcleaner ``` -------------------------------- ### Search Standard Application Locations Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/locations.md Provides an example of searching for standard application directories. ```swift let locations = Locations() let appPaths = [ locations.applicationsDirectory, locations.userApplicationsDirectory ] loadApps(folderPaths: appPaths) ``` -------------------------------- ### installHelper Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/helper-tool.md Installs the privileged helper tool. This must be called before executing any privileged operations. It may prompt the user for authentication. ```APIDOC ## installHelper ### Description Installs the privileged helper tool via Service Management. Prompts user for authentication if necessary. Must be called before executing privileged operations. ### Method (Implicitly a method call in Swift SDK) ### Parameters - **completion** ((Bool) -> Void) - Required - Callback with success status ### Request Example ```swift helperToolMgr.installHelper { success in if success { print("Helper tool installed") // Can now perform privileged operations } else { print("Failed to install helper tool") } } ``` ``` -------------------------------- ### SwiftUI Integration Setup Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/locations.md Shows how to create and pass the Locations object as a StateObject and environment object in SwiftUI. ```swift @StateObject var locations = Locations() // Pass to environment .environmentObject(locations) // Access in views @EnvironmentObject var locations: Locations ``` -------------------------------- ### Example: Load Apps with Streaming Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/logic.md Demonstrates fast loading with streaming enabled, suitable for application startup. Specifies multiple folder paths for searching applications. ```swift // Fast loading with streaming (good for app startup) loadApps(folderPaths: ["/Applications", NSHomeDirectory() + "/Applications"], useStreaming: true) ``` -------------------------------- ### Example File Kind Filter Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/file-search.md Shows how to create a FilterType case to specifically include only directories in the search results. ```swift let filters: [FilterType] = [ .kind(.folder) // Only directories ] ``` -------------------------------- ### InstalledPackage Struct Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/types.md Represents information about an installed Homebrew package. Includes details like name, version, installation status, and size. ```swift struct InstalledPackage: Identifiable, Equatable, Hashable { let id: UUID let name: String let displayName: String? let description: String? let version: String? let isCask: Bool var isPinned: Bool let tap: String? let tapRbPath: String? let installedOnRequest: Bool var size: String? var sizeBytes: Int64? } ``` -------------------------------- ### HomebrewPackageInfo Structure Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/types.md Represents complete information about an installed Homebrew package, including its name, installation status, versions, and metadata. ```swift struct HomebrewPackageInfo: Identifiable, Equatable, Hashable { let id: UUID let name: String let isCask: Bool let installedOn: Date? let versions: [String] let sizeInBytes: Int64? let isPinned: Bool let isOutdated: Bool let description: String? let homepage: String? let tap: String? let installedPath: String? let fileCount: Int? } ``` -------------------------------- ### Symlink Resolution Example Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/locations.md Illustrates that paths are resolved to their real locations, meaning symlinks are followed. ```swift // If /private is symlinked to /var, both are normalized ``` -------------------------------- ### Complete Package Management Workflow Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/homebrew-manager.md Demonstrates a full workflow: searching for a package, retrieving its details, and then proceeding with installation logic based on whether it's a cask or formula. Requires handling of asynchronous operations and optionals. ```swift HomebrewManager.searchPackage(name: "vlc") { searchResult in guard let result = searchResult else { print("Package not found") return } HomebrewManager.getPackageDetails( name: result.name, isCask: result.caskName != nil ) { details in switch details { case .cask(let cask): print("Installing: \(cask.name)") // Install logic here case .formula(let formula): print("Found formula with \(formula.dependencies?.count ?? 0) dependencies") } } } ``` -------------------------------- ### Undo Operation Example Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/undo-manager.md Demonstrates how to check if an undo operation is available and then perform it. Updates undo/redo flags automatically. ```swift if undoManager.canUndo { undoManager.undo() print("Restored app") } ``` -------------------------------- ### loadInstalledPackages Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/homebrew-manager.md Asynchronously loads all installed Homebrew packages, including formulae and casks. Parses output from `brew list` and enriches with metadata. ```APIDOC ## loadInstalledPackages ### Description Asynchronously loads all installed Homebrew packages (formulae and casks). Parses output of `brew list` commands and enriches with metadata from JSON APIs. ### Method static func ### Parameters #### Path Parameters - **completion** (([InstalledPackage]) -> Void) - Required - Callback with array of installed packages ### Request Example ```swift HomebrewManager.loadInstalledPackages { packages in let casks = packages.filter { $0.isCask } let formulae = packages.filter { !$0.isCask } print("Installed: \(casks.count) casks, \(formulae.count) formulae") } ``` ### Response #### Success Response - **[InstalledPackage]** - Callback with array of installed packages ``` -------------------------------- ### Example Size Filters Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/file-search.md Shows how to construct FilterType cases for size-based filtering, including a minimum size and a size range. ```swift let filters: [FilterType] = [ .size(.greaterThan, 100 * 1024 * 1024), // > 100 MB .size(.between, 1 * 1024 * 1024, 10 * 1024 * 1024) // 1-10 MB ] ``` -------------------------------- ### getOutdatedPackages Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/homebrew-manager.md Lists all installed packages with available updates. Uses `brew outdated` command. ```APIDOC ## getOutdatedPackages ### Description Lists all installed packages with available updates. Uses `brew outdated` command. ### Method Static method call ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - None ### Parameters - **completion** ( ([OutdatedVersionInfo]) -> Void ) - Required - Callback with outdated packages ### Request Example ```swift HomebrewManager.getOutdatedPackages { outdated in for info in outdated { print("\(info.installed) \u2192 \(info.available)") } } ``` ### Response #### Success Response - **[OutdatedVersionInfo]**: An array of objects, each containing information about an outdated package. ``` -------------------------------- ### Search Multiple Standard and User Directories Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/locations.md Combine standard directories with user-specific directories to create a comprehensive list of paths for searching applications. This example demonstrates loading apps with streaming enabled. ```swift let locations = Locations() let searchPaths = [ locations.applicationsDirectory, locations.userApplicationsDirectory, locations.applicationSupportDirectory, locations.dotLocalDirectory ] loadApps(folderPaths: searchPaths, useStreaming: true) ``` -------------------------------- ### Example Name Filters Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/file-search.md Demonstrates how to create an array of FilterType cases for name-based filtering, including startsWith, endsWith, and regex matching. ```swift let filters: [FilterType] = [ .name(.startsWith, "temp"), .name(.endsWith, ".bak"), .name(.regex, #"^\.\w+\.swp$"#) // Vim swap files ] ``` -------------------------------- ### Delete System Application with Helper Tool Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/helper-tool.md Deletes a system application by first ensuring the helper tool is installed, then calling its deleteFile method. It handles installation failures and file deletion errors. ```swift func deleteSystemApp(_ app: AppInfo) { let helperMgr = HelperToolManager.shared // Ensure helper is installed helperMgr.installHelper { success in guard success else { print("Failed to install helper") return } // Delete app bundle helperMgr.deleteFile(at: app.path.path) { success, error in if success { print("App deleted: \(app.appName)") // Remove from app list AppState.shared.sortedApps.removeAll { $0.id == app.id } } else { print("Failed to delete: \(error ?? "unknown error")") } } } } ``` -------------------------------- ### Example: Load Apps without Streaming Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/logic.md Demonstrates complete loading without streaming, suitable for manual refresh operations. Specifies a single folder path for searching applications. ```swift // Complete loading without streaming (good for manual refresh) loadApps(folderPaths: ["/Applications"], useStreaming: false) ``` -------------------------------- ### Build Search Paths with User Settings Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/locations.md Construct search paths by starting with standard directories and appending user-defined folder paths managed by FolderSettingsManager. This allows for a flexible search scope. ```swift let locations = Locations() let fsm = FolderSettingsManager.shared // Start with standard paths var searchPaths = [ locations.applicationsDirectory, locations.userApplicationsDirectory ] // Add user-included paths searchPaths.append(contentsOf: fsm.folderPaths) // Load apps from all paths loadApps(folderPaths: searchPaths) ``` -------------------------------- ### Sorting Example Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/file-search.md Demonstrates how to sort an array of FileSearchResult objects based on size in either ascending or descending order using SortColumn and SortOrder. ```swift var sortColumn = SortColumn.size var sortOrder = SortOrder.descending // Largest first let sorted = results.sorted { if sortOrder == .ascending { return a.size < b.size } else { return a.size > b.size } } ``` -------------------------------- ### Example Tag Filter Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/file-search.md Demonstrates creating a FilterType case to find files that have any of the specified tags: 'temp', 'cache', or 'log'. ```swift let filters: [FilterType] = [ .tags(.hasAnyOfTags, "temp,cache,log") // Has any of these tags ] ``` -------------------------------- ### getPackageSize Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/homebrew-manager.md Calculates the total size of an installed package including all dependencies. ```APIDOC ## getPackageSize ### Description Calculates total size of an installed package including all dependencies. ### Method Static method call ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - None ### Parameters - **name** (String) - Required - Package name - **isCask** (Bool) - Required - Type of package - **completion** ( (Int64?) -> Void ) - Required - Callback with size in bytes or nil if error ### Response #### Success Response - **Int64?**: The size of the package in bytes, or nil if an error occurred. ``` -------------------------------- ### Example Date Filters Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/file-search.md Illustrates creating FilterType cases for date-based filtering, specifying modified before a certain date and within a date range. ```swift let thirtyDaysAgo = Date().addingTimeInterval(-30 * 86400) let sixtyDaysAgo = Date().addingTimeInterval(-60 * 86400) let filters: [FilterType] = [ .date(.modifiedBefore, thirtyDaysAgo), // Not modified in 30 days .date(.modifiedBetween, sixtyDaysAgo, thirtyDaysAgo) // Modified 30-60 days ago ] ``` -------------------------------- ### UpdaterDisplaySettings Struct Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/configuration.md Configuration struct for how update results are displayed in the UI. Defaults to showing installed apps and grouping by source. ```swift struct UpdaterDisplaySettings: AppStorageCodable { var showInstalledApps: Bool = false var groupBySource: Bool = true } ``` -------------------------------- ### Manage Homebrew Packages Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/README.md Provides functionalities to interact with Homebrew packages, including searching for packages, loading installed packages, and retrieving detailed information about specific packages (casks or formulas). ```swift // Search for package HomebrewManager.searchPackage(name: "firefox") { result in if let result = result { print("\(result.displayName ?? result.name)") } } // Load installed packages HomebrewManager.loadInstalledPackages { packages in let casks = packages.filter { $0.isCask } print("Installed \(casks.count) casks") } // Get detailed info HomebrewManager.getPackageDetails(name: "vlc", isCask: true) { details in switch details { case .cask(let cask): print("Auto-updates: \(cask.autoUpdates ?? false)") case .formula(let formula): print("Dependencies: \(formula.dependencies?.count ?? 0)") } } ``` -------------------------------- ### Configure Automatic Background Updates Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/update-manager.md Sets up the manager to periodically check for updates in the background. Specify the interval for these checks, for example, every 6 hours. ```swift func startAutoUpdates() { let interval: TimeInterval = 6 * 3600 // 6 hours updateManager.checkForUpdatesInBackground( apps: appState.sortedApps, interval: interval ) } ``` -------------------------------- ### Initiate App Update Check Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/update-manager.md Starts an asynchronous check for updates for a given list of apps. The process involves setting a checking state, dispatching checks to configured sources, collecting results, and updating the list of available updates. ```swift func checkForUpdates(apps: [AppInfo]) ``` ```swift let appsToCheck = appState.sortedApps updateManager.checkForUpdates(apps: appsToCheck) // Monitor progress if updateManager.isChecking { ProgressView(value: updateManager.checkProgress) } ``` -------------------------------- ### List Outdated Homebrew Packages Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/homebrew-manager.md Fetches a list of all installed Homebrew packages that have available updates. This function utilizes the `brew outdated` command. ```swift static func getOutdatedPackages(completion: @escaping ([OutdatedVersionInfo]) -> Void) ``` ```swift HomebrewManager.getOutdatedPackages { outdated in for info in outdated { print("\(info.installed) → \(info.available)") } } ``` -------------------------------- ### Get Updateable Apps by Source Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/update-manager.md Retrieves a list of updateable applications filtered by a specific update source. Supported sources include .appStore, .sparkle, and .homebrew. ```swift func getAppsBySource(_ source: UpdateSource) -> [UpdateableApp] ``` -------------------------------- ### Get Sorted Applications Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/logic.md Internal function to recursively collect and sort application information from specified paths. Supports optional streaming, which updates AppState progressively. Returns an empty array if streaming is enabled. ```swift func getSortedApps(paths: [String], useStreaming: Bool = false) -> [AppInfo] ``` -------------------------------- ### Get Homebrew Package Size Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/homebrew-manager.md Retrieves the total size in bytes of an installed Homebrew package, including its dependencies. Returns nil if an error occurs. ```swift static func getPackageSize(name: String, isCask: Bool, completion: @escaping (Int64?) -> Void) ``` -------------------------------- ### Build Library Search Scope Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/locations.md Demonstrates how to define a search scope for user library support files. ```swift let locations = Locations() // Search all user library support files let libraryPaths = [ locations.applicationSupportDirectory, locations.cacheDirectory, locations.preferencesDirectory, locations.savedApplicationStateDirectory ] ``` -------------------------------- ### cleanupStaleEntries Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/undo-manager.md Removes history entries for deleted apps that are no longer installed. ```APIDOC ## cleanupStaleEntries Removes history entries for deleted apps that are no longer installed. ### Description Called automatically on app launch. ### Signature ```swift func cleanupStaleEntries() ``` ``` -------------------------------- ### Load Applications Synchronously Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/logic.md Main entry point for loading or refreshing applications. Supports optional two-phase streaming for faster initial loads. Clears existing app state before loading. ```swift func loadApps(folderPaths: [String], useStreaming: Bool = false) ``` -------------------------------- ### Refresh Apps List Source: https://github.com/alienator88/pearcleaner/wiki/Deep-Link-Guide Triggers a refresh of the installed applications list. ```plaintext pear://refreshAppsList ``` -------------------------------- ### Access Singleton Instance Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/undo-manager.md Get the shared instance of the UndoHistoryManager to interact with its functionality. ```swift let manager = UndoHistoryManager.shared ``` -------------------------------- ### Accessing the AppState Singleton Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/app-state.md Get the shared instance of AppState. In SwiftUI, it can be used as an environment object. ```swift let state = AppState.shared // In SwiftUI views, use as environment object @EnvironmentObject var appState: AppState // Access published properties let apps = appState.sortedApps appState.currentPage = .files ``` -------------------------------- ### Settings Properties Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/update-manager.md Configure update sources and UI display preferences. `settings` controls which sources (App Store, Sparkle, Homebrew) are checked, and `displaySettings` manages UI presentation. ```swift @Published var settings = UpdaterSourcesSettings() @Published var displaySettings = UpdaterDisplaySettings() ``` -------------------------------- ### pauseUpdate Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/update-manager.md Pauses the download or installation process for a specified application, identified by its UUID. The update can be resumed later using `updateApp()`. ```APIDOC ## pauseUpdate ### Description Pauses download/installation. Can be resumed with `updateApp()`. ### Method Swift Function ### Signature `func pauseUpdate(with id: UUID)` ### Parameters #### Path Parameters - **id** (UUID) - Required - ID of UpdateableApp to pause ``` -------------------------------- ### Pause an App Update Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/update-manager.md Temporarily halts the download or installation of an application update. The update can be resumed later by calling `updateApp()`. ```swift func pauseUpdate(with id: UUID) ``` -------------------------------- ### loadApps Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/logic.md Main entry point for loading or refreshing applications from specified folder paths. It can optionally use two-phase streaming for a faster initial load, displaying apps progressively. ```APIDOC ## loadApps ### Description Main entry point for loading or refreshing applications from specified folder paths. Clears `AppState.shared.sortedApps` before loading. If streaming is enabled, apps appear progressively in the UI as chunks complete. If disabled, the full list is calculated first, then updated at once. With streaming enabled: 1. Phase 1: Fast basic info and app list display 2. Phase 2: Expensive operations (architecture detection, cask lookup, entitlements) in background Without streaming: 1. Complete AppInfo calculated for all apps 2. List updated once with all apps ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Method Not applicable (Swift function call) ### Endpoint Not applicable (Swift function call) ### Request Example ```swift // Fast loading with streaming (good for app startup) loadApps(folderPaths: ["/Applications", NSHomeDirectory() + "/Applications"], useStreaming: true) // Complete loading without streaming (good for manual refresh) loadApps(folderPaths: ["/Applications"], useStreaming: false) ``` ### Response #### Success Response None (modifies AppState) #### Response Example None ``` -------------------------------- ### App Name Matching Strategies Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/app-path-finder.md Illustrates various methods for matching application names. Supports exact names, names stripped of version suffixes, and case-insensitive letter-only matching. ```swift // Exact name Firefox // Name without version suffix Firefox (strips "Firefox 120.0" → "Firefox") // Letters only firefox ``` -------------------------------- ### Working with Zombie Files Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/app-state.md Set a zombie file for detail views or retrieve associated files from storage. ```swift // Set zombie file for detail view appState.zombieFile = ZombieFile( id: UUID(), fileSize: fileUrls.reduce(into: [:]) { acc, url in acc[url] = 0 // Size calculated elsewhere }, fileIcon: [:] ) // Or get associated files from storage let zombieStorage = ZombieFileStorage.shared let associatedFiles = zombieStorage.getAssociatedFiles(for: appPath) ``` -------------------------------- ### Bundle Identifier Matching Strategies Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/app-path-finder.md Demonstrates different ways to match bundle identifiers for searching applications. Use exact matches, partial matches using the last two components, or component-only strings. ```swift // Exact match com.apple.mail // Last two components (for deep bundles) apple.mail // Components-only applmail ``` -------------------------------- ### Cleanup Stale History Entries Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/undo-manager.md Removes history entries for deleted apps that are no longer installed. This is called automatically on app launch. ```swift func cleanupStaleEntries() ``` -------------------------------- ### Modify Settings using UserDefaults and FolderSettingsManager Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/configuration.md Demonstrates how to modify settings programmatically. Use UserDefaults for simple boolean flags like 'loadOnStartup' and FolderSettingsManager for managing excluded paths. ```swift // Update single setting UserDefaults.standard.set(true, forKey: "settings.updater.loadOnStartup") // Read back let loadOnStartup = UserDefaults.standard.bool(forKey: "settings.updater.loadOnStartup") // Structured settings (using FolderSettingsManager) FolderSettingsManager.shared.addExcludedPath("/path/to/skip") let excluded = FolderSettingsManager.shared.fileFolderPathsApps ``` -------------------------------- ### flushBundleCache Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/logic.md Flushes the bundle cache for a single application path. This method is useful when loading newly installed apps and does not require an `AppInfo` object. ```APIDOC ## flushBundleCache ### Description Flushes bundle cache for a single app path without requiring AppInfo object. Useful when loading newly installed apps. ### Signature ```swift func flushBundleCache(for path: URL) ``` ### Parameters #### Path Parameters - **path** (URL) - Required - Path to app bundle ### Example ```swift flushBundleCache(for: appPath) ``` ``` -------------------------------- ### Load and Display Applications in SwiftUI Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/README.md Loads applications from specified directories and displays them in a SwiftUI List. This snippet requires `AppState` and `Locations` environment objects. ```swift // In SwiftUI view @EnvironmentObject var appState: AppState @EnvironmentObject var locations: Locations var body: some View { List(appState.sortedApps) { app in Text(app.appName) Text(app.appVersion) } .onAppear { let paths = [locations.applicationsDirectory, locations.userApplicationsDirectory] loadApps(folderPaths: paths, useStreaming: true) } } ``` -------------------------------- ### searchPackage Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/homebrew-manager.md Asynchronously searches Homebrew for a package by name, querying both formulae and casks. Returns the first matching package. ```APIDOC ## searchPackage ### Description Asynchronously searches Homebrew for a package by name. Queries both formulae and casks. Returns first matching package. ### Method static func ### Parameters #### Path Parameters - **name** (String) - Required - Package name to search for (formula or cask) - **completion** ((HomebrewSearchResult?) -> Void) - Required - Callback with search result or nil if not found ### Request Example ```swift HomebrewManager.searchPackage(name: "firefox") { result in if let result = result { print("Found: \(result.displayName ?? result.name)") print("Version: \(result.version ?? \"unknown\")") print("Description: \(result.description ?? \"\")") } else { print("Package not found") } } ``` ### Response #### Success Response - **HomebrewSearchResult?** - Callback with search result or nil if not found ``` -------------------------------- ### App Management and Configuration Actions Source: https://github.com/alienator88/pearcleaner/wiki/Deep-Link-Guide Endpoints for managing app uninstallation, path configurations, and system utilities. ```APIDOC ## GET pear://uninstallApp ### Description Uninstalls an app by its name or path. ### Endpoint pear://uninstallApp ### Parameters #### Query Parameters - **name** (string) - Optional - Name of the app to uninstall (case-insensitive). - **path** (string) - Optional - File path to the app. - **matchType** (string) - Optional - Determines how to match the app name. Valid values: 'exact' (default), 'contains'. ## GET pear://appsPaths ### Description Adds or removes a folder path where to check for .app bundles. ### Endpoint pear://appsPaths ### Parameters #### Query Parameters - **add** (flag) - Required - Specifies the action to add a path. - **remove** (flag) - Required - Specifies the action to remove a path. - **path** (string) - Required - The full path to the folder. ## GET pear://orphanedPaths ### Description Adds or removes a path to exclude from orphaned files search. ### Endpoint pear://orphanedPaths ### Parameters #### Query Parameters - **add** (flag) - Required - Specifies the action to add a path. - **remove** (flag) - Required - Specifies the action to remove a path. - **path** (string) - Required - The full path to the file or folder. ## GET pear://checkUpdates ### Description Checks for updates and displays the update dialog if available. ### Endpoint pear://checkUpdates ## GET pear://refreshAppsList ### Description Refreshes the list of installed apps. ### Endpoint pear://refreshAppsList ## GET pear://resetSettings ### Description Resets all user settings to their default values. ### Endpoint pear://resetSettings ``` -------------------------------- ### Reset Specific Pearcleaner Setting Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/configuration.md To reset a particular setting or a group of settings, specify the key path. For example, to reset all updater source settings. ```bash # Or delete specific keys defaults delete com.alienator88.Pearcleaner 'settings.updater.sources' ``` -------------------------------- ### AppPathFinder Initialization Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/app-path-finder.md Initializes an AppPathFinder instance to discover application-related files. It takes app information, location settings, and optional parameters for GUI state, undo history, and search sensitivity. ```APIDOC ## Initialization ```swift init(appInfo: AppInfo, locations: Locations, appState: AppState? = nil, undo: Bool = false, sensitivityOverride: SearchSensitivityLevel? = nil, completion: (() -> Void)? = nil) ``` ### Parameters #### Path Parameters * **appInfo** (AppInfo) - Required - App to find associated files for * **locations** (Locations) - Required - Folder location settings * **appState** (AppState?) - Optional - GUI state (nil for CLI) * **undo** (Bool) - Optional - Enable undo history tracking * **sensitivityOverride** (SearchSensitivityLevel?) - Optional - Override global sensitivity for this search * **completion** ((() -> Void)?) - Optional - Callback when search completes ### Request Example ```swift let appInfo = /* AppInfo instance */ let locations = Locations() let finder = AppPathFinder( appInfo: appInfo, locations: locations, appState: appState, undo: true, sensitivityOverride: .thorough ) ``` ``` -------------------------------- ### getBundleSize Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/app-state.md Gets or calculates the bundle size for a given app. It first checks a cache and then calculates the size if not found. The result is provided via a callback. ```APIDOC ## getBundleSize ### Description Gets or calculates the bundle size for an app. First checks if size is available in `sortedApps` cache, otherwise calculates via `totalSizeOnDisk()`. Updates the callback with the size and updates the corresponding entry in `sortedApps`. ### Method func ### Parameters #### Path Parameters - **appInfo** (AppInfo) - Required - App to get size for - **updateState** ((Int64) -> Void) - Required - Callback with calculated size ### Request Example ```swift appState.getBundleSize(for: app) { size in print("Bundle size: \(size) bytes") } ``` ``` -------------------------------- ### Initialize AppPathFinder Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/app-path-finder.md Instantiate AppPathFinder with app information, location settings, and optional parameters for undo history and search sensitivity. A completion callback can be provided for post-search actions. ```swift let appInfo = /* AppInfo instance */ let locations = Locations() let finder = AppPathFinder( appInfo: appInfo, locations: locations, appState: appState, undo: true, sensitivityOverride: .thorough ) ``` -------------------------------- ### Uninstall Package with Verification Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/homebrew-manager.md Uninstalls a specified package (formula or cask) and then verifies its removal by reloading the list of installed packages. Handles success and error callbacks. ```swift HomebrewManager.uninstallPackage(name: "firefox", isCask: true) { success, error in if success { HomebrewManager.loadInstalledPackages { packages in let stillInstalled = packages.contains { $0.name == "firefox" } if !stillInstalled { print("Successfully uninstalled") } } } else { print("Failed: \(error ?? "unknown error")") } } ``` -------------------------------- ### Manage App Paths Source: https://github.com/alienator88/pearcleaner/wiki/Deep-Link-Guide Adds or removes folder paths for .app bundle scanning. ```plaintext pear://appsPaths?add&path=/Users/USER/Applications ``` ```plaintext pear://appsPaths?remove&path=/Users/USER/Applications ``` -------------------------------- ### selectAll Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/update-manager.md Selects all currently available updateable applications. This is a convenience method to quickly mark all apps for update. ```APIDOC ## selectAll ### Description Selects all updateable apps. ### Method Swift Function ### Usage Example ```swift updateManager.selectAll() updateManager.updateSelectedApps() ``` ``` -------------------------------- ### Analyze All Apps for Architecture Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/lipo.md Iterates through all sorted applications, checks their architecture, and calculates potential space savings if they are universal binaries and the Intel architecture is removed. ```swift let apps = AppState.shared.sortedApps for app in apps { let arch = checkAppBundleArchitecture(at: app.path.path) if arch == .universal { let savings = calculateLipoSavings(for: app.path, removeArch: .intel) print("\(app.appName): could save \(savings / 1_000_000) MB") } } ``` -------------------------------- ### AppInfo Struct Definition Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/types.md Defines the structure for holding detailed information about a macOS application. This includes identifiers, paths, versioning, architecture, installation source, and file-related data. ```swift struct AppInfo: Identifiable, Equatable, Hashable { let id: UUID let path: URL let bundleIdentifier: String let appName: String let appVersion: String let appBuildNumber: String? let appIcon: NSImage? let webApp: Bool let wrapped: Bool let system: Bool var arch: Arch let cask: String? let steam: Bool let hasSparkle: Bool let isAppStore: Bool let adamID: UInt64? let autoUpdates: Bool? var bundleSize: Int64 var lipoSavings: Int64? var fileSize: [URL: Int64] var fileIcon: [URL: NSImage?] let creationDate: Date? let contentChangeDate: Date? let lastUsedDate: Date? let dateAdded: Date? let entitlements: [String]? let teamIdentifier: String? } ``` -------------------------------- ### Reinstall Helper Tool on Version Mismatch Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/helper-tool.md Compares the current helper tool version with the expected version and reinstalls the helper if they do not match. ```swift if HelperToolManager.shared.helperVersion != expectedVersion { HelperToolManager.shared.installHelper { _ in // Retry operation } } ``` -------------------------------- ### Get Bundle Size for App Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/app-state.md Calculates or retrieves the bundle size for a given app. It first checks a cache and then computes the size if not found. The result is provided via a callback. ```swift appState.getBundleSize(for: app) { size in print("Bundle size: \(size) bytes") } ``` -------------------------------- ### Search Temporary Files Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/locations.md Shows how to search for temporary files, including filtering by modification date. ```swift let locations = Locations() let tempPaths = [ locations.tmpDirectory, locations.varDirectory ] let oldFiles = searchFiles( in: locations.tmpDirectory, query: "*", filters: [ .date(.modifiedBefore, Date().addingTimeInterval(-7*86400)) ] ) ``` -------------------------------- ### Flush Bundle Cache for a Single App Path Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/logic.md Flushes the bundle cache for a single application path. This is useful when loading newly installed apps and an AppInfo object is not readily available. ```swift func flushBundleCache(for path: URL) ``` -------------------------------- ### Access Standard Directories Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/locations.md Instantiate Locations and access individual standard directories like applications, user library, and cache directories. These paths can also be converted to URLs. ```swift let locations = Locations() // Access individual directories let appDir = locations.applicationsDirectory // "/Applications" let libDir = locations.userLibraryDirectory // "~/Library" let cacheDir = locations.cacheDirectory // "~/Library/Caches" // Convert to URL let appURL = URL(fileURLWithPath: locations.applicationsDirectory) ``` -------------------------------- ### Check Development Environment Source: https://github.com/alienator88/pearcleaner/wiki/Deep-Link-Guide Opens the development environment page, optionally filtering by environment name. ```plaintext pear://checkDevEnv ``` ```plaintext pear://checkDevEnv?name=xcode ``` -------------------------------- ### Basic File Search with AppPathFinder Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/app-path-finder.md Initializes AppPathFinder with app state and locations to find orphaned files. The results are used to update the UI by setting the fileSize of the zombieFile. ```swift let appInfo = appState.appInfo let locations = Locations() let pathFinder = AppPathFinder( appInfo: appInfo, locations: locations, appState: appState ) let orphanedFiles = pathFinder.findFiles() // Update UI with found files appState.zombieFile.fileSize = Dictionary( orphanedFiles.map { ($0, 0) } ) ``` -------------------------------- ### Get Specific Package Details Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/homebrew-manager.md Fetches detailed information for a specific Homebrew package (formula or cask) using Homebrew JSON APIs. Use a switch statement to access type-specific details. ```swift HomebrewManager.getPackageDetails(name: "vlc", isCask: true) { details in guard let details = details else { return } switch details { case .formula(let formula): print("Formula: \(formula.name)") print("Dependencies: \(formula.dependencies?.joined(separator: ", ") ?? "none")") case .cask(let cask): print("Cask: \(cask.name)") print("Auto-updates: \(cask.autoUpdates ?? false)") print("Requires: \(cask.minimumMacOSVersion ?? "any macOS")") } } ``` -------------------------------- ### Search Homebrew Package Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/homebrew-manager.md Asynchronously searches Homebrew for a package by name. Use this to find formulae or casks. Returns the first matching package or nil if not found. ```swift HomebrewManager.searchPackage(name: "firefox") { result in if let result = result { print("Found: \(result.displayName ?? result.name)") print("Version: \(result.version ?? "unknown")") print("Description: \(result.description ?? "")") } else { print("Package not found") } } ``` -------------------------------- ### Open Settings Page Source: https://github.com/alienator88/pearcleaner/wiki/Deep-Link-Guide Opens the settings interface, with an optional query parameter to target a specific tab. ```plaintext pear://openSettings ``` ```plaintext pear://openSettings?name=general ``` -------------------------------- ### Find App Files Asynchronously Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/app-path-finder.md Asynchronously searches the file system for app-associated files using multiple matching strategies. Use this to avoid blocking the main thread and ensure a responsive UI. ```swift func findFilesAsync() async -> [URL] ``` ```swift Task { let files = await finder.findFilesAsync() appState.zombieFile.fileSize = Dictionary( files.map { ($0, 0) } // Size calculated separately ) } ``` -------------------------------- ### AppInfoMini Structure Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/types.md A lightweight struct for initial app list display, containing essential properties for rendering and sorting. It omits expensive operations like architecture detection. ```swift struct AppInfoMini { let id: UUID let path: URL let bundleIdentifier: String let appName: String let appVersion: String let appIcon: NSImage? let system: Bool let bundleSize: Int64 let creationDate: Date? let contentChangeDate: Date? let lastUsedDate: Date? let dateAdded: Date? } ``` -------------------------------- ### Standard macOS Directories Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/locations.md Access properties for standard macOS directory paths. Convert to URL using `URL(fileURLWithPath:)` if needed. ```swift let applicationsDirectory: String // /Applications let userApplicationsDirectory: String // ~/ let systemLibraryDirectory: String // /Library let userLibraryDirectory: String // ~/Library let cacheDirectory: String // ~/Library/Caches let applicationSupportDirectory: String // ~/Library/Application Support let preferencesDirectory: String // ~/Library/Preferences let tmpDirectory: String // /tmp let varDirectory: String // /var let dotLocalDirectory: String // ~/.local let homeDirectory: String // ~ let desktopDirectory: String // ~/Desktop let downloadsDirectory: String // ~/Downloads let documentsDirectory: String // ~/Documents let savedApplicationStateDirectory: String // ~/Library/Saved Application State let coresDirectory: String // ~/Library/Caches/CrashReporter ``` -------------------------------- ### Initialize UpdateManager Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/update-manager.md Instantiate UpdateManager as a StateObject in your main app. Provide the owner and repository for checking Pearcleaner's own GitHub releases. ```swift @StateObject var updater = Updater(owner: "alienator88", repo: "Pearcleaner") ``` -------------------------------- ### Find App Files Synchronously Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/app-path-finder.md Synchronously searches the file system for app-associated files using multiple matching strategies. Use this when blocking the current thread is acceptable. ```swift func findFiles() -> [URL] ``` ```swift let finder = AppPathFinder(appInfo: app, locations: locations) let orphanedFiles = finder.findFiles() for file in orphanedFiles { print("Found: \(file.path)") } ``` -------------------------------- ### Open Lipo Page Source: https://github.com/alienator88/pearcleaner/wiki/Deep-Link-Guide Navigates to the Lipo utility page. ```plaintext pear://appLipo ``` -------------------------------- ### Monitor for Outdated Packages Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/homebrew-manager.md Retrieves a list of outdated Homebrew packages. If the list is empty, it indicates all packages are up to date; otherwise, it iterates through the outdated packages and prints their current and available versions. ```swift HomebrewManager.getOutdatedPackages { outdated in if outdated.isEmpty { print("All packages up to date") } else { for info in outdated { print("\(info.installed) → \(info.available) available") } } } ``` -------------------------------- ### Architecture Enumeration Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/lipo.md Defines the possible architectures for application binaries, including Apple Silicon, Intel, Universal, and unknown or uninitialized states. ```swift enum Arch: Int, CaseIterable, Identifiable { case arm // Apple Silicon (arm64) case intel // Intel (x86_64) case universal // Both arm64 and x86_64 case unknown // Unable to determine case empty // Uninitialized } ``` -------------------------------- ### uninstallPackage Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/homebrew-manager.md Uninstalls a Homebrew package via `brew uninstall`. Runs asynchronously in the background. ```APIDOC ## uninstallPackage ### Description Uninstalls a Homebrew package via `brew uninstall`. Runs asynchronously in background. ### Method Static method call ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - None ### Parameters - **name** (String) - Required - Package name to uninstall - **isCask** (Bool) - Required - True for cask, false for formula - **completion** ( (Bool, String?) -> Void ) - Required - Callback with success and optional error message ### Request Example ```swift HomebrewManager.uninstallPackage(name: "firefox", isCask: true) { success, error in if success { print("Firefox uninstalled") } else { print("Error: \(error ?? "unknown")") } } ``` ### Response #### Success Response - **Bool**: Indicates if the uninstallation was successful. - **String?**: An optional error message if the uninstallation failed. #### Response Example (Callback parameters: success: Bool, error: String?) ``` -------------------------------- ### Configure Update Sources Settings Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/update-manager.md Allows customization of which update sources the manager should check. You can enable or disable specific sources like App Store, Sparkle, or Homebrew by modifying the settings object. ```swift // Load current settings @Published var settings: UpdaterSourcesSettings // Disable Homebrew updates, enable others settings.checkAppStore = true settings.checkSparkle = true settings.checkHomebrew = false updateManager.settings = settings ``` -------------------------------- ### Select All Updateable Apps Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/update-manager.md Selects all available updateable applications. This is often used in conjunction with updating selected apps. ```swift func selectAll() ``` ```swift updateManager.selectAll() updateManager.updateSelectedApps() ``` -------------------------------- ### Detect and Strip Application Architectures Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/README.md Checks the architecture of an application bundle and optionally strips the Intel architecture if it's a universal binary. Provides progress feedback during the stripping process. ```swift let arch = checkAppBundleArchitecture(at: app.path.path) if arch == .universal { let savings = calculateLipoSavings(for: app.path, removeArch: .intel) let success = stripArchitecture( from: app.path, removeArch: .intel, progress: { msg in print(msg) } ) } ``` -------------------------------- ### HelperToolManager Singleton Initialization Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/helper-tool.md Provides a singleton instance of HelperToolManager for easy access throughout the application. This class manages communication with a privileged helper tool. ```swift class HelperToolManager: ObservableObject { static let shared = HelperToolManager() } ``` -------------------------------- ### loadVolumeInfo Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/app-state.md Asynchronously loads information about all mounted volumes, excluding Time Machine volumes. This information is updated on the main thread and is automatically called during app initialization. ```APIDOC ## loadVolumeInfo ### Description Asynchronously loads information about all mounted volumes (capacity, available space, purgeable space, external status). Runs on background thread and updates `volumeInfos` on main thread. Skips Time Machine volumes. Automatically called during app initialization. ### Method func ### Endpoint loadVolumeInfo() ### Request Example ```swift AppState.shared.loadVolumeInfo() // Later, access volumes via AppState.shared.volumeInfos ``` ``` -------------------------------- ### restoreApp Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/undo-manager.md Attempts to restore an app and its associated files from trash. ```APIDOC ## restoreApp Attempts to restore an app and its associated files from trash. ### Description Returns false if files have been permanently removed. ### Signature ```swift func restoreApp(from entry: UndoHistoryEntry) -> Bool ``` ### Parameters #### entry - Type: `UndoHistoryEntry` - Description: History entry to restore ### Returns - Type: `Bool` - Description: True if successful, false if files no longer in trash ### Example ```swift if let entry = history.first { let success = historyMgr.restoreApp(from: entry) if success { print("App restored") } else { print("Files no longer in trash") } } ``` ``` -------------------------------- ### Handling Non-Existent Paths Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/logic.md Demonstrates how `totalSizeOnDisk` returns 0 for invalid or inaccessible paths, indicating no exceptions are thrown. ```swift let size = totalSizeOnDisk(for: invalidPath) // Returns 0 if path doesn't exist or is inaccessible ``` -------------------------------- ### Execute Shell Command with Elevated Privileges Source: https://github.com/alienator88/pearcleaner/blob/main/_autodocs/api-reference/helper-tool.md Executes a shell command and its arguments with elevated privileges. Useful for CLI tools like Homebrew. Returns success status, command output, and an optional error message. ```swift helperToolMgr.executeCommand( "brew", arguments: ["uninstall", "firefox"], completion: { success, output, error in if success { print("Command output: \(output)") } else { print("Error: \(error ?? "")") } } ) ```