mirror of
https://github.com/exituser/Pearcleaner.git
synced 2026-09-17 07:19:04 +00:00
3.0.2 fixes
This commit is contained in:
@@ -15,7 +15,6 @@
|
|||||||
C71848442B8D2D600046CB13 /* ZombieView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C71848432B8D2D600046CB13 /* ZombieView.swift */; };
|
C71848442B8D2D600046CB13 /* ZombieView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C71848432B8D2D600046CB13 /* ZombieView.swift */; };
|
||||||
C72893052AFD42E600C8C1CD /* DeepLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = C72893042AFD42E600C8C1CD /* DeepLink.swift */; };
|
C72893052AFD42E600C8C1CD /* DeepLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = C72893042AFD42E600C8C1CD /* DeepLink.swift */; };
|
||||||
C72893122AFD51EA00C8C1CD /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = C72893112AFD51EA00C8C1CD /* main.swift */; };
|
C72893122AFD51EA00C8C1CD /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = C72893112AFD51EA00C8C1CD /* main.swift */; };
|
||||||
C7575D382B0181FC006A600A /* FileWatcher in Frameworks */ = {isa = PBXBuildFile; productRef = C7575D372B0181FC006A600A /* FileWatcher */; };
|
|
||||||
C7575D392B0182DE006A600A /* PearcleanerSentinel in CopyFiles */ = {isa = PBXBuildFile; fileRef = C728930F2AFD51EA00C8C1CD /* PearcleanerSentinel */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
C7575D392B0182DE006A600A /* PearcleanerSentinel in CopyFiles */ = {isa = PBXBuildFile; fileRef = C728930F2AFD51EA00C8C1CD /* PearcleanerSentinel */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||||
C76D08482AF83C3F00D07867 /* Update.swift in Sources */ = {isa = PBXBuildFile; fileRef = C76D08472AF83C3F00D07867 /* Update.swift */; };
|
C76D08482AF83C3F00D07867 /* Update.swift in Sources */ = {isa = PBXBuildFile; fileRef = C76D08472AF83C3F00D07867 /* Update.swift */; };
|
||||||
C76D084A2AF83C6E00D07867 /* General.swift in Sources */ = {isa = PBXBuildFile; fileRef = C76D08492AF83C6E00D07867 /* General.swift */; };
|
C76D084A2AF83C6E00D07867 /* General.swift in Sources */ = {isa = PBXBuildFile; fileRef = C76D08492AF83C6E00D07867 /* General.swift */; };
|
||||||
@@ -30,6 +29,7 @@
|
|||||||
C77B901E2AF1A9DB009CC655 /* SettingsWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C77B901D2AF1A9DB009CC655 /* SettingsWindow.swift */; };
|
C77B901E2AF1A9DB009CC655 /* SettingsWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C77B901D2AF1A9DB009CC655 /* SettingsWindow.swift */; };
|
||||||
C77B90232AF2D616009CC655 /* FilesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C77B90222AF2D616009CC655 /* FilesView.swift */; };
|
C77B90232AF2D616009CC655 /* FilesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C77B90222AF2D616009CC655 /* FilesView.swift */; };
|
||||||
C7A27E812AFD7C4600166168 /* com.alienator88.PearcleanerSentinel.plist in Resources */ = {isa = PBXBuildFile; fileRef = C7A27E802AFD7C4600166168 /* com.alienator88.PearcleanerSentinel.plist */; };
|
C7A27E812AFD7C4600166168 /* com.alienator88.PearcleanerSentinel.plist in Resources */ = {isa = PBXBuildFile; fileRef = C7A27E802AFD7C4600166168 /* com.alienator88.PearcleanerSentinel.plist */; };
|
||||||
|
C7A2AE5D2B9644F300161540 /* FileWatcher in Frameworks */ = {isa = PBXBuildFile; productRef = C7A2AE5C2B9644F300161540 /* FileWatcher */; };
|
||||||
C7A9CE472B89164700EB6E78 /* Authorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7A9CE462B89164700EB6E78 /* Authorization.swift */; };
|
C7A9CE472B89164700EB6E78 /* Authorization.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7A9CE462B89164700EB6E78 /* Authorization.swift */; };
|
||||||
C7ACADE62B92A737000B5845 /* Features.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7ACADE52B92A737000B5845 /* Features.swift */; };
|
C7ACADE62B92A737000B5845 /* Features.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7ACADE52B92A737000B5845 /* Features.swift */; };
|
||||||
C7CF47242B3B3F1700979C5F /* WindowSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7CF47232B3B3F1700979C5F /* WindowSettings.swift */; };
|
C7CF47242B3B3F1700979C5F /* WindowSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7CF47232B3B3F1700979C5F /* WindowSettings.swift */; };
|
||||||
@@ -37,6 +37,7 @@
|
|||||||
C7D31D4A2AFEB26700C7ED9E /* AppListItems.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7D31D492AFEB26700C7ED9E /* AppListItems.swift */; };
|
C7D31D4A2AFEB26700C7ED9E /* AppListItems.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7D31D492AFEB26700C7ED9E /* AppListItems.swift */; };
|
||||||
C7D31D512AFF00F300C7ED9E /* Locations.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7D31D502AFF00F300C7ED9E /* Locations.swift */; };
|
C7D31D512AFF00F300C7ED9E /* Locations.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7D31D502AFF00F300C7ED9E /* Locations.swift */; };
|
||||||
C7F539382AF60865007DF1B2 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F539372AF60865007DF1B2 /* Utilities.swift */; };
|
C7F539382AF60865007DF1B2 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7F539372AF60865007DF1B2 /* Utilities.swift */; };
|
||||||
|
C7FB173B2B96321300B96F9A /* AppsListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7FB173A2B96321300B96F9A /* AppsListView.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
@@ -95,6 +96,7 @@
|
|||||||
C7D31D492AFEB26700C7ED9E /* AppListItems.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppListItems.swift; sourceTree = "<group>"; };
|
C7D31D492AFEB26700C7ED9E /* AppListItems.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppListItems.swift; sourceTree = "<group>"; };
|
||||||
C7D31D502AFF00F300C7ED9E /* Locations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Locations.swift; sourceTree = "<group>"; };
|
C7D31D502AFF00F300C7ED9E /* Locations.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Locations.swift; sourceTree = "<group>"; };
|
||||||
C7F539372AF60865007DF1B2 /* Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utilities.swift; sourceTree = "<group>"; };
|
C7F539372AF60865007DF1B2 /* Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utilities.swift; sourceTree = "<group>"; };
|
||||||
|
C7FB173A2B96321300B96F9A /* AppsListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppsListView.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@@ -102,7 +104,7 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
C7575D382B0181FC006A600A /* FileWatcher in Frameworks */,
|
C7A2AE5D2B9644F300161540 /* FileWatcher in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -146,7 +148,6 @@
|
|||||||
C72893102AFD51EA00C8C1CD /* PearcleanerSentinel */ = {
|
C72893102AFD51EA00C8C1CD /* PearcleanerSentinel */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
C7A27E822AFD996100166168 /* Resources */,
|
|
||||||
C7A27E7F2AFD70DD00166168 /* PearcleanerSentinel.entitlements */,
|
C7A27E7F2AFD70DD00166168 /* PearcleanerSentinel.entitlements */,
|
||||||
C72893112AFD51EA00C8C1CD /* main.swift */,
|
C72893112AFD51EA00C8C1CD /* main.swift */,
|
||||||
);
|
);
|
||||||
@@ -224,17 +225,11 @@
|
|||||||
C7D31D492AFEB26700C7ED9E /* AppListItems.swift */,
|
C7D31D492AFEB26700C7ED9E /* AppListItems.swift */,
|
||||||
C7045A272B03E71D00376976 /* MiniMode.swift */,
|
C7045A272B03E71D00376976 /* MiniMode.swift */,
|
||||||
C71848432B8D2D600046CB13 /* ZombieView.swift */,
|
C71848432B8D2D600046CB13 /* ZombieView.swift */,
|
||||||
|
C7FB173A2B96321300B96F9A /* AppsListView.swift */,
|
||||||
);
|
);
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
C7A27E822AFD996100166168 /* Resources */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
);
|
|
||||||
path = Resources;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
@@ -252,7 +247,7 @@
|
|||||||
);
|
);
|
||||||
name = PearcleanerSentinel;
|
name = PearcleanerSentinel;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
C7575D372B0181FC006A600A /* FileWatcher */,
|
C7A2AE5C2B9644F300161540 /* FileWatcher */,
|
||||||
);
|
);
|
||||||
productName = PeakPurgeMonitor;
|
productName = PeakPurgeMonitor;
|
||||||
productReference = C728930F2AFD51EA00C8C1CD /* PearcleanerSentinel */;
|
productReference = C728930F2AFD51EA00C8C1CD /* PearcleanerSentinel */;
|
||||||
@@ -306,7 +301,7 @@
|
|||||||
);
|
);
|
||||||
mainGroup = C77B8FF72AF18E2E009CC655;
|
mainGroup = C77B8FF72AF18E2E009CC655;
|
||||||
packageReferences = (
|
packageReferences = (
|
||||||
C7575D362B0181F3006A600A /* XCRemoteSwiftPackageReference "FileWatcher" */,
|
C7A2AE5B2B9644DA00161540 /* XCRemoteSwiftPackageReference "FileWatcher" */,
|
||||||
);
|
);
|
||||||
productRefGroup = C77B90012AF18E2E009CC655 /* Products */;
|
productRefGroup = C77B90012AF18E2E009CC655 /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
@@ -344,6 +339,7 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
C76D08482AF83C3F00D07867 /* Update.swift in Sources */,
|
C76D08482AF83C3F00D07867 /* Update.swift in Sources */,
|
||||||
|
C7FB173B2B96321300B96F9A /* AppsListView.swift in Sources */,
|
||||||
C7045A342B068B2900376976 /* UpdateView.swift in Sources */,
|
C7045A342B068B2900376976 /* UpdateView.swift in Sources */,
|
||||||
C77B90162AF19377009CC655 /* AppState.swift in Sources */,
|
C77B90162AF19377009CC655 /* AppState.swift in Sources */,
|
||||||
C7045A322B068AD700376976 /* NewWin.swift in Sources */,
|
C7045A322B068AD700376976 /* NewWin.swift in Sources */,
|
||||||
@@ -383,6 +379,7 @@
|
|||||||
DEAD_CODE_STRIPPING = YES;
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEVELOPMENT_TEAM = BK8443AXLU;
|
DEVELOPMENT_TEAM = BK8443AXLU;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
|
FRAMEWORK_SEARCH_PATHS = "";
|
||||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.alienator88.PearcleanerSentinel;
|
PRODUCT_BUNDLE_IDENTIFIER = com.alienator88.PearcleanerSentinel;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
@@ -400,6 +397,7 @@
|
|||||||
DEAD_CODE_STRIPPING = YES;
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEVELOPMENT_TEAM = BK8443AXLU;
|
DEVELOPMENT_TEAM = BK8443AXLU;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
|
FRAMEWORK_SEARCH_PATHS = "";
|
||||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.alienator88.PearcleanerSentinel;
|
PRODUCT_BUNDLE_IDENTIFIER = com.alienator88.PearcleanerSentinel;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
@@ -448,6 +446,7 @@
|
|||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
ENABLE_TESTABILITY = YES;
|
ENABLE_TESTABILITY = YES;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
FRAMEWORK_SEARCH_PATHS = "";
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
GCC_DYNAMIC_NO_PIC = NO;
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
@@ -513,6 +512,7 @@
|
|||||||
ENABLE_NS_ASSERTIONS = NO;
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
FRAMEWORK_SEARCH_PATHS = "";
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
@@ -539,7 +539,7 @@
|
|||||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 20;
|
CURRENT_PROJECT_VERSION = 21;
|
||||||
DEAD_CODE_STRIPPING = YES;
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEVELOPMENT_ASSET_PATHS = "";
|
DEVELOPMENT_ASSET_PATHS = "";
|
||||||
DEVELOPMENT_TEAM = BK8443AXLU;
|
DEVELOPMENT_TEAM = BK8443AXLU;
|
||||||
@@ -557,7 +557,7 @@
|
|||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||||
MARKETING_VERSION = 3.0.1;
|
MARKETING_VERSION = 3.0.2;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.alienator88.Pearcleaner;
|
PRODUCT_BUNDLE_IDENTIFIER = com.alienator88.Pearcleaner;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
@@ -574,7 +574,7 @@
|
|||||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 20;
|
CURRENT_PROJECT_VERSION = 21;
|
||||||
DEAD_CODE_STRIPPING = YES;
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEVELOPMENT_ASSET_PATHS = "";
|
DEVELOPMENT_ASSET_PATHS = "";
|
||||||
DEVELOPMENT_TEAM = BK8443AXLU;
|
DEVELOPMENT_TEAM = BK8443AXLU;
|
||||||
@@ -592,7 +592,7 @@
|
|||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||||
MARKETING_VERSION = 3.0.1;
|
MARKETING_VERSION = 3.0.2;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.alienator88.Pearcleaner;
|
PRODUCT_BUNDLE_IDENTIFIER = com.alienator88.Pearcleaner;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
@@ -633,7 +633,7 @@
|
|||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
|
|
||||||
/* Begin XCRemoteSwiftPackageReference section */
|
/* Begin XCRemoteSwiftPackageReference section */
|
||||||
C7575D362B0181F3006A600A /* XCRemoteSwiftPackageReference "FileWatcher" */ = {
|
C7A2AE5B2B9644DA00161540 /* XCRemoteSwiftPackageReference "FileWatcher" */ = {
|
||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
repositoryURL = "https://github.com/eonist/FileWatcher.git";
|
repositoryURL = "https://github.com/eonist/FileWatcher.git";
|
||||||
requirement = {
|
requirement = {
|
||||||
@@ -644,9 +644,9 @@
|
|||||||
/* End XCRemoteSwiftPackageReference section */
|
/* End XCRemoteSwiftPackageReference section */
|
||||||
|
|
||||||
/* Begin XCSwiftPackageProductDependency section */
|
/* Begin XCSwiftPackageProductDependency section */
|
||||||
C7575D372B0181FC006A600A /* FileWatcher */ = {
|
C7A2AE5C2B9644F300161540 /* FileWatcher */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = C7575D362B0181F3006A600A /* XCRemoteSwiftPackageReference "FileWatcher" */;
|
package = C7A2AE5B2B9644DA00161540 /* XCRemoteSwiftPackageReference "FileWatcher" */;
|
||||||
productName = FileWatcher;
|
productName = FileWatcher;
|
||||||
};
|
};
|
||||||
/* End XCSwiftPackageProductDependency section */
|
/* End XCSwiftPackageProductDependency section */
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct AppCommands: Commands {
|
struct AppCommands: Commands {
|
||||||
|
@AppStorage("settings.general.instant") private var instantSearch: Bool = true
|
||||||
|
|
||||||
let appState: AppState
|
let appState: AppState
|
||||||
let locations: Locations
|
let locations: Locations
|
||||||
@@ -32,18 +33,20 @@ struct AppCommands: Commands {
|
|||||||
Button {
|
Button {
|
||||||
withAnimation(.easeInOut(duration: 0.5)) {
|
withAnimation(.easeInOut(duration: 0.5)) {
|
||||||
// Refresh Apps list
|
// Refresh Apps list
|
||||||
appState.reload.toggle()
|
|
||||||
let sortedApps = getSortedApps()
|
|
||||||
updateOnMain {
|
updateOnMain {
|
||||||
|
appState.reload.toggle()
|
||||||
|
}
|
||||||
|
let sortedApps = getSortedApps()
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||||
appState.sortedApps.userApps = []
|
appState.sortedApps.userApps = []
|
||||||
appState.sortedApps.systemApps = []
|
appState.sortedApps.systemApps = []
|
||||||
appState.sortedApps.userApps = sortedApps.userApps
|
appState.sortedApps.userApps = sortedApps.userApps
|
||||||
appState.sortedApps.systemApps = sortedApps.systemApps
|
appState.sortedApps.systemApps = sortedApps.systemApps
|
||||||
}
|
if instantSearch {
|
||||||
Task(priority: .high){
|
Task(priority: .high){
|
||||||
loadAllPaths(allApps: sortedApps.userApps + sortedApps.systemApps, appState: appState, locations: locations)
|
loadAllPaths(allApps: sortedApps.userApps + sortedApps.systemApps, appState: appState, locations: locations)
|
||||||
}
|
}
|
||||||
updateOnMain {
|
}
|
||||||
appState.reload.toggle()
|
appState.reload.toggle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,16 +67,18 @@ struct AppCommands: Commands {
|
|||||||
|
|
||||||
// Edit Menu
|
// Edit Menu
|
||||||
CommandGroup(replacing: .undoRedo) {
|
CommandGroup(replacing: .undoRedo) {
|
||||||
|
|
||||||
Button
|
Button
|
||||||
{
|
{
|
||||||
undoTrash(appState: appState) {
|
undoTrash(appState: appState) {
|
||||||
let sortedApps = getSortedApps()
|
let sortedApps = getSortedApps()
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||||
appState.sortedApps.userApps = []
|
|
||||||
appState.sortedApps.systemApps = []
|
|
||||||
appState.sortedApps.userApps = sortedApps.userApps
|
appState.sortedApps.userApps = sortedApps.userApps
|
||||||
appState.sortedApps.systemApps = sortedApps.systemApps
|
appState.sortedApps.systemApps = sortedApps.systemApps
|
||||||
loadAllPaths(allApps: sortedApps.userApps + sortedApps.systemApps, appState: appState, locations: locations)
|
// if instantSearch {
|
||||||
|
// loadAllPaths(allApps: sortedApps.userApps + sortedApps.systemApps, appState: appState, locations: locations)
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} label: {
|
} label: {
|
||||||
|
|||||||
@@ -321,7 +321,14 @@ func findPathsForApp(appInfo: AppInfo = .empty, appState: AppState, locations: L
|
|||||||
|
|
||||||
var collection: [URL] = []
|
var collection: [URL] = []
|
||||||
if let url = URL(string: appInfo.path.absoluteString) {
|
if let url = URL(string: appInfo.path.absoluteString) {
|
||||||
collection.insert(url, at: 0)
|
if !url.path.contains(".Trash") {
|
||||||
|
if url.path.contains("Wrapper") {
|
||||||
|
let modifiedUrl = url.deletingLastPathComponent().deletingLastPathComponent()
|
||||||
|
collection.insert(modifiedUrl, at: 0)
|
||||||
|
} else {
|
||||||
|
collection.insert(url, at: 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -329,7 +336,6 @@ func findPathsForApp(appInfo: AppInfo = .empty, appState: AppState, locations: L
|
|||||||
let dispatchGroup = DispatchGroup()
|
let dispatchGroup = DispatchGroup()
|
||||||
var bundleComponents = appInfo.bundleIdentifier.components(separatedBy: ".")
|
var bundleComponents = appInfo.bundleIdentifier.components(separatedBy: ".")
|
||||||
if let lastComponent = bundleComponents.last, let rangeOfDash = lastComponent.range(of: "-") {
|
if let lastComponent = bundleComponents.last, let rangeOfDash = lastComponent.range(of: "-") {
|
||||||
// Remove the dash and everything after it
|
|
||||||
let updatedLastComponent = String(lastComponent[..<rangeOfDash.lowerBound])
|
let updatedLastComponent = String(lastComponent[..<rangeOfDash.lowerBound])
|
||||||
bundleComponents[bundleComponents.count - 1] = updatedLastComponent
|
bundleComponents[bundleComponents.count - 1] = updatedLastComponent
|
||||||
}
|
}
|
||||||
@@ -370,6 +376,7 @@ func findPathsForApp(appInfo: AppInfo = .empty, appState: AppState, locations: L
|
|||||||
if collection.contains(itemURL) {
|
if collection.contains(itemURL) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Catch web app plist files
|
// Catch web app plist files
|
||||||
if appInfo.webApp {
|
if appInfo.webApp {
|
||||||
if itemL.contains(bundleIdentifierL) {
|
if itemL.contains(bundleIdentifierL) {
|
||||||
@@ -417,7 +424,6 @@ func findPathsForApp(appInfo: AppInfo = .empty, appState: AppState, locations: L
|
|||||||
collection.append(contentsOf: groupContainers)
|
collection.append(contentsOf: groupContainers)
|
||||||
var sortedCollection = collection.sorted(by: { $0.absoluteString < $1.absoluteString })
|
var sortedCollection = collection.sorted(by: { $0.absoluteString < $1.absoluteString })
|
||||||
|
|
||||||
|
|
||||||
// Calculate file details (sizes and icons)
|
// Calculate file details (sizes and icons)
|
||||||
var fileSize: [URL: Int64] = [:]
|
var fileSize: [URL: Int64] = [:]
|
||||||
var fileIcon: [URL: NSImage?] = [:]
|
var fileIcon: [URL: NSImage?] = [:]
|
||||||
@@ -438,6 +444,7 @@ func findPathsForApp(appInfo: AppInfo = .empty, appState: AppState, locations: L
|
|||||||
sortedCollection = []
|
sortedCollection = []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save to appState
|
// Save to appState
|
||||||
dispatchGroup.notify(queue: .main) {
|
dispatchGroup.notify(queue: .main) {
|
||||||
|
|
||||||
@@ -593,7 +600,7 @@ func reversePathsSearch(appState: AppState, locations: Locations, completion: @e
|
|||||||
let dispatchGroup = DispatchGroup()
|
let dispatchGroup = DispatchGroup()
|
||||||
let allPaths = appState.appInfoStore.flatMap { $0.files.map { $0.path.pearFormat() } }
|
let allPaths = appState.appInfoStore.flatMap { $0.files.map { $0.path.pearFormat() } }
|
||||||
let allNames = appState.appInfoStore.map { $0.appName.pearFormat() }
|
let allNames = appState.appInfoStore.map { $0.appName.pearFormat() }
|
||||||
let skipped = ["apple", "comapple", "temporary", "btserver", "proapps", "scripteditor", "ilife", "livefsd", "siritoday", "addressbook", "animoji", "appstore", "askpermission", "callhistory", "clouddocs", "diskimages", "dock", "facetime", "fileprovider", "instruments", "knowledge", "mobilesync", "syncservices", "homeenergyd", "icloud", "icdd", "networkserviceproxy", "familycircle", "geoservices", "installation", "passkit", "sharedimagecache", "desktop", "mbuseragent", "swiftpm", "baseband", "coresimulator", "photoslegacyupgrade", "photosupgrade", "siritts", "ipod", "globalpreferences", "apmanalytics", "apmexperiment", "avatarcache", "byhost", "contextstoreagent", "mobilemeaccounts", "intentbuilderc", "loginwindow", "momc", "replayd", "sharedfilelistd", "clang", "audiocomponent", "csexattrcryptoservice", "livetranscriptionagent", "sandobxhelper", "statuskitagent", "betaenrollmentd", "contentlinkingd", "diagnosticextensionsd", "gamed", "heard", "homed", "itunescloudd", "lldb", "mds", "mediaanalysisd", "metrickitd", "mobiletimerd", "proactived", "ptpcamerad", "studentd", "talagent", "watchlistd", "apptranslocation", "xcrun", "ds_store", "caches", "crashreporter"] // Skip system folders
|
let skipped = ["apple", "comapple", "temporary", "btserver", "proapps", "scripteditor", "ilife", "livefsd", "siritoday", "addressbook", "animoji", "appstore", "askpermission", "callhistory", "clouddocs", "diskimages", "dock", "facetime", "fileprovider", "instruments", "knowledge", "mobilesync", "syncservices", "homeenergyd", "icloud", "icdd", "networkserviceproxy", "familycircle", "geoservices", "installation", "passkit", "sharedimagecache", "desktop", "mbuseragent", "swiftpm", "baseband", "coresimulator", "photoslegacyupgrade", "photosupgrade", "siritts", "ipod", "globalpreferences", "apmanalytics", "apmexperiment", "avatarcache", "byhost", "contextstoreagent", "mobilemeaccounts", "intentbuilderc", "loginwindow", "momc", "replayd", "sharedfilelistd", "clang", "audiocomponent", "csexattrcryptoservice", "livetranscriptionagent", "sandobxhelper", "statuskitagent", "betaenrollmentd", "contentlinkingd", "diagnosticextensionsd", "gamed", "heard", "homed", "itunescloudd", "lldb", "mds", "mediaanalysisd", "metrickitd", "mobiletimerd", "proactived", "ptpcamerad", "studentd", "talagent", "watchlistd", "apptranslocation", "xcrun", "ds_store", "caches", "crashreporter", "trash"] // Skip system folders
|
||||||
|
|
||||||
|
|
||||||
// Skip locations that might not exist
|
// Skip locations that might not exist
|
||||||
@@ -654,7 +661,6 @@ func reversePathsSearch(appState: AppState, locations: Locations, completion: @e
|
|||||||
updateOnMain {
|
updateOnMain {
|
||||||
updatedZombieFile.fileSize = fileSize
|
updatedZombieFile.fileSize = fileSize
|
||||||
updatedZombieFile.fileIcon = fileIcon
|
updatedZombieFile.fileIcon = fileIcon
|
||||||
// appState.selectedZombieItems = Set(sortedCollection)
|
|
||||||
appState.zombieFile = updatedZombieFile
|
appState.zombieFile = updatedZombieFile
|
||||||
appState.showProgress = false
|
appState.showProgress = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -504,6 +504,40 @@ struct WindowActionButton: ButtonStyle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct SimpleButtonBrightStyle: ButtonStyle {
|
||||||
|
@State private var hovered = false
|
||||||
|
let icon: String
|
||||||
|
let help: String
|
||||||
|
let color: Color
|
||||||
|
let shield: Bool?
|
||||||
|
|
||||||
|
init(icon: String, help: String, color: Color, shield: Bool? = nil) {
|
||||||
|
self.icon = icon
|
||||||
|
self.help = help
|
||||||
|
self.color = color
|
||||||
|
self.shield = shield
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeBody(configuration: Self.Configuration) -> some View {
|
||||||
|
HStack {
|
||||||
|
Image(systemName: icon)
|
||||||
|
.resizable()
|
||||||
|
.scaledToFit()
|
||||||
|
.frame(width: 20)
|
||||||
|
.foregroundColor(hovered ? color.opacity(0.5) : color)
|
||||||
|
}
|
||||||
|
.padding(5)
|
||||||
|
.onHover { hovering in
|
||||||
|
withAnimation() {
|
||||||
|
hovered = hovering
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.scaleEffect(configuration.isPressed ? 0.95 : 1)
|
||||||
|
.help(help)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct FilesViewActionButton: ButtonStyle {
|
struct FilesViewActionButton: ButtonStyle {
|
||||||
enum UserAction {
|
enum UserAction {
|
||||||
|
|||||||
@@ -427,7 +427,7 @@ func ensureApplicationSupportFolderExists(appState: AppState) {
|
|||||||
let fileManager = FileManager.default
|
let fileManager = FileManager.default
|
||||||
let supportURL = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!.appendingPathComponent("Pearcleaner")
|
let supportURL = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!.appendingPathComponent("Pearcleaner")
|
||||||
|
|
||||||
// Check to make sure Application Support/Support Admin folder exists
|
// Check to make sure Application Support/Pearcleaner folder exists
|
||||||
if !fileManager.fileExists(atPath: supportURL.path) {
|
if !fileManager.fileExists(atPath: supportURL.path) {
|
||||||
try! fileManager.createDirectory(at: supportURL, withIntermediateDirectories: true)
|
try! fileManager.createDirectory(at: supportURL, withIntermediateDirectories: true)
|
||||||
printOS("Created Application Support/Pearcleaner folder")
|
printOS("Created Application Support/Pearcleaner folder")
|
||||||
@@ -463,7 +463,7 @@ func writeLog(string: String) {
|
|||||||
|
|
||||||
|
|
||||||
// --- Load Plist file with launchctl ---
|
// --- Load Plist file with launchctl ---
|
||||||
func launchctl(load: Bool) {
|
func launchctl(load: Bool, completion: @escaping () -> Void = {}) {
|
||||||
let cmd = load ? "load" : "unload"
|
let cmd = load ? "load" : "unload"
|
||||||
if let plistPath = Bundle.main.path(forResource: "com.alienator88.PearcleanerSentinel", ofType: "plist") {
|
if let plistPath = Bundle.main.path(forResource: "com.alienator88.PearcleanerSentinel", ofType: "plist") {
|
||||||
var plistContent = try! String(contentsOfFile: plistPath)
|
var plistContent = try! String(contentsOfFile: plistPath)
|
||||||
@@ -491,6 +491,8 @@ func launchctl(load: Bool) {
|
|||||||
|
|
||||||
task.launch()
|
task.launch()
|
||||||
|
|
||||||
|
completion()
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,8 +29,6 @@ struct PearcleanerApp: App {
|
|||||||
|
|
||||||
var body: some Scene {
|
var body: some Scene {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
WindowGroup {
|
WindowGroup {
|
||||||
Group {
|
Group {
|
||||||
ZStack() {
|
ZStack() {
|
||||||
@@ -53,7 +51,7 @@ struct PearcleanerApp: App {
|
|||||||
}
|
}
|
||||||
.environmentObject(appState)
|
.environmentObject(appState)
|
||||||
.preferredColorScheme(displayMode.colorScheme)
|
.preferredColorScheme(displayMode.colorScheme)
|
||||||
.alert(isPresented: $appState.showAlert) { presentAlert(appState: appState) }
|
// .alert(isPresented: $appState.showAlert) { presentAlert(appState: appState) }
|
||||||
.handlesExternalEvents(preferring: Set(arrayLiteral: "pear"), allowing: Set(arrayLiteral: "*"))
|
.handlesExternalEvents(preferring: Set(arrayLiteral: "pear"), allowing: Set(arrayLiteral: "*"))
|
||||||
.onOpenURL(perform: { url in
|
.onOpenURL(perform: { url in
|
||||||
let deeplinkManager = DeeplinkManager(showPopover: $showPopover)
|
let deeplinkManager = DeeplinkManager(showPopover: $showPopover)
|
||||||
@@ -103,7 +101,6 @@ struct PearcleanerApp: App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
Task {
|
Task {
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
"color-space" : "display-p3",
|
"color-space" : "display-p3",
|
||||||
"components" : {
|
"components" : {
|
||||||
"alpha" : "1.000",
|
"alpha" : "1.000",
|
||||||
"blue" : "0xFF",
|
"blue" : "0x50",
|
||||||
"green" : "0xFF",
|
"green" : "0xC3",
|
||||||
"red" : "0xFF"
|
"red" : "0x79"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"idiom" : "universal"
|
"idiom" : "universal"
|
||||||
@@ -23,9 +23,9 @@
|
|||||||
"color-space" : "display-p3",
|
"color-space" : "display-p3",
|
||||||
"components" : {
|
"components" : {
|
||||||
"alpha" : "1.000",
|
"alpha" : "1.000",
|
||||||
"blue" : "0xFF",
|
"blue" : "0x50",
|
||||||
"green" : "0xFF",
|
"green" : "0xC3",
|
||||||
"red" : "0xFF"
|
"red" : "0x79"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"idiom" : "universal"
|
"idiom" : "universal"
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ struct GeneralSettingsTab: View {
|
|||||||
.font(.callout)
|
.font(.callout)
|
||||||
.foregroundStyle(.gray)
|
.foregroundStyle(.gray)
|
||||||
}
|
}
|
||||||
InfoButton(text: "When transparent material is enabled, sticky section headers (User/System) in app list are disabled to keep from showing app name text overlayed under the section header text with no background to separate the two.", color: nil)
|
// InfoButton(text: "When transparent material is enabled, sticky section headers (User/System) in app list are disabled to keep from showing app name text overlayed under the section header text with no background to separate the two.", color: nil)
|
||||||
Spacer()
|
Spacer()
|
||||||
Toggle(isOn: $glass, label: {
|
Toggle(isOn: $glass, label: {
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ struct Asset: Codable {
|
|||||||
|
|
||||||
extension Release {
|
extension Release {
|
||||||
var modifiedBody: String {
|
var modifiedBody: String {
|
||||||
return body.replacingOccurrences(of: "- [x]", with: "").replacingOccurrences(of: "###", with: "")
|
return body.replacingOccurrences(of: "- [x]", with: ">").replacingOccurrences(of: "###", with: "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,53 +64,9 @@ struct AppListView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.top, 20)
|
.padding(.top, 20)
|
||||||
// .padding(.bottom)
|
|
||||||
|
|
||||||
ScrollView {
|
|
||||||
|
|
||||||
LazyVStack(alignment: .leading, spacing: 0, pinnedViews: [glass ? [] : .sectionHeaders]) {
|
AppsListView(search: $search, showPopover: $showPopover, filteredUserApps: filteredUserApps, filteredSystemApps: filteredSystemApps)
|
||||||
|
|
||||||
if filteredUserApps.count > 0 {
|
|
||||||
// VStack {
|
|
||||||
// Header(title: "User", count: filteredUserApps.count, showPopover: $showPopover)
|
|
||||||
ForEach(filteredUserApps, id: \.self) { appInfo in
|
|
||||||
Section(header: Header(title: "User", count: filteredUserApps.count, showPopover: $showPopover)) {
|
|
||||||
AppListItems(search: $search, showPopover: $showPopover, appInfo: appInfo)
|
|
||||||
.padding(.vertical,5)
|
|
||||||
if appInfo != filteredUserApps.last {
|
|
||||||
Divider().padding(.horizontal, 5)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// AppListItems(search: $search, showPopover: $showPopover, appInfo: appInfo)
|
|
||||||
// if appInfo != filteredUserApps.last {
|
|
||||||
// Divider().padding(.horizontal, 5)
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if filteredSystemApps.count > 0 {
|
|
||||||
// VStack {
|
|
||||||
// Header(title: "System", count: filteredSystemApps.count, showPopover: $showPopover)
|
|
||||||
Section(header: Header(title: "System", count: filteredSystemApps.count, showPopover: $showPopover)) {
|
|
||||||
|
|
||||||
ForEach(filteredSystemApps, id: \.self) { appInfo in
|
|
||||||
AppListItems(search: $search, showPopover: $showPopover, appInfo: appInfo)
|
|
||||||
.padding(.vertical,5)
|
|
||||||
if appInfo != filteredSystemApps.last {
|
|
||||||
Divider().padding(.horizontal, 5)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
.padding(.horizontal)
|
|
||||||
|
|
||||||
}
|
|
||||||
.scrollIndicators(.never)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
.frame(width: sidebarWidth)
|
.frame(width: sidebarWidth)
|
||||||
@@ -267,6 +223,6 @@ struct Header: View {
|
|||||||
}
|
}
|
||||||
.padding(.vertical, 9)
|
.padding(.vertical, 9)
|
||||||
.padding(.leading, 6)
|
.padding(.leading, 6)
|
||||||
.background(!glass ? Color("windowBG") : .clear)
|
// .background(!glass ? Color("windowBG") : .clear)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
//
|
||||||
|
// AppsListView.swift
|
||||||
|
// Pearcleaner
|
||||||
|
//
|
||||||
|
// Created by Alin Lupascu on 3/4/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct AppsListView: View {
|
||||||
|
@Binding var search: String
|
||||||
|
@Binding var showPopover: Bool
|
||||||
|
var filteredUserApps: [AppInfo]
|
||||||
|
var filteredSystemApps: [AppInfo]
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
ScrollView {
|
||||||
|
LazyVStack(alignment: .leading, spacing: 0, pinnedViews: [.sectionHeaders]) {
|
||||||
|
if filteredUserApps.count > 0 {
|
||||||
|
SectionView(title: "User", count: filteredUserApps.count, apps: filteredUserApps, search: $search, showPopover: $showPopover)
|
||||||
|
}
|
||||||
|
|
||||||
|
if filteredSystemApps.count > 0 {
|
||||||
|
SectionView(title: "System", count: filteredSystemApps.count, apps: filteredSystemApps, search: $search, showPopover: $showPopover)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.horizontal)
|
||||||
|
}
|
||||||
|
.scrollIndicators(.never)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SectionView: View {
|
||||||
|
var title: String
|
||||||
|
var count: Int
|
||||||
|
var apps: [AppInfo]
|
||||||
|
@Binding var search: String
|
||||||
|
@Binding var showPopover: Bool
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(spacing: 0) {
|
||||||
|
Header(title: title, count: count, showPopover: $showPopover)
|
||||||
|
ForEach(apps, id: \.self) { appInfo in
|
||||||
|
AppListItems(search: $search, showPopover: $showPopover, appInfo: appInfo)
|
||||||
|
.padding(.vertical, 5)
|
||||||
|
if appInfo != apps.last {
|
||||||
|
Divider().padding(.horizontal, 5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//List {
|
||||||
|
// Section {
|
||||||
|
// ForEach(filteredUserApps, id:\.self) { element in
|
||||||
|
// Text(element.appName)
|
||||||
|
// }
|
||||||
|
// .listRowBackground(Color.clear)
|
||||||
|
// } header: {
|
||||||
|
// Text("User Apps")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Section {
|
||||||
|
// ForEach(filteredSystemApps, id:\.self) { element in
|
||||||
|
// Text(element.appName)
|
||||||
|
// }
|
||||||
|
// .listRowBackground(Color.clear)
|
||||||
|
// } header: {
|
||||||
|
// Text("System Apps")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
//.scrollContentBackground(.hidden)
|
||||||
|
//.background(.clear)
|
||||||
|
//.scrollIndicators(.never)
|
||||||
|
|
||||||
@@ -14,6 +14,7 @@ struct FilesView: View {
|
|||||||
@State private var showPop: Bool = false
|
@State private var showPop: Bool = false
|
||||||
@AppStorage("settings.general.mini") private var mini: Bool = false
|
@AppStorage("settings.general.mini") private var mini: Bool = false
|
||||||
@AppStorage("settings.sentinel.enable") private var sentinel: Bool = false
|
@AppStorage("settings.sentinel.enable") private var sentinel: Bool = false
|
||||||
|
@AppStorage("settings.general.instant") var instantSearch: Bool = true
|
||||||
@Environment(\.colorScheme) var colorScheme
|
@Environment(\.colorScheme) var colorScheme
|
||||||
@Binding var showPopover: Bool
|
@Binding var showPopover: Bool
|
||||||
@Binding var search: String
|
@Binding var search: String
|
||||||
@@ -35,8 +36,24 @@ struct FilesView: View {
|
|||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
.transition(.opacity)
|
.transition(.opacity)
|
||||||
} else {
|
} else {
|
||||||
VStack() {
|
// Titlebar
|
||||||
|
if mini {
|
||||||
|
HStack() {
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Button("Close") {
|
||||||
|
updateOnMain {
|
||||||
|
appState.appInfo = AppInfo.empty
|
||||||
|
search = ""
|
||||||
|
appState.currentView = .apps
|
||||||
|
showPopover = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.buttonStyle(NavButtonBottomBarStyle(image: "x.circle.fill", help: "Close"))
|
||||||
|
}
|
||||||
|
.padding([.horizontal, .top], 5)
|
||||||
|
}
|
||||||
|
VStack(spacing: 0) {
|
||||||
// Main Group
|
// Main Group
|
||||||
HStack(alignment: .center) {
|
HStack(alignment: .center) {
|
||||||
|
|
||||||
@@ -112,7 +129,7 @@ struct FilesView: View {
|
|||||||
|
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 20)
|
.padding(.horizontal, 20)
|
||||||
.padding(.top, 10)
|
.padding(.top, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
Divider()
|
Divider()
|
||||||
@@ -153,8 +170,8 @@ struct FilesView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)) {
|
)) {
|
||||||
Text("").tag(true)
|
Image(systemName: "checkmark.square").tag(true)
|
||||||
Text("").tag(false)
|
Image(systemName: "square").tag(false)
|
||||||
}
|
}
|
||||||
.pickerStyle(SegmentedPickerStyle())
|
.pickerStyle(SegmentedPickerStyle())
|
||||||
.frame(width: 100)
|
.frame(width: 100)
|
||||||
@@ -163,20 +180,6 @@ struct FilesView: View {
|
|||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
if mini {
|
|
||||||
|
|
||||||
Button("Close") {
|
|
||||||
updateOnMain {
|
|
||||||
appState.appInfo = AppInfo.empty
|
|
||||||
search = ""
|
|
||||||
appState.currentView = .apps
|
|
||||||
showPopover = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.buttonStyle(NavButtonBottomBarStyle(image: "x.circle.fill", help: "Close"))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if !appState.selectedItems.isEmpty {
|
if !appState.selectedItems.isEmpty {
|
||||||
Button("Uninstall") {
|
Button("Uninstall") {
|
||||||
Task {
|
Task {
|
||||||
@@ -191,13 +194,9 @@ struct FilesView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
var selectedItemsArray = Array(appState.selectedItems)
|
var selectedItemsArray = Array(appState.selectedItems)
|
||||||
.filter { !$0.path.contains(".Trash") }
|
|
||||||
.map { path in
|
|
||||||
return path.path.contains("Wrapper") ? path.deletingLastPathComponent().deletingLastPathComponent() : path
|
|
||||||
}
|
|
||||||
|
|
||||||
if let url = URL(string: appState.appInfo.path.absoluteString) {
|
if let url = URL(string: appState.appInfo.path.absoluteString) {
|
||||||
let appFolderURL = url.deletingLastPathComponent() // Get the immediate parent directory
|
let appFolderURL = appState.appInfo.path.absoluteString.contains("Wrapper") ? url.deletingLastPathComponent().deletingLastPathComponent().deletingLastPathComponent() : url.deletingLastPathComponent() // Get the immediate parent directory of regular and wrapped apps
|
||||||
|
|
||||||
if appFolderURL.path == "/Applications" || appFolderURL.path == "\(home)/Applications" {
|
if appFolderURL.path == "/Applications" || appFolderURL.path == "\(home)/Applications" {
|
||||||
// Do nothing, skip insertion
|
// Do nothing, skip insertion
|
||||||
@@ -207,7 +206,6 @@ struct FilesView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
killApp(appId: appState.appInfo.bundleIdentifier) {
|
killApp(appId: appState.appInfo.bundleIdentifier) {
|
||||||
moveFilesToTrash(at: selectedItemsArray) {
|
moveFilesToTrash(at: selectedItemsArray) {
|
||||||
withAnimation {
|
withAnimation {
|
||||||
@@ -226,7 +224,7 @@ struct FilesView: View {
|
|||||||
.buttonStyle(NavButtonBottomBarStyle(image: "trash.fill", help: "Uninstall"))
|
.buttonStyle(NavButtonBottomBarStyle(image: "trash.fill", help: "Uninstall"))
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Text("No files selected to clean").font(.title).foregroundStyle(Color("mode")).opacity(0.2)
|
Text("No files selected to remove").font(.title).foregroundStyle(Color("mode")).opacity(0.2)
|
||||||
.padding(5)
|
.padding(5)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,17 +232,17 @@ struct FilesView: View {
|
|||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
Picker("", selection: $selectedOption) {
|
Picker("", selection: $selectedOption) {
|
||||||
Text("").tag("Default")
|
Image(systemName: "textformat.abc").tag("Default")
|
||||||
Text("").tag("Size")
|
Image(systemName: "number").tag("Size")
|
||||||
}
|
}
|
||||||
.pickerStyle(SegmentedPickerStyle())
|
.pickerStyle(SegmentedPickerStyle())
|
||||||
.frame(width: 100)
|
.frame(width: 100)
|
||||||
.help("Sorting Selection")
|
.help("Sorting alphabetically or by size")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
.transition(.opacity)
|
.transition(.opacity)
|
||||||
.padding(20)
|
.padding([.horizontal, .bottom], 20)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,14 +252,12 @@ struct FilesView: View {
|
|||||||
func refreshAppList(_ appInfo: AppInfo) {
|
func refreshAppList(_ appInfo: AppInfo) {
|
||||||
showPopover = false
|
showPopover = false
|
||||||
let sortedApps = getSortedApps()
|
let sortedApps = getSortedApps()
|
||||||
updateOnMain {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||||
appState.sortedApps.userApps = []
|
|
||||||
appState.sortedApps.systemApps = []
|
|
||||||
appState.sortedApps.userApps = sortedApps.userApps
|
appState.sortedApps.userApps = sortedApps.userApps
|
||||||
appState.sortedApps.systemApps = sortedApps.systemApps
|
appState.sortedApps.systemApps = sortedApps.systemApps
|
||||||
}
|
// if instantSearch {
|
||||||
Task(priority: .high){
|
// loadAllPaths(allApps: sortedApps.userApps + sortedApps.systemApps, appState: appState, locations: locations)
|
||||||
loadAllPaths(allApps: sortedApps.userApps + sortedApps.systemApps, appState: appState, locations: locations)
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,49 +186,7 @@ struct MiniAppView: View {
|
|||||||
} else {
|
} else {
|
||||||
VStack(alignment: .center) {
|
VStack(alignment: .center) {
|
||||||
|
|
||||||
ScrollView {
|
AppsListView(search: $search, showPopover: $showPopover, filteredUserApps: filteredUserApps, filteredSystemApps: filteredSystemApps)
|
||||||
|
|
||||||
LazyVStack(alignment: .leading, spacing: 0, pinnedViews: [glass ? [] : .sectionHeaders]) {
|
|
||||||
|
|
||||||
if filteredUserApps.count > 0 {
|
|
||||||
|
|
||||||
// VStack {
|
|
||||||
// Header(title: "User", count: filteredUserApps.count, showPopover: $showPopover)
|
|
||||||
Section(header: Header(title: "User", count: filteredUserApps.count, showPopover: $showPopover)) {
|
|
||||||
|
|
||||||
ForEach(filteredUserApps, id: \.self) { appInfo in
|
|
||||||
AppListItems(search: $search, showPopover: $showPopover, appInfo: appInfo)
|
|
||||||
// .padding(.vertical,5)
|
|
||||||
if appInfo != filteredUserApps.last {
|
|
||||||
Divider().padding(.horizontal, 5)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if filteredSystemApps.count > 0 {
|
|
||||||
|
|
||||||
// VStack {
|
|
||||||
// Header(title: "System", count: filteredSystemApps.count, showPopover: $showPopover)
|
|
||||||
Section(header: Header(title: "System", count: filteredSystemApps.count, showPopover: $showPopover)) {
|
|
||||||
ForEach(filteredSystemApps, id: \.self) { appInfo in
|
|
||||||
AppListItems(search: $search, showPopover: $showPopover, appInfo: appInfo)
|
|
||||||
.padding(.vertical,5)
|
|
||||||
if appInfo != filteredSystemApps.last {
|
|
||||||
Divider().padding(.horizontal, 5)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
.padding(.horizontal)
|
|
||||||
|
|
||||||
}
|
|
||||||
.scrollIndicators(.never)
|
|
||||||
|
|
||||||
if appState.currentView != .empty {
|
if appState.currentView != .empty {
|
||||||
SearchBarMiniBottom(search: $search).background(.ultraThinMaterial)
|
SearchBarMiniBottom(search: $search).background(.ultraThinMaterial)
|
||||||
|
|||||||
@@ -37,8 +37,38 @@ struct ZombieView: View {
|
|||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
.transition(.opacity)
|
.transition(.opacity)
|
||||||
} else {
|
} else {
|
||||||
VStack() {
|
// Titlebar
|
||||||
|
if mini {
|
||||||
|
HStack(spacing: 0) {
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
Button("Rescan") {
|
||||||
|
updateOnMain {
|
||||||
|
appState.zombieFile = .empty
|
||||||
|
appState.showProgress.toggle()
|
||||||
|
if instantSearch {
|
||||||
|
reversePathsSearch(appState: appState, locations: locations)
|
||||||
|
} else {
|
||||||
|
loadAllPaths(allApps: appState.sortedApps.userApps + appState.sortedApps.systemApps, appState: appState, locations: locations, reverseAddon: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.buttonStyle(NavButtonBottomBarStyle(image: "arrow.counterclockwise.circle.fill", help: "Rescan files"))
|
||||||
|
|
||||||
|
Button("Close") {
|
||||||
|
updateOnMain {
|
||||||
|
appState.appInfo = AppInfo.empty
|
||||||
|
search = ""
|
||||||
|
appState.currentView = .apps
|
||||||
|
showPopover = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.buttonStyle(NavButtonBottomBarStyle(image: "x.circle.fill", help: "Close"))
|
||||||
|
}
|
||||||
|
.padding([.horizontal, .top], 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
VStack() {
|
||||||
// Main Group
|
// Main Group
|
||||||
HStack() {
|
HStack() {
|
||||||
|
|
||||||
@@ -74,7 +104,7 @@ struct ZombieView: View {
|
|||||||
|
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 20)
|
.padding(.horizontal, 20)
|
||||||
.padding(.top, 10)
|
.padding(.top, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
Divider()
|
Divider()
|
||||||
@@ -116,8 +146,8 @@ struct ZombieView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)) {
|
)) {
|
||||||
Text("").tag(true)
|
Image(systemName: "checkmark.square").tag(true)
|
||||||
Text("").tag(false)
|
Image(systemName: "square").tag(false)
|
||||||
}
|
}
|
||||||
.pickerStyle(SegmentedPickerStyle())
|
.pickerStyle(SegmentedPickerStyle())
|
||||||
.frame(width: 100)
|
.frame(width: 100)
|
||||||
@@ -126,23 +156,6 @@ struct ZombieView: View {
|
|||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
if mini {
|
|
||||||
Button("Close") {
|
|
||||||
updateOnMain {
|
|
||||||
appState.appInfo = AppInfo.empty
|
|
||||||
search = ""
|
|
||||||
appState.currentView = .apps
|
|
||||||
showPopover = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.buttonStyle(NavButtonBottomBarStyle(image: "x.circle.fill", help: "Close"))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if !appState.selectedZombieItems.isEmpty {
|
if !appState.selectedZombieItems.isEmpty {
|
||||||
Button("Remove") {
|
Button("Remove") {
|
||||||
Task {
|
Task {
|
||||||
@@ -158,7 +171,6 @@ struct ZombieView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let selectedItemsArray = Array(appState.selectedZombieItems)
|
let selectedItemsArray = Array(appState.selectedZombieItems)
|
||||||
.filter { !$0.path.contains(".Trash") }
|
|
||||||
|
|
||||||
killApp(appId: appState.appInfo.bundleIdentifier) {
|
killApp(appId: appState.appInfo.bundleIdentifier) {
|
||||||
moveFilesToTrash(at: selectedItemsArray) {
|
moveFilesToTrash(at: selectedItemsArray) {
|
||||||
@@ -166,9 +178,6 @@ struct ZombieView: View {
|
|||||||
showPopover = false
|
showPopover = false
|
||||||
updateOnMain {
|
updateOnMain {
|
||||||
appState.isReminderVisible.toggle()
|
appState.isReminderVisible.toggle()
|
||||||
if sentinel {
|
|
||||||
launchctl(load: true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -183,53 +192,25 @@ struct ZombieView: View {
|
|||||||
.padding(5)
|
.padding(5)
|
||||||
}
|
}
|
||||||
|
|
||||||
Button("Rescan") {
|
|
||||||
updateOnMain {
|
|
||||||
appState.zombieFile = .empty
|
|
||||||
appState.showProgress.toggle()
|
|
||||||
if instantSearch {
|
|
||||||
reversePathsSearch(appState: appState, locations: locations)
|
|
||||||
} else {
|
|
||||||
loadAllPaths(allApps: appState.sortedApps.userApps + appState.sortedApps.systemApps, appState: appState, locations: locations, reverseAddon: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.buttonStyle(NavButtonBottomBarStyle(image: "arrow.counterclockwise.circle.fill", help: "Rescan files"))
|
|
||||||
|
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
Picker("", selection: $selectedOption) {
|
Picker("", selection: $selectedOption) {
|
||||||
Text("").tag("Default")
|
Image(systemName: "textformat.abc").tag("Default")
|
||||||
Text("").tag("Size")
|
Image(systemName: "number").tag("Size")
|
||||||
}
|
}
|
||||||
.pickerStyle(SegmentedPickerStyle())
|
.pickerStyle(SegmentedPickerStyle())
|
||||||
.frame(width: 100)
|
.frame(width: 100)
|
||||||
.help("Sorting Selection")
|
.help("Sorting alphabetically or by size")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
.transition(.opacity)
|
.transition(.opacity)
|
||||||
.padding(20)
|
.padding([.horizontal, .bottom], 20)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func refreshAppList(_ appInfo: AppInfo) {
|
|
||||||
showPopover = false
|
|
||||||
let sortedApps = getSortedApps()
|
|
||||||
updateOnMain {
|
|
||||||
appState.sortedApps.userApps = []
|
|
||||||
appState.sortedApps.systemApps = []
|
|
||||||
appState.sortedApps.userApps = sortedApps.userApps
|
|
||||||
appState.sortedApps.systemApps = sortedApps.systemApps
|
|
||||||
}
|
|
||||||
Task(priority: .high){
|
|
||||||
loadAllPaths(allApps: sortedApps.userApps + sortedApps.systemApps, appState: appState, locations: locations)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class NewWin: NSWindowController {
|
|||||||
window.titleVisibility = .hidden
|
window.titleVisibility = .hidden
|
||||||
window.titlebarAppearsTransparent = true
|
window.titlebarAppearsTransparent = true
|
||||||
window.center()
|
window.center()
|
||||||
window.title = "Support Admin"
|
window.title = "Pearcleaner"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,10 +65,12 @@ class NewWin: NSWindowController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func makeNewView(appState: AppState, newWin: NewWindow) -> some View {
|
private func makeNewView(appState: AppState, newWin: NewWindow) -> some View {
|
||||||
|
|
||||||
switch newWin {
|
switch newWin {
|
||||||
case .update:
|
case .update:
|
||||||
return AnyView(UpdateView()
|
return AnyView(UpdateView()
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
|
.background(.black.opacity(0.2))
|
||||||
.environmentObject(appState))
|
.environmentObject(appState))
|
||||||
case .no_update:
|
case .no_update:
|
||||||
return AnyView(NoUpdateView()
|
return AnyView(NoUpdateView()
|
||||||
@@ -77,6 +79,8 @@ class NewWin: NSWindowController {
|
|||||||
case .perm:
|
case .perm:
|
||||||
return AnyView(PermView()
|
return AnyView(PermView()
|
||||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
|
.background(.black.opacity(0.2))
|
||||||
|
|
||||||
.environmentObject(appState))
|
.environmentObject(appState))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,34 +17,69 @@ struct PermView: View {
|
|||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
Text("Attention")
|
Text("Pearcleaner Permissions")
|
||||||
.font(.title)
|
.font(.title)
|
||||||
.bold()
|
.bold()
|
||||||
.padding(.vertical)
|
.padding(.vertical)
|
||||||
|
.padding(.top, 5)
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
}
|
}
|
||||||
.background(.red)
|
|
||||||
|
|
||||||
Text("Pearcleaner requires the following permissions:")
|
Divider()
|
||||||
.font(.title3)
|
.padding(.bottom)
|
||||||
.fontWeight(.semibold)
|
|
||||||
.padding(.vertical)
|
|
||||||
|
|
||||||
ScrollView {
|
Spacer()
|
||||||
Text(" - Full Disk Access permission to find and delete files in non-user locations.\n - Accessibility permission to delete files via Finder which allows for the Undo function.\n\nAdd Pearcleaner in both Privacy panes via the + or by dragging the app over the pane. If the app is already pre-populated in the list, just toggle On. Restart app when both permissions are granted.")
|
|
||||||
.font(.body)
|
VStack(alignment: .leading, spacing: 20) {
|
||||||
.multilineTextAlignment(.leading)
|
HStack(alignment: .top, spacing: 20) {
|
||||||
.padding(.horizontal, 20)
|
Image(systemName: "externaldrive")
|
||||||
|
.resizable()
|
||||||
|
.scaledToFit()
|
||||||
|
.frame(width: 20, height: 20)
|
||||||
|
.foregroundStyle(.gray)
|
||||||
|
Text("Full Disk Access permission to find and delete files in system paths")
|
||||||
|
.font(.callout)
|
||||||
|
.foregroundStyle(.gray)
|
||||||
|
}
|
||||||
|
|
||||||
|
HStack(alignment: .top, spacing: 20) {
|
||||||
|
Image(systemName: "accessibility")
|
||||||
|
.resizable()
|
||||||
|
.scaledToFit()
|
||||||
|
.frame(width: 20, height: 20)
|
||||||
|
.foregroundStyle(.gray)
|
||||||
|
Text("Accessibility permission to delete files via Finder")
|
||||||
|
.font(.callout)
|
||||||
|
.foregroundStyle(.gray)
|
||||||
|
}
|
||||||
|
|
||||||
|
HStack(alignment: .top, spacing: 20) {
|
||||||
|
Image(systemName: "info.circle")
|
||||||
|
.resizable()
|
||||||
|
.scaledToFit()
|
||||||
|
.frame(width: 20, height: 20)
|
||||||
|
.foregroundStyle(.gray)
|
||||||
|
Text("Add Pearcleaner in both Privacy panes via the + or by dragging the app over the pane. If the app is already pre-populated in the list, just toggle On if neeeded. Restart app when both permissions are granted")
|
||||||
|
.font(.callout)
|
||||||
|
.foregroundStyle(.gray)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.frame(height: 130)
|
.padding(.horizontal, 20)
|
||||||
.padding(.horizontal)
|
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
|
|
||||||
|
Button(action: {
|
||||||
|
relaunchApp(afterDelay: 1)
|
||||||
|
}) {
|
||||||
|
Text("Restart")
|
||||||
|
}
|
||||||
|
.buttonStyle(SimpleButtonBrightStyle(icon: "arrow.uturn.left.circle", help: "Restart", color: .red))
|
||||||
|
.padding()
|
||||||
|
|
||||||
Button(action: {
|
Button(action: {
|
||||||
if let url = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_AllFiles") {
|
if let url = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_AllFiles") {
|
||||||
NSWorkspace.shared.open(url)
|
NSWorkspace.shared.open(url)
|
||||||
@@ -52,7 +87,8 @@ struct PermView: View {
|
|||||||
}) {
|
}) {
|
||||||
Text("Full Disk Access")
|
Text("Full Disk Access")
|
||||||
}
|
}
|
||||||
.buttonStyle(WindowActionButton(action: .accept))
|
.buttonStyle(SimpleButtonBrightStyle(icon: "externaldrive", help: "Full Disk", color: .accentColor))
|
||||||
|
|
||||||
.padding()
|
.padding()
|
||||||
|
|
||||||
Button(action: {
|
Button(action: {
|
||||||
@@ -62,16 +98,10 @@ struct PermView: View {
|
|||||||
}) {
|
}) {
|
||||||
Text("Accessibility")
|
Text("Accessibility")
|
||||||
}
|
}
|
||||||
.buttonStyle(WindowActionButton(action: .accept))
|
.buttonStyle(SimpleButtonBrightStyle(icon: "accessibility", help: "Accessibility", color: .accentColor))
|
||||||
.padding()
|
.padding()
|
||||||
|
|
||||||
Button(action: {
|
|
||||||
relaunchApp(afterDelay: 1)
|
|
||||||
}) {
|
|
||||||
Text("Restart")
|
|
||||||
}
|
|
||||||
.buttonStyle(WindowActionButton(action: .cancel))
|
|
||||||
.padding()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ struct UpdateView: View {
|
|||||||
let isAppInAppsDir = isAppInApplicationsDir()
|
let isAppInAppsDir = isAppInApplicationsDir()
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack(spacing: 5) {
|
||||||
HStack {
|
HStack {
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
@@ -29,36 +29,28 @@ struct UpdateView: View {
|
|||||||
Text("v\(appState.releases.first?.tag_name ?? "")")
|
Text("v\(appState.releases.first?.tag_name ?? "")")
|
||||||
.font(.title3)
|
.font(.title3)
|
||||||
.fontWeight(.semibold)
|
.fontWeight(.semibold)
|
||||||
.foregroundStyle(Color.white.opacity(0.5))
|
.opacity(0.5)
|
||||||
.padding()
|
.padding()
|
||||||
|
|
||||||
}
|
}
|
||||||
.background(.blue)
|
|
||||||
|
|
||||||
Spacer()
|
Divider()
|
||||||
|
.padding([.horizontal])
|
||||||
|
|
||||||
ScrollView {
|
ScrollView {
|
||||||
Text("\(appState.releases.first?.body ?? "No release information")")
|
Text("\(appState.releases.first?.modifiedBody ?? "No release information")")
|
||||||
.font(.body)
|
.font(.body)
|
||||||
.multilineTextAlignment(.leading)
|
.multilineTextAlignment(.leading)
|
||||||
.padding(.horizontal, 20)
|
.padding(20)
|
||||||
}
|
}
|
||||||
.frame(height: 160)
|
|
||||||
.padding()
|
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
if !isAppInAppsDir {
|
if !isAppInAppsDir {
|
||||||
HStack {
|
Text("Please move Pearcleaner to the **Applications** folder before updating!")
|
||||||
Text("Pearcleaner not in /Applications directory. Updater could have permission issues updating files.")
|
.font(.callout)
|
||||||
.font(.footnote)
|
.foregroundStyle(.red)
|
||||||
.foregroundStyle(.red)
|
.padding(.top, 0)
|
||||||
.padding()
|
|
||||||
.lineLimit(2)
|
|
||||||
.fixedSize(horizontal: false, vertical: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VStack() {
|
VStack() {
|
||||||
@@ -73,7 +65,7 @@ struct UpdateView: View {
|
|||||||
Button(action: NewWin.close) {
|
Button(action: NewWin.close) {
|
||||||
Text("Cancel")
|
Text("Cancel")
|
||||||
}
|
}
|
||||||
.buttonStyle(WindowActionButton(action: .cancel))
|
.buttonStyle(SimpleButtonBrightStyle(icon: "x.circle", help: "Close", color: .red))
|
||||||
|
|
||||||
if appState.progressBar.1 != 1.0 {
|
if appState.progressBar.1 != 1.0 {
|
||||||
Button(action: {
|
Button(action: {
|
||||||
@@ -81,7 +73,7 @@ struct UpdateView: View {
|
|||||||
}) {
|
}) {
|
||||||
Text("Update")
|
Text("Update")
|
||||||
}
|
}
|
||||||
.buttonStyle(WindowActionButton(action: .accept))
|
.buttonStyle(SimpleButtonBrightStyle(icon: "arrow.down.circle", help: "Update", color: .accentColor))
|
||||||
} else {
|
} else {
|
||||||
Button(action: {
|
Button(action: {
|
||||||
NewWin.close()
|
NewWin.close()
|
||||||
@@ -89,7 +81,7 @@ struct UpdateView: View {
|
|||||||
}) {
|
}) {
|
||||||
Text("Restart")
|
Text("Restart")
|
||||||
}
|
}
|
||||||
.buttonStyle(WindowActionButton(action: .accept))
|
.buttonStyle(SimpleButtonBrightStyle(icon: "arrow.uturn.left.circle", help: "Restart", color: .accentColor))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -112,7 +104,7 @@ struct NoUpdateView: View {
|
|||||||
@EnvironmentObject var appState: AppState
|
@EnvironmentObject var appState: AppState
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack(spacing: 5) {
|
||||||
HStack {
|
HStack {
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
@@ -128,19 +120,19 @@ struct NoUpdateView: View {
|
|||||||
Text("v\(appState.releases.first?.tag_name ?? "")")
|
Text("v\(appState.releases.first?.tag_name ?? "")")
|
||||||
.font(.title3)
|
.font(.title3)
|
||||||
.fontWeight(.semibold)
|
.fontWeight(.semibold)
|
||||||
.foregroundStyle(Color.white.opacity(0.5))
|
.opacity(0.5)
|
||||||
.padding()
|
.padding()
|
||||||
|
|
||||||
}
|
}
|
||||||
.background(.blue)
|
|
||||||
|
|
||||||
Spacer()
|
Divider()
|
||||||
|
.padding([.horizontal])
|
||||||
|
|
||||||
Text("Pearcleaner is on the most current release available, but you may force a re-download of the same version below.")
|
Text("Pearcleaner is on the most current release available, but you may force a re-download of the same version below.")
|
||||||
.font(.body)
|
.font(.body)
|
||||||
.lineLimit(3)
|
.lineLimit(3)
|
||||||
.multilineTextAlignment(.leading)
|
.multilineTextAlignment(.leading)
|
||||||
.padding(20)
|
.padding()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -160,14 +152,14 @@ struct NoUpdateView: View {
|
|||||||
}) {
|
}) {
|
||||||
Text("Force Update")
|
Text("Force Update")
|
||||||
}
|
}
|
||||||
.buttonStyle(WindowActionButton(action: .cancel))
|
.buttonStyle(SimpleButtonBrightStyle(icon: "arrow.down.circle", help: "Force-Update", color: .red))
|
||||||
|
|
||||||
Button(action: {
|
Button(action: {
|
||||||
NewWin.close()
|
NewWin.close()
|
||||||
}) {
|
}) {
|
||||||
Text("Okay")
|
Text("Okay")
|
||||||
}
|
}
|
||||||
.buttonStyle(WindowActionButton(action: .accept))
|
.buttonStyle(SimpleButtonBrightStyle(icon: "checkmark.circle", help: "Ok", color: .accentColor))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +171,7 @@ struct NoUpdateView: View {
|
|||||||
}) {
|
}) {
|
||||||
Text("Restart")
|
Text("Restart")
|
||||||
}
|
}
|
||||||
.buttonStyle(WindowActionButton(action: .accept))
|
.buttonStyle(SimpleButtonBrightStyle(icon: "arrow.uturn.left.circle", help: "Restart", color: .accentColor))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.bottom)
|
.padding(.bottom)
|
||||||
@@ -190,7 +182,6 @@ struct NoUpdateView: View {
|
|||||||
.padding(EdgeInsets(top: -25, leading: 0, bottom: 25, trailing: 0))
|
.padding(EdgeInsets(top: -25, leading: 0, bottom: 25, trailing: 0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import FileWatcher
|
|
||||||
import AppKit
|
import AppKit
|
||||||
|
import FileWatcher
|
||||||
|
|
||||||
// Start Trash monitoring
|
// Start Trash monitoring
|
||||||
fileWatcher()
|
fileWatcher()
|
||||||
@@ -31,8 +31,16 @@ func checkApp(file: String) {
|
|||||||
let app = URL(fileURLWithPath: file)
|
let app = URL(fileURLWithPath: file)
|
||||||
let appExt = app.pathExtension
|
let appExt = app.pathExtension
|
||||||
if appExt == "app" {
|
if appExt == "app" {
|
||||||
if FileManager.default.isInTrash(app) {
|
if let appBundle = Bundle(url: app) {
|
||||||
NSWorkspace.shared.open(URL(string: "pear://com.alienator88.Pearcleaner?path=\(file)")!)
|
if appBundle.bundleIdentifier == "com.alienator88.Pearcleaner" {
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
if FileManager.default.isInTrash(app) {
|
||||||
|
NSWorkspace.shared.open(URL(string: "pear://com.alienator88.Pearcleaner?path=\(file)")!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print("Error: Unable to get bundle information for \(file)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user