mirror of
https://github.com/exituser/Pearcleaner.git
synced 2026-09-17 06:09:01 +00:00
v3.6.0
This commit is contained in:
@@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
C7045A282B03E71D00376976 /* MiniMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7045A272B03E71D00376976 /* MiniMode.swift */; };
|
C7045A282B03E71D00376976 /* MiniMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7045A272B03E71D00376976 /* MiniMode.swift */; };
|
||||||
C7045A2A2B03FAF000376976 /* TopBarMini.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7045A292B03FAF000376976 /* TopBarMini.swift */; };
|
|
||||||
C7045A322B068AD700376976 /* NewWin.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7045A312B068AD700376976 /* NewWin.swift */; };
|
C7045A322B068AD700376976 /* NewWin.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7045A312B068AD700376976 /* NewWin.swift */; };
|
||||||
C7045A342B068B2900376976 /* UpdateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7045A332B068B2900376976 /* UpdateView.swift */; };
|
C7045A342B068B2900376976 /* UpdateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7045A332B068B2900376976 /* UpdateView.swift */; };
|
||||||
C7045A362B068DD700376976 /* PermView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7045A352B068DD700376976 /* PermView.swift */; };
|
C7045A362B068DD700376976 /* PermView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7045A352B068DD700376976 /* PermView.swift */; };
|
||||||
@@ -39,7 +38,6 @@
|
|||||||
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 */; };
|
||||||
C7D31D482AFEB23700C7ED9E /* TopBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7D31D472AFEB23700C7ED9E /* TopBar.swift */; };
|
|
||||||
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 */; };
|
||||||
C7DC1FEE2B9F7D3D009AC317 /* features.json in Resources */ = {isa = PBXBuildFile; fileRef = C7DC1FED2B9F7D3D009AC317 /* features.json */; };
|
C7DC1FEE2B9F7D3D009AC317 /* features.json in Resources */ = {isa = PBXBuildFile; fileRef = C7DC1FED2B9F7D3D009AC317 /* features.json */; };
|
||||||
@@ -47,11 +45,11 @@
|
|||||||
C7DD49EE2BAB7F6000CCBA16 /* ReversePathsFetch.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7DD49ED2BAB7F6000CCBA16 /* ReversePathsFetch.swift */; };
|
C7DD49EE2BAB7F6000CCBA16 /* ReversePathsFetch.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7DD49ED2BAB7F6000CCBA16 /* ReversePathsFetch.swift */; };
|
||||||
C7DD49F02BABA14400CCBA16 /* Folders.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7DD49EF2BABA14400CCBA16 /* Folders.swift */; };
|
C7DD49F02BABA14400CCBA16 /* Folders.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7DD49EF2BABA14400CCBA16 /* Folders.swift */; };
|
||||||
C7DE672B2BA6343D00EB1633 /* MenuBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7DE672A2BA6343D00EB1633 /* MenuBarItem.swift */; };
|
C7DE672B2BA6343D00EB1633 /* MenuBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7DE672A2BA6343D00EB1633 /* MenuBarItem.swift */; };
|
||||||
C7DE672D2BA6356500EB1633 /* MenuBarMiniAppView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7DE672C2BA6356500EB1633 /* MenuBarMiniAppView.swift */; };
|
|
||||||
C7ED86B12BA8A35500F13DE4 /* Interface.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7ED86B02BA8A35500F13DE4 /* Interface.swift */; };
|
C7ED86B12BA8A35500F13DE4 /* Interface.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7ED86B02BA8A35500F13DE4 /* Interface.swift */; };
|
||||||
C7ED86B32BA8ED8800F13DE4 /* Trash.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7ED86B22BA8ED8800F13DE4 /* Trash.swift */; };
|
C7ED86B32BA8ED8800F13DE4 /* Trash.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7ED86B22BA8ED8800F13DE4 /* Trash.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 */; };
|
C7FB173B2B96321300B96F9A /* AppsListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7FB173A2B96321300B96F9A /* AppsListView.swift */; };
|
||||||
|
C7FEBA112BDC422200AE195F /* Searchbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7FEBA102BDC422200AE195F /* Searchbar.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@@ -99,7 +97,6 @@
|
|||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
C7045A272B03E71D00376976 /* MiniMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MiniMode.swift; sourceTree = "<group>"; };
|
C7045A272B03E71D00376976 /* MiniMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MiniMode.swift; sourceTree = "<group>"; };
|
||||||
C7045A292B03FAF000376976 /* TopBarMini.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopBarMini.swift; sourceTree = "<group>"; };
|
|
||||||
C7045A312B068AD700376976 /* NewWin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewWin.swift; sourceTree = "<group>"; };
|
C7045A312B068AD700376976 /* NewWin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewWin.swift; sourceTree = "<group>"; };
|
||||||
C7045A332B068B2900376976 /* UpdateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateView.swift; sourceTree = "<group>"; };
|
C7045A332B068B2900376976 /* UpdateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateView.swift; sourceTree = "<group>"; };
|
||||||
C7045A352B068DD700376976 /* PermView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermView.swift; sourceTree = "<group>"; };
|
C7045A352B068DD700376976 /* PermView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermView.swift; sourceTree = "<group>"; };
|
||||||
@@ -135,7 +132,6 @@
|
|||||||
C7A9CE462B89164700EB6E78 /* Authorization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Authorization.swift; sourceTree = "<group>"; };
|
C7A9CE462B89164700EB6E78 /* Authorization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Authorization.swift; sourceTree = "<group>"; };
|
||||||
C7ACADE52B92A737000B5845 /* Features.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Features.swift; sourceTree = "<group>"; };
|
C7ACADE52B92A737000B5845 /* Features.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Features.swift; sourceTree = "<group>"; };
|
||||||
C7CF47232B3B3F1700979C5F /* WindowSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowSettings.swift; sourceTree = "<group>"; };
|
C7CF47232B3B3F1700979C5F /* WindowSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WindowSettings.swift; sourceTree = "<group>"; };
|
||||||
C7D31D472AFEB23700C7ED9E /* TopBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TopBar.swift; sourceTree = "<group>"; };
|
|
||||||
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>"; };
|
||||||
C7DC1FED2B9F7D3D009AC317 /* features.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = features.json; sourceTree = SOURCE_ROOT; };
|
C7DC1FED2B9F7D3D009AC317 /* features.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = features.json; sourceTree = SOURCE_ROOT; };
|
||||||
@@ -143,11 +139,11 @@
|
|||||||
C7DD49ED2BAB7F6000CCBA16 /* ReversePathsFetch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReversePathsFetch.swift; sourceTree = "<group>"; };
|
C7DD49ED2BAB7F6000CCBA16 /* ReversePathsFetch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReversePathsFetch.swift; sourceTree = "<group>"; };
|
||||||
C7DD49EF2BABA14400CCBA16 /* Folders.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Folders.swift; sourceTree = "<group>"; };
|
C7DD49EF2BABA14400CCBA16 /* Folders.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Folders.swift; sourceTree = "<group>"; };
|
||||||
C7DE672A2BA6343D00EB1633 /* MenuBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuBarItem.swift; sourceTree = "<group>"; };
|
C7DE672A2BA6343D00EB1633 /* MenuBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuBarItem.swift; sourceTree = "<group>"; };
|
||||||
C7DE672C2BA6356500EB1633 /* MenuBarMiniAppView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuBarMiniAppView.swift; sourceTree = "<group>"; };
|
|
||||||
C7ED86B02BA8A35500F13DE4 /* Interface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Interface.swift; sourceTree = "<group>"; };
|
C7ED86B02BA8A35500F13DE4 /* Interface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Interface.swift; sourceTree = "<group>"; };
|
||||||
C7ED86B22BA8ED8800F13DE4 /* Trash.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Trash.swift; sourceTree = "<group>"; };
|
C7ED86B22BA8ED8800F13DE4 /* Trash.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Trash.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>"; };
|
C7FB173A2B96321300B96F9A /* AppsListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppsListView.swift; sourceTree = "<group>"; };
|
||||||
|
C7FEBA102BDC422200AE195F /* Searchbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Searchbar.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@@ -300,12 +296,10 @@
|
|||||||
C77B90222AF2D616009CC655 /* FilesView.swift */,
|
C77B90222AF2D616009CC655 /* FilesView.swift */,
|
||||||
C71848432B8D2D600046CB13 /* ZombieView.swift */,
|
C71848432B8D2D600046CB13 /* ZombieView.swift */,
|
||||||
C76D08542AF89CDE00D07867 /* RegularMode.swift */,
|
C76D08542AF89CDE00D07867 /* RegularMode.swift */,
|
||||||
C7D31D472AFEB23700C7ED9E /* TopBar.swift */,
|
|
||||||
C7045A292B03FAF000376976 /* TopBarMini.swift */,
|
|
||||||
C7D31D492AFEB26700C7ED9E /* AppListItems.swift */,
|
C7D31D492AFEB26700C7ED9E /* AppListItems.swift */,
|
||||||
C7045A272B03E71D00376976 /* MiniMode.swift */,
|
C7045A272B03E71D00376976 /* MiniMode.swift */,
|
||||||
C7FB173A2B96321300B96F9A /* AppsListView.swift */,
|
C7FB173A2B96321300B96F9A /* AppsListView.swift */,
|
||||||
C7DE672C2BA6356500EB1633 /* MenuBarMiniAppView.swift */,
|
C7FEBA102BDC422200AE195F /* Searchbar.swift */,
|
||||||
);
|
);
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -467,11 +461,9 @@
|
|||||||
C7DD49EE2BAB7F6000CCBA16 /* ReversePathsFetch.swift in Sources */,
|
C7DD49EE2BAB7F6000CCBA16 /* ReversePathsFetch.swift in Sources */,
|
||||||
C7045A322B068AD700376976 /* NewWin.swift in Sources */,
|
C7045A322B068AD700376976 /* NewWin.swift in Sources */,
|
||||||
C7DD49F02BABA14400CCBA16 /* Folders.swift in Sources */,
|
C7DD49F02BABA14400CCBA16 /* Folders.swift in Sources */,
|
||||||
C7DE672D2BA6356500EB1633 /* MenuBarMiniAppView.swift in Sources */,
|
|
||||||
C7ED86B32BA8ED8800F13DE4 /* Trash.swift in Sources */,
|
C7ED86B32BA8ED8800F13DE4 /* Trash.swift in Sources */,
|
||||||
C7D31D512AFF00F300C7ED9E /* Locations.swift in Sources */,
|
C7D31D512AFF00F300C7ED9E /* Locations.swift in Sources */,
|
||||||
C77B901A2AF1938F009CC655 /* Logic.swift in Sources */,
|
C77B901A2AF1938F009CC655 /* Logic.swift in Sources */,
|
||||||
C7045A2A2B03FAF000376976 /* TopBarMini.swift in Sources */,
|
|
||||||
C77B901C2AF193A3009CC655 /* Styles.swift in Sources */,
|
C77B901C2AF193A3009CC655 /* Styles.swift in Sources */,
|
||||||
C7045A282B03E71D00376976 /* MiniMode.swift in Sources */,
|
C7045A282B03E71D00376976 /* MiniMode.swift in Sources */,
|
||||||
C7ED86B12BA8A35500F13DE4 /* Interface.swift in Sources */,
|
C7ED86B12BA8A35500F13DE4 /* Interface.swift in Sources */,
|
||||||
@@ -488,12 +480,12 @@
|
|||||||
C771CB762BD028AF00C33A18 /* SegmentedPicker.swift in Sources */,
|
C771CB762BD028AF00C33A18 /* SegmentedPicker.swift in Sources */,
|
||||||
C74412C72BBF249000DDFCA8 /* AppPathsFetch.swift in Sources */,
|
C74412C72BBF249000DDFCA8 /* AppPathsFetch.swift in Sources */,
|
||||||
C79D05202BC99EB40083F976 /* ThemeManager.swift in Sources */,
|
C79D05202BC99EB40083F976 /* ThemeManager.swift in Sources */,
|
||||||
C7D31D482AFEB23700C7ED9E /* TopBar.swift in Sources */,
|
|
||||||
C74FDC632BCD833D00B8960F /* Conditions.swift in Sources */,
|
C74FDC632BCD833D00B8960F /* Conditions.swift in Sources */,
|
||||||
C7ACADE62B92A737000B5845 /* Features.swift in Sources */,
|
C7ACADE62B92A737000B5845 /* Features.swift in Sources */,
|
||||||
C7F539382AF60865007DF1B2 /* Utilities.swift in Sources */,
|
C7F539382AF60865007DF1B2 /* Utilities.swift in Sources */,
|
||||||
C76D08552AF89CDE00D07867 /* RegularMode.swift in Sources */,
|
C76D08552AF89CDE00D07867 /* RegularMode.swift in Sources */,
|
||||||
C7A9CE472B89164700EB6E78 /* Authorization.swift in Sources */,
|
C7A9CE472B89164700EB6E78 /* Authorization.swift in Sources */,
|
||||||
|
C7FEBA112BDC422200AE195F /* Searchbar.swift in Sources */,
|
||||||
C7CF47242B3B3F1700979C5F /* WindowSettings.swift in Sources */,
|
C7CF47242B3B3F1700979C5F /* WindowSettings.swift in Sources */,
|
||||||
C77B90232AF2D616009CC655 /* FilesView.swift in Sources */,
|
C77B90232AF2D616009CC655 /* FilesView.swift in Sources */,
|
||||||
);
|
);
|
||||||
@@ -564,8 +556,8 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
APP_BUILD = 38;
|
APP_BUILD = 39;
|
||||||
APP_VERSION = 3.5.4;
|
APP_VERSION = 3.6.0;
|
||||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
@@ -634,8 +626,8 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
APP_BUILD = 38;
|
APP_BUILD = 39;
|
||||||
APP_VERSION = 3.5.4;
|
APP_VERSION = 3.6.0;
|
||||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ struct AppCommands: Commands {
|
|||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||||
appState.sortedApps = sortedApps
|
appState.sortedApps = sortedApps
|
||||||
for app in appState.trashedFiles {
|
for app in appState.trashedFiles {
|
||||||
AppPathFinder(appInfo: app, appState: appState, locations: locations).findPaths()
|
AppPathFinder(appInfo: app, appState: appState, locations: locations, undo: true).findPaths()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,16 +16,18 @@ class AppPathFinder {
|
|||||||
private var locations: Locations
|
private var locations: Locations
|
||||||
private var backgroundRun: Bool
|
private var backgroundRun: Bool
|
||||||
private var reverseAddon: Bool
|
private var reverseAddon: Bool
|
||||||
|
private var undo: Bool
|
||||||
private var completion: () -> Void = {}
|
private var completion: () -> Void = {}
|
||||||
private var collection: [URL] = []
|
private var collection: [URL] = []
|
||||||
private let collectionAccessQueue = DispatchQueue(label: "com.alienator88.Pearcleaner.appPathFinder.collectionAccess")
|
private let collectionAccessQueue = DispatchQueue(label: "com.alienator88.Pearcleaner.appPathFinder.collectionAccess")
|
||||||
|
|
||||||
init(appInfo: AppInfo = .empty, appState: AppState, locations: Locations, backgroundRun: Bool = false, reverseAddon: Bool = false, completion: @escaping () -> Void = {}) {
|
init(appInfo: AppInfo = .empty, appState: AppState, locations: Locations, backgroundRun: Bool = false, reverseAddon: Bool = false, undo: Bool = false, completion: @escaping () -> Void = {}) {
|
||||||
self.appInfo = appInfo
|
self.appInfo = appInfo
|
||||||
self.appState = appState
|
self.appState = appState
|
||||||
self.locations = locations
|
self.locations = locations
|
||||||
self.backgroundRun = backgroundRun
|
self.backgroundRun = backgroundRun
|
||||||
self.reverseAddon = reverseAddon
|
self.reverseAddon = reverseAddon
|
||||||
|
self.undo = undo
|
||||||
self.completion = completion
|
self.completion = completion
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,7 +308,10 @@ class AppPathFinder {
|
|||||||
|
|
||||||
if !self.backgroundRun {
|
if !self.backgroundRun {
|
||||||
self.appState.appInfo = self.appInfo
|
self.appState.appInfo = self.appInfo
|
||||||
|
if !self.undo {
|
||||||
self.appState.selectedItems = Set(updatedCollection)
|
self.appState.selectedItems = Set(updatedCollection)
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append object to store if running reverse search with empty store
|
// Append object to store if running reverse search with empty store
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ class AppState: ObservableObject
|
|||||||
@Published var currentView = CurrentDetailsView.empty
|
@Published var currentView = CurrentDetailsView.empty
|
||||||
@Published var showAlert: Bool = false
|
@Published var showAlert: Bool = false
|
||||||
@Published var sidebar: Bool = true
|
@Published var sidebar: Bool = true
|
||||||
// @Published var isReminderVisible: Bool = false
|
|
||||||
@Published var releases = [Release]()
|
@Published var releases = [Release]()
|
||||||
@Published var progressBar: (String, Double) = ("Ready", 0.0)
|
@Published var progressBar: (String, Double) = ("Ready", 0.0)
|
||||||
@Published var reload: Bool = false
|
@Published var reload: Bool = false
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ class ReversePathsSearcher {
|
|||||||
let allNames = appState.appInfoStore.map { $0.appName.pearFormat() }
|
let allNames = appState.appInfoStore.map { $0.appName.pearFormat() }
|
||||||
|
|
||||||
for location in locations.reverse.paths where fileManager.fileExists(atPath: location) {
|
for location in locations.reverse.paths where fileManager.fileExists(atPath: location) {
|
||||||
|
|
||||||
dispatchGroup.enter()
|
dispatchGroup.enter()
|
||||||
processLocation(location, allPaths: allPaths, allNames: allNames)
|
processLocation(location, allPaths: allPaths, allNames: allNames)
|
||||||
dispatchGroup.leave()
|
dispatchGroup.leave()
|
||||||
|
|||||||
@@ -11,22 +11,26 @@ import SwiftUI
|
|||||||
struct SimpleButtonStyle: ButtonStyle {
|
struct SimpleButtonStyle: ButtonStyle {
|
||||||
@State private var hovered = false
|
@State private var hovered = false
|
||||||
let icon: String
|
let icon: String
|
||||||
|
let iconFlip: String
|
||||||
let label: String
|
let label: String
|
||||||
let help: String
|
let help: String
|
||||||
let color: Color
|
let color: Color
|
||||||
let size: CGFloat
|
let size: CGFloat
|
||||||
|
let padding: CGFloat
|
||||||
|
|
||||||
init(icon: String, label: String = "", help: String, color: Color = Color("mode"), size: CGFloat = 20) {
|
init(icon: String, iconFlip: String = "", label: String = "", help: String, color: Color = Color("mode"), size: CGFloat = 20, padding: CGFloat = 5) {
|
||||||
self.icon = icon
|
self.icon = icon
|
||||||
|
self.iconFlip = iconFlip
|
||||||
self.label = label
|
self.label = label
|
||||||
self.help = help
|
self.help = help
|
||||||
self.color = color
|
self.color = color
|
||||||
self.size = size
|
self.size = size
|
||||||
|
self.padding = padding
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeBody(configuration: Self.Configuration) -> some View {
|
func makeBody(configuration: Self.Configuration) -> some View {
|
||||||
HStack {
|
HStack(alignment: .center) {
|
||||||
Image(systemName: icon)
|
Image(systemName: (hovered && !iconFlip.isEmpty) ? iconFlip : icon)
|
||||||
.resizable()
|
.resizable()
|
||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
.frame(width: size, height: size)
|
.frame(width: size, height: size)
|
||||||
@@ -35,7 +39,7 @@ struct SimpleButtonStyle: ButtonStyle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.foregroundColor(hovered ? color : color.opacity(0.5))
|
.foregroundColor(hovered ? color : color.opacity(0.5))
|
||||||
.padding(5)
|
.padding(padding)
|
||||||
.onHover { hovering in
|
.onHover { hovering in
|
||||||
withAnimation() {
|
withAnimation() {
|
||||||
hovered = hovering
|
hovered = hovering
|
||||||
@@ -121,6 +125,35 @@ struct ResetSettingsButtonStyle: ButtonStyle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct SimpleCheckboxToggleStyle: ToggleStyle {
|
||||||
|
@EnvironmentObject private var themeSettings: ThemeSettings
|
||||||
|
@State private var isHovered: Bool = false
|
||||||
|
|
||||||
|
func makeBody(configuration: Configuration) -> some View {
|
||||||
|
HStack {
|
||||||
|
RoundedRectangle(cornerRadius: 4)
|
||||||
|
.fill(themeSettings.themeColor.darker(by: 5))
|
||||||
|
.frame(width: 18, height: 18)
|
||||||
|
.overlay {
|
||||||
|
if configuration.isOn {
|
||||||
|
Image(systemName: "checkmark")
|
||||||
|
.foregroundStyle(Color("mode"))
|
||||||
|
.scaleEffect(isHovered ? 0.8 : 1.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onTapGesture {
|
||||||
|
withAnimation(.smooth()) {
|
||||||
|
configuration.isOn.toggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
configuration.label
|
||||||
|
}
|
||||||
|
.onHover(perform: { hovering in
|
||||||
|
self.isHovered = hovering
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct InfoButton: View {
|
struct InfoButton: View {
|
||||||
@State private var isPopoverPresented: Bool = false
|
@State private var isPopoverPresented: Bool = false
|
||||||
@@ -192,10 +225,40 @@ struct UninstallButton: ButtonStyle {
|
|||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
.padding(.vertical, 4)
|
.padding(.vertical, 4)
|
||||||
.background(configuration.isPressed ? Color("uninstall").opacity(0.8) : Color("uninstall"))
|
.background(configuration.isPressed ? Color("uninstall").opacity(0.8) : Color("uninstall"))
|
||||||
// .background(
|
.cornerRadius(8)
|
||||||
// configuration.isPressed ? Color("uninstall").opacity(0.8) :
|
.onHover { over in
|
||||||
// (isEnabled ? Color("uninstall") : Color.gray)
|
if over {
|
||||||
// )
|
NSCursor.pointingHand.push()
|
||||||
|
} else {
|
||||||
|
NSCursor.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct RescanButton: ButtonStyle {
|
||||||
|
|
||||||
|
func makeBody(configuration: Configuration) -> some View {
|
||||||
|
HStack(alignment: .center, spacing: 10) {
|
||||||
|
Image(systemName: "arrow.counterclockwise.circle")
|
||||||
|
.foregroundColor(.white)
|
||||||
|
|
||||||
|
Divider()
|
||||||
|
.frame(height: 24)
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.opacity(0.5)
|
||||||
|
|
||||||
|
configuration.label
|
||||||
|
.foregroundColor(.white)
|
||||||
|
|
||||||
|
}
|
||||||
|
.frame(height: 24)
|
||||||
|
.frame(minWidth: 75)
|
||||||
|
.padding(.horizontal)
|
||||||
|
.padding(.vertical, 4)
|
||||||
|
.background(configuration.isPressed ? Color("button").opacity(0.8) : Color("button"))
|
||||||
.cornerRadius(8)
|
.cornerRadius(8)
|
||||||
.onHover { over in
|
.onHover { over in
|
||||||
if over {
|
if over {
|
||||||
@@ -475,68 +538,6 @@ struct AnimatedSearchStyle: TextFieldStyle {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct SimpleSearchStyle: TextFieldStyle {
|
|
||||||
@State private var isHovered = false
|
|
||||||
@FocusState private var isFocused: Bool
|
|
||||||
@State var icon: Image?
|
|
||||||
@State var trash: Bool = false
|
|
||||||
@Binding var text: String
|
|
||||||
@EnvironmentObject var appState: AppState
|
|
||||||
@AppStorage("settings.general.mini") private var mini: Bool = false
|
|
||||||
|
|
||||||
func _body(configuration: TextField<Self._Label>) -> some View {
|
|
||||||
|
|
||||||
HStack(spacing: 5) {
|
|
||||||
|
|
||||||
HStack(spacing: 5) {
|
|
||||||
if icon != nil {
|
|
||||||
icon
|
|
||||||
.foregroundColor(Color("mode").opacity(0.5))
|
|
||||||
}
|
|
||||||
|
|
||||||
configuration
|
|
||||||
.font(.title3)
|
|
||||||
.textFieldStyle(PlainTextFieldStyle())
|
|
||||||
|
|
||||||
|
|
||||||
if trash && text != "" {
|
|
||||||
Image(systemName: "xmark")
|
|
||||||
.resizable()
|
|
||||||
.aspectRatio(contentMode: .fit)
|
|
||||||
.frame(width: 10, height: 10)
|
|
||||||
.padding(.trailing, 5)
|
|
||||||
.foregroundStyle(isHovered ? Color("mode").opacity(0.8) : Color("mode").opacity(0.5))
|
|
||||||
.onTapGesture {
|
|
||||||
text = ""
|
|
||||||
}
|
|
||||||
.help("Clear search")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
.padding(6)
|
|
||||||
.overlay(
|
|
||||||
RoundedRectangle(cornerRadius: 6)
|
|
||||||
.strokeBorder(Color("mode").opacity(0.2), lineWidth: 1)
|
|
||||||
.allowsHitTesting(false)
|
|
||||||
)
|
|
||||||
.onHover { hovering in
|
|
||||||
withAnimation(Animation.easeInOut(duration: 0.15)) {
|
|
||||||
self.isHovered = hovering
|
|
||||||
self.isFocused = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.focused($isFocused)
|
|
||||||
.onAppear {
|
|
||||||
updateOnMain {
|
|
||||||
self.isFocused = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct GlassEffect: NSViewRepresentable {
|
struct GlassEffect: NSViewRepresentable {
|
||||||
var material: NSVisualEffectView.Material // Choose the material you want
|
var material: NSVisualEffectView.Material // Choose the material you want
|
||||||
var blendingMode: NSVisualEffectView.BlendingMode // Choose the blending mode
|
var blendingMode: NSVisualEffectView.BlendingMode // Choose the blending mode
|
||||||
|
|||||||
@@ -386,6 +386,9 @@ func removeApp(appState: AppState, withId id: UUID) {
|
|||||||
if brew {
|
if brew {
|
||||||
caskCleanup(app: appState.appInfo.appName)
|
caskCleanup(app: appState.appInfo.appName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
appState.appInfo = AppInfo.empty
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ struct PearcleanerApp: App {
|
|||||||
// Enable menubar item
|
// Enable menubar item
|
||||||
if menubarEnabled {
|
if menubarEnabled {
|
||||||
MenuBarExtraManager.shared.addMenuBarExtra(withView: {
|
MenuBarExtraManager.shared.addMenuBarExtra(withView: {
|
||||||
MenuBarMiniAppView(search: $search, showPopover: $showPopover)
|
MiniAppView(search: $search, showPopover: $showPopover)
|
||||||
.environmentObject(locations)
|
.environmentObject(locations)
|
||||||
.environmentObject(appState)
|
.environmentObject(appState)
|
||||||
.environmentObject(fsm)
|
.environmentObject(fsm)
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
"color-space" : "display-p3",
|
"color-space" : "display-p3",
|
||||||
"components" : {
|
"components" : {
|
||||||
"alpha" : "1.000",
|
"alpha" : "1.000",
|
||||||
"blue" : "0xFF",
|
"blue" : "0xE8",
|
||||||
"green" : "0x83",
|
"green" : "0x7D",
|
||||||
"red" : "0x24"
|
"red" : "0x4D"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"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" : "0xBE",
|
||||||
"green" : "0x83",
|
"green" : "0x67",
|
||||||
"red" : "0x24"
|
"red" : "0x3F"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"idiom" : "universal"
|
"idiom" : "universal"
|
||||||
|
|||||||
@@ -428,7 +428,7 @@ struct InterfaceSettingsTab: View {
|
|||||||
.onChange(of: menubarEnabled) { newVal in
|
.onChange(of: menubarEnabled) { newVal in
|
||||||
if newVal {
|
if newVal {
|
||||||
MenuBarExtraManager.shared.addMenuBarExtra(withView: {
|
MenuBarExtraManager.shared.addMenuBarExtra(withView: {
|
||||||
MenuBarMiniAppView(search: $search, showPopover: $showPopover)
|
MiniAppView(search: $search, showPopover: $showPopover)
|
||||||
.environmentObject(locations)
|
.environmentObject(locations)
|
||||||
.environmentObject(appState)
|
.environmentObject(appState)
|
||||||
.environmentObject(fsm)
|
.environmentObject(fsm)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ struct AppListItems: View {
|
|||||||
let itemId = UUID()
|
let itemId = UUID()
|
||||||
let appInfo: AppInfo
|
let appInfo: AppInfo
|
||||||
var isSelected: Bool {
|
var isSelected: Bool {
|
||||||
appState.appInfo.id == appInfo.id
|
appState.appInfo.path == appInfo.path
|
||||||
}
|
}
|
||||||
@State private var hoveredItemPath: URL? = nil
|
@State private var hoveredItemPath: URL? = nil
|
||||||
var body: some View {
|
var body: some View {
|
||||||
@@ -39,7 +39,8 @@ struct AppListItems: View {
|
|||||||
Image(nsImage: appIcon)
|
Image(nsImage: appIcon)
|
||||||
.resizable()
|
.resizable()
|
||||||
.aspectRatio(contentMode: .fit)
|
.aspectRatio(contentMode: .fit)
|
||||||
.frame(width: (isHovered || isSelected) ? 32 : 30, height: (isHovered || isSelected) ? 32 : 30)
|
.frame(width: 30)
|
||||||
|
// .frame(width: (isHovered || isSelected) ? 32 : 30, height: (isHovered || isSelected) ? 32 : 30)
|
||||||
.clipShape(RoundedRectangle(cornerRadius: 8))
|
.clipShape(RoundedRectangle(cornerRadius: 8))
|
||||||
// .shadow(color: Color("pop").opacity(0.8), radius: isSelected ? 2 : 0)
|
// .shadow(color: Color("pop").opacity(0.8), radius: isSelected ? 2 : 0)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,13 +30,13 @@ struct AppsListView: View {
|
|||||||
SectionView(title: "System", count: filteredSystemApps.count, apps: filteredSystemApps, search: $search, showPopover: $showPopover)
|
SectionView(title: "System", count: filteredSystemApps.count, apps: filteredSystemApps, search: $search, showPopover: $showPopover)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// .padding(.horizontal)
|
|
||||||
.padding(.top, !mini ? 4 : 0)
|
.padding(.top, !mini ? 4 : 0)
|
||||||
}
|
}
|
||||||
.scrollIndicators(.never)
|
.scrollIndicators(.never)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct SectionView: View {
|
struct SectionView: View {
|
||||||
var title: String
|
var title: String
|
||||||
var count: Int
|
var count: Int
|
||||||
@@ -51,7 +51,6 @@ struct SectionView: View {
|
|||||||
ForEach(apps, id: \.self) { appInfo in
|
ForEach(apps, id: \.self) { appInfo in
|
||||||
AppListItems(search: $search, showPopover: $showPopover, appInfo: appInfo)
|
AppListItems(search: $search, showPopover: $showPopover, appInfo: appInfo)
|
||||||
if appInfo != apps.last {
|
if appInfo != apps.last {
|
||||||
// Divider().padding(.horizontal, 5)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,6 +58,72 @@ struct SectionView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct Header: View {
|
||||||
|
let title: String
|
||||||
|
let count: Int
|
||||||
|
@State private var hovered = false
|
||||||
|
@EnvironmentObject var appState: AppState
|
||||||
|
@EnvironmentObject var locations: Locations
|
||||||
|
@EnvironmentObject var fsm: FolderSettingsManager
|
||||||
|
@Binding var showPopover: Bool
|
||||||
|
@AppStorage("settings.general.glass") private var glass: Bool = true
|
||||||
|
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
HStack {
|
||||||
|
Text("\(title)").foregroundStyle(Color("mode")).opacity(0.5)
|
||||||
|
|
||||||
|
Text("\(count)")
|
||||||
|
.font(.system(size: 10))
|
||||||
|
.monospacedDigit()
|
||||||
|
.frame(minWidth: count > 99 ? 30 : 24, minHeight: 17)
|
||||||
|
.background(Color("mode").opacity(0.1))
|
||||||
|
.clipShape(.capsule)
|
||||||
|
.padding(.leading, 2)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
if hovered {
|
||||||
|
Text("REFRESH")
|
||||||
|
.font(.system(size: 10))
|
||||||
|
.monospaced()
|
||||||
|
.foregroundStyle(Color("mode").opacity(0.8))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.onHover { hovering in
|
||||||
|
withAnimation() {
|
||||||
|
hovered = hovering
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onTapGesture {
|
||||||
|
withAnimation {
|
||||||
|
// Refresh Apps list
|
||||||
|
appState.reload.toggle()
|
||||||
|
showPopover = false
|
||||||
|
let sortedApps = getSortedApps(paths: fsm.folderPaths, appState: appState)
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||||
|
appState.sortedApps = sortedApps
|
||||||
|
appState.reload.toggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.frame(minHeight: 20)
|
||||||
|
.help("Click header or ⌘+R to refresh apps list")
|
||||||
|
.padding(5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//List {
|
//List {
|
||||||
// Section {
|
// Section {
|
||||||
// ForEach(filteredUserApps, id:\.self) { element in
|
// ForEach(filteredUserApps, id:\.self) { element in
|
||||||
|
|||||||
@@ -80,7 +80,6 @@ struct FilesView: View {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Titlebar
|
// Titlebar
|
||||||
if !regularWin {
|
|
||||||
HStack(spacing: 0) {
|
HStack(spacing: 0) {
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
@@ -93,10 +92,11 @@ struct FilesView: View {
|
|||||||
showPopover = false
|
showPopover = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.buttonStyle(SimpleButtonStyle(icon: "x.circle.fill", help: "Close"))
|
.buttonStyle(SimpleButtonStyle(icon: "x.circle", iconFlip: "x.circle.fill", help: "Close"))
|
||||||
}
|
|
||||||
.padding([.horizontal, .top], 5)
|
|
||||||
}
|
}
|
||||||
|
.padding(.top, 6)
|
||||||
|
.padding(.trailing, (mini || menubarEnabled) ? 6 : 0)
|
||||||
|
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
|
|
||||||
// Main Group
|
// Main Group
|
||||||
@@ -163,6 +163,8 @@ struct FilesView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
|
.toggleStyle(SimpleCheckboxToggleStyle())
|
||||||
|
.help("All checkboxes")
|
||||||
|
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
@@ -244,9 +246,11 @@ struct FilesView: View {
|
|||||||
let iconImage = fileIcon.map(Image.init(nsImage:))
|
let iconImage = fileIcon.map(Image.init(nsImage:))
|
||||||
VStack {
|
VStack {
|
||||||
FileDetailsItem(size: fileSize, sizeL: fileSizeL, icon: iconImage, path: path)
|
FileDetailsItem(size: fileSize, sizeL: fileSizeL, icon: iconImage, path: path)
|
||||||
if index < sort.count - 1 {
|
.padding(.vertical, 5)
|
||||||
Divider().padding(.leading, 40).opacity(0.5)
|
// .padding(.leading, 40)
|
||||||
}
|
// if index < sort.count - 1 {
|
||||||
|
// Divider().padding(.leading, 40).opacity(0.5)
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,25 +273,27 @@ struct FilesView: View {
|
|||||||
|
|
||||||
Button("\(sizeType == "Logical" ? totalSelectedSize.logical : sizeType == "Finder" ? totalSelectedSize.finder : totalSelectedSize.real)") {
|
Button("\(sizeType == "Logical" ? totalSelectedSize.logical : sizeType == "Finder" ? totalSelectedSize.finder : totalSelectedSize.real)") {
|
||||||
Task {
|
Task {
|
||||||
|
if appState.selectedItems.count == appState.appInfo.fileSize.keys.count {
|
||||||
updateOnMain {
|
updateOnMain {
|
||||||
search = ""
|
search = ""
|
||||||
if !regularWin {
|
if mini || menubarEnabled {
|
||||||
appState.currentView = .apps
|
appState.currentView = .apps
|
||||||
showPopover = false
|
showPopover = false
|
||||||
} else {
|
} else {
|
||||||
appState.currentView = .empty
|
appState.currentView = .empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let selectedItemsArray = Array(appState.selectedItems)
|
let selectedItemsArray = Array(appState.selectedItems)
|
||||||
|
|
||||||
killApp(appId: appState.appInfo.bundleIdentifier) {
|
killApp(appId: appState.appInfo.bundleIdentifier) {
|
||||||
moveFilesToTrash(at: selectedItemsArray) {
|
moveFilesToTrash(at: selectedItemsArray) {
|
||||||
withAnimation {
|
withAnimation {
|
||||||
showPopover = false
|
showPopover = false
|
||||||
updateOnMain {
|
// updateOnMain {
|
||||||
appState.currentView = mini ? .apps : .empty
|
// appState.currentView = mini ? .apps : .empty
|
||||||
// appState.isReminderVisible.toggle()
|
// }
|
||||||
}
|
|
||||||
if sentinel {
|
if sentinel {
|
||||||
launchctl(load: true)
|
launchctl(load: true)
|
||||||
}
|
}
|
||||||
@@ -300,15 +306,20 @@ struct FilesView: View {
|
|||||||
removeApp(appState: appState, withId: appState.appInfo.id)
|
removeApp(appState: appState, withId: appState.appInfo.id)
|
||||||
} else {
|
} else {
|
||||||
// Add deleted appInfo object to trashed array
|
// Add deleted appInfo object to trashed array
|
||||||
appState.appInfo.fileSize = [:]
|
|
||||||
appState.trashedFiles.append(appState.appInfo)
|
appState.trashedFiles.append(appState.appInfo)
|
||||||
|
|
||||||
// Clear out appInfoStore object
|
// Clear out appInfoStore object (Used for leftover file search)
|
||||||
if let index = appState.appInfoStore.firstIndex(where: { $0.path == appState.appInfo.path }) {
|
if let index = appState.appInfoStore.firstIndex(where: { $0.path == appState.appInfo.path }) {
|
||||||
appState.appInfoStore[index] = .empty
|
appState.appInfoStore[index] = .empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateOnMain {
|
||||||
|
// Remove items from the list
|
||||||
|
appState.appInfo.fileSize = appState.appInfo.fileSize.filter { !appState.selectedItems.contains($0.key) }
|
||||||
|
// Update the selectedFiles to remove references that are no longer present
|
||||||
|
appState.selectedItems.removeAll()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
appState.appInfo = AppInfo.empty
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,8 +331,6 @@ struct FilesView: View {
|
|||||||
.padding(.top)
|
.padding(.top)
|
||||||
|
|
||||||
|
|
||||||
// Spacer()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -360,7 +369,7 @@ struct FileDetailsItem: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
|
.toggleStyle(SimpleCheckboxToggleStyle())
|
||||||
.disabled(self.path.path.contains(".Trash"))
|
.disabled(self.path.path.contains(".Trash"))
|
||||||
|
|
||||||
if let appIcon = icon {
|
if let appIcon = icon {
|
||||||
@@ -369,8 +378,6 @@ struct FileDetailsItem: View {
|
|||||||
.aspectRatio(contentMode: .fit)
|
.aspectRatio(contentMode: .fit)
|
||||||
.frame(width: 30, height: 30)
|
.frame(width: 30, height: 30)
|
||||||
.clipShape(RoundedRectangle(cornerRadius: 8))
|
.clipShape(RoundedRectangle(cornerRadius: 8))
|
||||||
.brightness(isHovered ? 0.2 : 0)
|
|
||||||
.shadow(color: Color("mode"), radius: isHovered ? 2 : 0)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,6 +389,17 @@ struct FileDetailsItem: View {
|
|||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
.truncationMode(.tail)
|
.truncationMode(.tail)
|
||||||
.help(path.lastPathComponent)
|
.help(path.lastPathComponent)
|
||||||
|
.overlay{
|
||||||
|
if (isHovered) {
|
||||||
|
VStack {
|
||||||
|
Spacer()
|
||||||
|
RoundedRectangle(cornerRadius: 10)
|
||||||
|
.fill(Color("mode").opacity(0.5))
|
||||||
|
.frame(height: 1.5)
|
||||||
|
.offset(y: 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if isNested(path: path) {
|
if isNested(path: path) {
|
||||||
InfoButton(text: "Application file is nested within subdirectories. To prevent deleting incorrect folders, Pearcleaner will leave these alone. You may manually delete the remaining folders if required.", color: nil, label: "")
|
InfoButton(text: "Application file is nested within subdirectories. To prevent deleting incorrect folders, Pearcleaner will leave these alone. You may manually delete the remaining folders if required.", color: nil, label: "")
|
||||||
@@ -398,7 +416,17 @@ struct FileDetailsItem: View {
|
|||||||
.truncationMode(.tail)
|
.truncationMode(.tail)
|
||||||
.opacity(0.5)
|
.opacity(0.5)
|
||||||
.help(path.path)
|
.help(path.path)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
.onTapGesture {
|
||||||
|
NSWorkspace.shared.selectFile(path.path, inFileViewerRootedAtPath: path.deletingLastPathComponent().path)
|
||||||
|
}
|
||||||
|
.onHover { hovering in
|
||||||
|
withAnimation(Animation.easeIn(duration: 0.2)) {
|
||||||
|
self.isHovered = hovering
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
@@ -409,14 +437,6 @@ struct FileDetailsItem: View {
|
|||||||
Text("\(displaySize)")
|
Text("\(displaySize)")
|
||||||
|
|
||||||
}
|
}
|
||||||
.onHover { hovering in
|
|
||||||
withAnimation(Animation.easeIn(duration: 0.2)) {
|
|
||||||
self.isHovered = hovering
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.onTapGesture {
|
|
||||||
NSWorkspace.shared.selectFile(path.path, inFileViewerRootedAtPath: path.deletingLastPathComponent().path)
|
|
||||||
}
|
|
||||||
.contextMenu {
|
.contextMenu {
|
||||||
if path.pathExtension == "app" {
|
if path.pathExtension == "app" {
|
||||||
Button("Open \(path.deletingPathExtension().lastPathComponent)") {
|
Button("Open \(path.deletingPathExtension().lastPathComponent)") {
|
||||||
|
|||||||
@@ -1,142 +0,0 @@
|
|||||||
//
|
|
||||||
// MenuBarAppsListView.swift
|
|
||||||
// Pearcleaner
|
|
||||||
//
|
|
||||||
// Created by Alin Lupascu on 3/16/24.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct MenuBarMiniAppView: View {
|
|
||||||
@Environment(\.colorScheme) var colorScheme
|
|
||||||
@EnvironmentObject var appState: AppState
|
|
||||||
@EnvironmentObject var locations: Locations
|
|
||||||
@EnvironmentObject var themeSettings: ThemeSettings
|
|
||||||
@State private var animateGradient: Bool = false
|
|
||||||
@Binding var search: String
|
|
||||||
@State private var showSys: Bool = true
|
|
||||||
@State private var showUsr: Bool = true
|
|
||||||
@AppStorage("settings.general.mini") private var mini: Bool = false
|
|
||||||
@AppStorage("settings.general.glass") private var glass: Bool = true
|
|
||||||
@AppStorage("settings.general.popover") private var popoverStay: Bool = true
|
|
||||||
@Binding var showPopover: Bool
|
|
||||||
@State private var showMenu = false
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
|
|
||||||
var filteredApps: [AppInfo] {
|
|
||||||
if search.isEmpty {
|
|
||||||
return appState.sortedApps
|
|
||||||
} else {
|
|
||||||
return appState.sortedApps.filter { $0.appName.localizedCaseInsensitiveContains(search) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ZStack {
|
|
||||||
HStack(spacing: 0){
|
|
||||||
|
|
||||||
if appState.reload {
|
|
||||||
VStack {
|
|
||||||
Spacer()
|
|
||||||
ProgressView("Refreshing app list")
|
|
||||||
Spacer()
|
|
||||||
}
|
|
||||||
.padding(.vertical)
|
|
||||||
} else {
|
|
||||||
VStack(alignment: .center) {
|
|
||||||
|
|
||||||
AppsListView(search: $search, showPopover: $showPopover, filteredApps: filteredApps).padding(.top, 8)
|
|
||||||
|
|
||||||
HStack(spacing: 10) {
|
|
||||||
|
|
||||||
Button("Leftover Files") {
|
|
||||||
showMenu = false
|
|
||||||
withAnimation(.easeInOut(duration: 0.5)) {
|
|
||||||
showPopover = false
|
|
||||||
updateOnMain() {
|
|
||||||
appState.appInfo = .empty
|
|
||||||
appState.selectedZombieItems = []
|
|
||||||
if appState.zombieFile.fileSize.keys.count == 0 {
|
|
||||||
appState.currentView = .zombie
|
|
||||||
appState.showProgress.toggle()
|
|
||||||
showPopover.toggle()
|
|
||||||
reversePreloader(allApps: appState.sortedApps, appState: appState, locations: locations, reverseAddon: true)
|
|
||||||
} else {
|
|
||||||
appState.currentView = .zombie
|
|
||||||
showPopover.toggle()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.buttonStyle(SimpleButtonStyle(icon: "clock.arrow.circlepath", help: "Leftover Files"))
|
|
||||||
.padding(.leading, 10)
|
|
||||||
|
|
||||||
SearchBarMiniBottom(search: $search)
|
|
||||||
|
|
||||||
Button("More") {
|
|
||||||
self.showMenu.toggle()
|
|
||||||
}
|
|
||||||
.padding(.trailing, 10)
|
|
||||||
.buttonStyle(SimpleButtonStyle(icon: "ellipsis.circle", help: "More"))
|
|
||||||
.popover(isPresented: $showMenu) {
|
|
||||||
VStack(alignment: .leading) {
|
|
||||||
|
|
||||||
if #available(macOS 14.0, *) {
|
|
||||||
SettingsLink{
|
|
||||||
Label("Settings", systemImage: "gear")
|
|
||||||
}
|
|
||||||
.buttonStyle(SimpleButtonStyle(icon: "gear", label: "Settings", help: "Settings"))
|
|
||||||
} else {
|
|
||||||
Button("Settings") {
|
|
||||||
NSApp.sendAction(Selector(("showPreferencesWindow:")), to: NSApp.delegate, from: nil)
|
|
||||||
showMenu = false
|
|
||||||
}
|
|
||||||
.buttonStyle(SimpleButtonStyle(icon: "gear", label: "Settings", help: "Settings"))
|
|
||||||
}
|
|
||||||
|
|
||||||
Button("Quit") {
|
|
||||||
NSApp.terminate(nil)
|
|
||||||
}
|
|
||||||
.buttonStyle(SimpleButtonStyle(icon: "x.circle.fill", label: "Quit Pearcleaner", help: "Quit Pearcleaner"))
|
|
||||||
}
|
|
||||||
.padding()
|
|
||||||
.background(backgroundView(themeSettings: themeSettings, glass: glass).padding(-80))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
.padding(.top, 5)
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
.padding(.vertical, 8)
|
|
||||||
.padding(.bottom, 8)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.frame(minWidth: 300, minHeight: 370)
|
|
||||||
.edgesIgnoringSafeArea(.all)
|
|
||||||
.background(backgroundView(themeSettings: themeSettings, glass: glass).padding(-80))
|
|
||||||
.transition(.opacity)
|
|
||||||
.popover(isPresented: $showPopover, arrowEdge: .leading) {
|
|
||||||
VStack {
|
|
||||||
if appState.currentView == .files {
|
|
||||||
FilesView(showPopover: $showPopover, search: $search, regularWin: false)
|
|
||||||
.id(appState.appInfo.id)
|
|
||||||
} else if appState.currentView == .zombie {
|
|
||||||
ZombieView(showPopover: $showPopover, search: $search, regularWin: false)
|
|
||||||
.id(appState.appInfo.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
.interactiveDismissDisabled(popoverStay)
|
|
||||||
.background(backgroundView(themeSettings: themeSettings, glass: glass).padding(-80))
|
|
||||||
.frame(width: 650, height: 500)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -28,56 +28,17 @@ struct MiniMode: View {
|
|||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
Group {
|
Group {
|
||||||
if appState.currentView == .empty {
|
if appState.currentView == .empty {
|
||||||
TopBarMini(search: $search, showPopover: $showPopover)
|
|
||||||
MiniEmptyView(showPopover: $showPopover)
|
MiniEmptyView(showPopover: $showPopover)
|
||||||
} else {
|
} else {
|
||||||
TopBarMini(search: $search, showPopover: $showPopover)
|
|
||||||
MiniAppView(search: $search, showPopover: $showPopover)
|
MiniAppView(search: $search, showPopover: $showPopover)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.transition(.opacity)
|
.transition(.opacity)
|
||||||
}
|
}
|
||||||
.popover(isPresented: $showPopover, arrowEdge: .trailing) {
|
|
||||||
VStack {
|
|
||||||
if appState.currentView == .files {
|
|
||||||
FilesView(showPopover: $showPopover, search: $search, regularWin: false)
|
|
||||||
.id(appState.appInfo.id)
|
|
||||||
} else if appState.currentView == .zombie {
|
|
||||||
ZombieView(showPopover: $showPopover, search: $search, regularWin: false)
|
|
||||||
.id(appState.appInfo.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
.interactiveDismissDisabled(popoverStay)
|
|
||||||
// .background(Color("pop"))
|
|
||||||
// .background(backgroundView(themeSettings: themeSettings, glass: false).padding(-80))
|
|
||||||
.background(backgroundView(themeSettings: themeSettings, glass: glass).padding(-80))
|
|
||||||
// .background(
|
|
||||||
// Group {
|
|
||||||
// if glass {
|
|
||||||
// backgroundView(themeSettings: themeSettings).padding(-80)
|
|
||||||
//// GlassEffect(material: .sidebar, blendingMode: .behindWindow).edgesIgnoringSafeArea(.all)
|
|
||||||
// } else {
|
|
||||||
// Rectangle()
|
|
||||||
// .fill(Color("pop"))
|
|
||||||
// .padding(-80)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// )
|
|
||||||
.frame(width: 650, height: 550)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
.frame(minWidth: 300, minHeight: 345)
|
.frame(minWidth: 300, minHeight: 345)
|
||||||
.edgesIgnoringSafeArea(.all)
|
.edgesIgnoringSafeArea(.all)
|
||||||
.background(backgroundView(themeSettings: themeSettings, glass: glass))
|
.background(backgroundView(themeSettings: themeSettings, glass: glass))
|
||||||
// .background(glass ? GlassEffect(material: .sidebar, blendingMode: .behindWindow).edgesIgnoringSafeArea(.all) : nil)
|
|
||||||
// MARK: Background for whole app
|
|
||||||
// .background(Color("bg").opacity(1))
|
|
||||||
// .background(VisualEffect(material: .sidebar, blendingMode: .behindWindow).edgesIgnoringSafeArea(.all))
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,6 +56,7 @@ struct MiniEmptyView: View {
|
|||||||
@AppStorage("settings.general.mini") private var mini: Bool = false
|
@AppStorage("settings.general.mini") private var mini: Bool = false
|
||||||
@AppStorage("settings.general.animateLogo") private var animateLogo: Bool = true
|
@AppStorage("settings.general.animateLogo") private var animateLogo: Bool = true
|
||||||
@Binding var showPopover: Bool
|
@Binding var showPopover: Bool
|
||||||
|
@State private var animationStart = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .center) {
|
VStack(alignment: .center) {
|
||||||
@@ -102,7 +64,7 @@ struct MiniEmptyView: View {
|
|||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
if #available(macOS 14, *) {
|
if #available(macOS 14, *) {
|
||||||
if animateLogo {
|
if animateLogo && animationStart {
|
||||||
LinearGradient(gradient: Gradient(colors: [.green, .orange]), startPoint: .leading, endPoint: .trailing)
|
LinearGradient(gradient: Gradient(colors: [.green, .orange]), startPoint: .leading, endPoint: .trailing)
|
||||||
.mask(
|
.mask(
|
||||||
Image(systemName: "plus.square.dashed")
|
Image(systemName: "plus.square.dashed")
|
||||||
@@ -144,36 +106,28 @@ struct MiniEmptyView: View {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Text("Drop an app here")
|
Text("Drop an app here")
|
||||||
.font(.title3)
|
.font(.title3)
|
||||||
|
.opacity(0.7)
|
||||||
|
|
||||||
|
Text("Click for apps list")
|
||||||
|
.font(.footnote)
|
||||||
.padding(.bottom, 25)
|
.padding(.bottom, 25)
|
||||||
.opacity(0.5)
|
.opacity(0.5)
|
||||||
|
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
|
|
||||||
// if appState.isReminderVisible {
|
}
|
||||||
// Text("CMD + Z to undo")
|
.onTapGesture {
|
||||||
// .font(.title2)
|
withAnimation(.easeInOut(duration: 0.5)) {
|
||||||
// .foregroundStyle(Color("mode").opacity(0.5))
|
appState.currentView = .apps
|
||||||
// .fontWeight(.medium)
|
}
|
||||||
// .onAppear {
|
}
|
||||||
// DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
|
.onAppear {
|
||||||
// withAnimation {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||||
// updateOnMain {
|
animationStart = true
|
||||||
// appState.isReminderVisible = false
|
}
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Spacer()
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,26 +139,24 @@ struct MiniEmptyView: View {
|
|||||||
struct MiniAppView: View {
|
struct MiniAppView: View {
|
||||||
@Environment(\.colorScheme) var colorScheme
|
@Environment(\.colorScheme) var colorScheme
|
||||||
@EnvironmentObject var appState: AppState
|
@EnvironmentObject var appState: AppState
|
||||||
|
@EnvironmentObject var locations: Locations
|
||||||
|
@EnvironmentObject var themeSettings: ThemeSettings
|
||||||
@State private var animateGradient: Bool = false
|
@State private var animateGradient: Bool = false
|
||||||
@Binding var search: String
|
@Binding var search: String
|
||||||
@State private var showSys: Bool = true
|
@State private var showSys: Bool = true
|
||||||
@State private var showUsr: Bool = true
|
@State private var showUsr: Bool = true
|
||||||
@AppStorage("settings.general.mini") private var mini: Bool = false
|
@AppStorage("settings.general.mini") private var mini: Bool = false
|
||||||
@AppStorage("settings.general.glass") private var glass: Bool = true
|
@AppStorage("settings.general.glass") private var glass: Bool = true
|
||||||
|
@AppStorage("settings.general.popover") private var popoverStay: Bool = true
|
||||||
|
@AppStorage("settings.menubar.enabled") private var menubarEnabled: Bool = false
|
||||||
|
@AppStorage("settings.general.sidebarWidth") private var sidebarWidth: Double = 280
|
||||||
@Binding var showPopover: Bool
|
@Binding var showPopover: Bool
|
||||||
|
@State private var showMenu = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
|
||||||
var filteredApps: [AppInfo] {
|
|
||||||
if search.isEmpty {
|
|
||||||
return appState.sortedApps
|
|
||||||
} else {
|
|
||||||
return appState.sortedApps.filter { $0.appName.localizedCaseInsensitiveContains(search) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ZStack {
|
ZStack {
|
||||||
HStack(spacing: 0){
|
|
||||||
|
|
||||||
if appState.reload {
|
if appState.reload {
|
||||||
VStack {
|
VStack {
|
||||||
@@ -214,23 +166,31 @@ struct MiniAppView: View {
|
|||||||
}
|
}
|
||||||
.padding(.vertical)
|
.padding(.vertical)
|
||||||
} else {
|
} else {
|
||||||
VStack(alignment: .center) {
|
Searchbar(glass: glass, sidebarWidth: sidebarWidth, menubarEnabled: menubarEnabled, mini: mini, search: $search, showPopover: $showPopover)
|
||||||
|
|
||||||
AppsListView(search: $search, showPopover: $showPopover, filteredApps: filteredApps)
|
|
||||||
|
|
||||||
if appState.currentView != .empty {
|
|
||||||
SearchBarMiniBottom(search: $search)
|
|
||||||
.padding(.horizontal)
|
|
||||||
.padding(.top, 5)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding(.bottom)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.transition(.opacity)
|
.transition(.opacity)
|
||||||
|
.frame(minWidth: 300, minHeight: 370)
|
||||||
|
.edgesIgnoringSafeArea(.all)
|
||||||
|
.background(backgroundView(themeSettings: themeSettings, glass: glass).padding(-80))
|
||||||
|
.transition(.opacity)
|
||||||
|
.popover(isPresented: $showPopover, arrowEdge: .trailing) {
|
||||||
|
VStack {
|
||||||
|
if appState.currentView == .files {
|
||||||
|
FilesView(showPopover: $showPopover, search: $search, regularWin: false)
|
||||||
|
.id(appState.appInfo.id)
|
||||||
|
} else if appState.currentView == .zombie {
|
||||||
|
ZombieView(showPopover: $showPopover, search: $search, regularWin: false)
|
||||||
|
.id(appState.appInfo.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.interactiveDismissDisabled(popoverStay)
|
||||||
|
.background(backgroundView(themeSettings: themeSettings, glass: glass).padding(-80))
|
||||||
|
.frame(width: 650, height: 500)
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,26 +11,22 @@ import SwiftUI
|
|||||||
struct RegularMode: View {
|
struct RegularMode: View {
|
||||||
@EnvironmentObject var appState: AppState
|
@EnvironmentObject var appState: AppState
|
||||||
@EnvironmentObject var themeSettings: ThemeSettings
|
@EnvironmentObject var themeSettings: ThemeSettings
|
||||||
|
@EnvironmentObject var locations: Locations
|
||||||
@AppStorage("settings.general.glass") private var glass: Bool = false
|
@AppStorage("settings.general.glass") private var glass: Bool = false
|
||||||
@AppStorage("settings.general.sidebarWidth") private var sidebarWidth: Double = 280
|
@AppStorage("settings.general.sidebarWidth") private var sidebarWidth: Double = 280
|
||||||
|
@AppStorage("settings.menubar.enabled") private var menubarEnabled: Bool = false
|
||||||
|
@AppStorage("settings.general.mini") private var mini: Bool = false
|
||||||
@Binding var search: String
|
@Binding var search: String
|
||||||
@State private var showSys: Bool = true
|
@State private var showSys: Bool = true
|
||||||
@State private var showUsr: Bool = true
|
@State private var showUsr: Bool = true
|
||||||
@Binding var showPopover: Bool
|
@Binding var showPopover: Bool
|
||||||
|
@State private var showMenu = false
|
||||||
|
|
||||||
var filteredApps: [AppInfo] {
|
|
||||||
if search.isEmpty {
|
|
||||||
return appState.sortedApps
|
|
||||||
} else {
|
|
||||||
return appState.sortedApps.filter { $0.appName.localizedCaseInsensitiveContains(search) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
|
||||||
HStack(alignment: .center, spacing: 0) {
|
HStack(alignment: .center, spacing: 0) {
|
||||||
|
|
||||||
// App List
|
// App List
|
||||||
HStack(spacing: 0){
|
HStack(spacing: 0){
|
||||||
|
|
||||||
@@ -43,26 +39,10 @@ struct RegularMode: View {
|
|||||||
.frame(width: sidebarWidth)
|
.frame(width: sidebarWidth)
|
||||||
.padding(.vertical)
|
.padding(.vertical)
|
||||||
} else {
|
} else {
|
||||||
VStack(alignment: .center) {
|
Searchbar(glass: glass, sidebarWidth: sidebarWidth, menubarEnabled: menubarEnabled, mini: mini, search: $search, showPopover: $showPopover)
|
||||||
|
|
||||||
VStack(alignment: .center, spacing: 20) {
|
|
||||||
HStack {
|
|
||||||
SearchBarMiniBottom(search: $search)
|
|
||||||
.padding(.horizontal)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.padding(.top, 20)
|
|
||||||
|
|
||||||
|
|
||||||
AppsListView(search: $search, showPopover: $showPopover, filteredApps: filteredApps)
|
|
||||||
|
|
||||||
}
|
|
||||||
.frame(width: sidebarWidth)
|
.frame(width: sidebarWidth)
|
||||||
.padding(.vertical, 7)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
.background(backgroundView(themeSettings: themeSettings, darker: true, glass: glass))
|
.background(backgroundView(themeSettings: themeSettings, darker: true, glass: glass))
|
||||||
.transition(.opacity)
|
.transition(.opacity)
|
||||||
@@ -73,22 +53,21 @@ struct RegularMode: View {
|
|||||||
|
|
||||||
|
|
||||||
// Details View
|
// Details View
|
||||||
VStack(spacing: 0) {
|
HStack(spacing: 0) {
|
||||||
|
Spacer()
|
||||||
Group {
|
Group {
|
||||||
if appState.currentView == .empty || appState.currentView == .apps {
|
if appState.currentView == .empty || appState.currentView == .apps {
|
||||||
TopBar(showPopover: $showPopover)
|
|
||||||
AppDetailsEmptyView(showPopover: $showPopover)
|
AppDetailsEmptyView(showPopover: $showPopover)
|
||||||
} else if appState.currentView == .files {
|
} else if appState.currentView == .files {
|
||||||
TopBar(showPopover: $showPopover)
|
|
||||||
FilesView(showPopover: $showPopover, search: $search, regularWin: true)
|
FilesView(showPopover: $showPopover, search: $search, regularWin: true)
|
||||||
.id(appState.appInfo.id)
|
.id(appState.appInfo.id)
|
||||||
} else if appState.currentView == .zombie {
|
} else if appState.currentView == .zombie {
|
||||||
TopBar(showPopover: $showPopover)
|
|
||||||
ZombieView(showPopover: $showPopover, search: $search, regularWin: true)
|
ZombieView(showPopover: $showPopover, search: $search, regularWin: true)
|
||||||
.id(appState.appInfo.id)
|
.id(appState.appInfo.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.transition(.opacity)
|
.transition(.opacity)
|
||||||
|
Spacer()
|
||||||
}
|
}
|
||||||
.zIndex(2)
|
.zIndex(2)
|
||||||
.background(backgroundView(themeSettings: themeSettings))
|
.background(backgroundView(themeSettings: themeSettings))
|
||||||
@@ -109,13 +88,14 @@ struct AppDetailsEmptyView: View {
|
|||||||
@EnvironmentObject var locations: Locations
|
@EnvironmentObject var locations: Locations
|
||||||
@AppStorage("settings.general.animateLogo") private var animateLogo: Bool = true
|
@AppStorage("settings.general.animateLogo") private var animateLogo: Bool = true
|
||||||
@Binding var showPopover: Bool
|
@Binding var showPopover: Bool
|
||||||
|
@State private var animationStart = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .center) {
|
VStack(alignment: .center) {
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
if #available(macOS 14, *) {
|
if #available(macOS 14, *) {
|
||||||
if animateLogo {
|
if animateLogo && animationStart {
|
||||||
PearDropView()
|
PearDropView()
|
||||||
.phaseAnimator([false, true]) { wwdc24, chromaRotate in
|
.phaseAnimator([false, true]) { wwdc24, chromaRotate in
|
||||||
wwdc24
|
wwdc24
|
||||||
@@ -139,75 +119,10 @@ struct AppDetailsEmptyView: View {
|
|||||||
.padding(.bottom, 25)
|
.padding(.bottom, 25)
|
||||||
.opacity(0.5)
|
.opacity(0.5)
|
||||||
}
|
}
|
||||||
}
|
.onAppear {
|
||||||
}
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||||
|
animationStart = true
|
||||||
|
|
||||||
struct SearchBar: View {
|
|
||||||
@Binding var search: String
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
HStack {
|
|
||||||
TextField("Search", text: $search)
|
|
||||||
.textFieldStyle(SimpleSearchStyle(icon: Image(systemName: "magnifyingglass"),trash: true, text: $search))
|
|
||||||
}
|
|
||||||
.frame(height: 30)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct Header: View {
|
|
||||||
let title: String
|
|
||||||
let count: Int
|
|
||||||
@State private var hovered = false
|
|
||||||
@EnvironmentObject var appState: AppState
|
|
||||||
@EnvironmentObject var locations: Locations
|
|
||||||
@EnvironmentObject var fsm: FolderSettingsManager
|
|
||||||
@Binding var showPopover: Bool
|
|
||||||
@AppStorage("settings.general.glass") private var glass: Bool = true
|
|
||||||
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
HStack {
|
|
||||||
Text("\(title)").foregroundStyle(Color("mode")).opacity(0.5)
|
|
||||||
|
|
||||||
Text("\(count)")
|
|
||||||
.font(.system(size: 10))
|
|
||||||
.monospacedDigit()
|
|
||||||
.frame(minWidth: count > 99 ? 30 : 24, minHeight: 17)
|
|
||||||
.background(Color("mode").opacity(0.1))
|
|
||||||
.clipShape(.capsule)
|
|
||||||
.padding(.leading, 2)
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
if hovered {
|
|
||||||
Text("REFRESH")
|
|
||||||
.font(.system(size: 10))
|
|
||||||
.monospaced()
|
|
||||||
.foregroundStyle(Color("mode").opacity(0.8))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
.onHover { hovering in
|
|
||||||
withAnimation() {
|
|
||||||
hovered = hovering
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.onTapGesture {
|
|
||||||
withAnimation {
|
|
||||||
// Refresh Apps list
|
|
||||||
appState.reload.toggle()
|
|
||||||
showPopover = false
|
|
||||||
let sortedApps = getSortedApps(paths: fsm.folderPaths, appState: appState)
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
|
||||||
appState.sortedApps = sortedApps
|
|
||||||
appState.reload.toggle()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.frame(minHeight: 20)
|
|
||||||
.help("Click header or ⌘+R to refresh apps list")
|
|
||||||
.padding(5)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,213 @@
|
|||||||
|
//
|
||||||
|
// Searchbar.swift
|
||||||
|
// Pearcleaner
|
||||||
|
//
|
||||||
|
// Created by Alin Lupascu on 4/26/24.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct Searchbar: View {
|
||||||
|
@EnvironmentObject var appState: AppState
|
||||||
|
@EnvironmentObject var themeSettings: ThemeSettings
|
||||||
|
@EnvironmentObject var locations: Locations
|
||||||
|
var glass: Bool
|
||||||
|
var sidebarWidth: Double
|
||||||
|
var menubarEnabled: Bool
|
||||||
|
var mini: Bool
|
||||||
|
@Binding var search: String
|
||||||
|
@Binding var showPopover: Bool
|
||||||
|
@State private var showMenu = false
|
||||||
|
@State private var showSys: Bool = true
|
||||||
|
@State private var showUsr: Bool = true
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(alignment: .center, spacing: 0) {
|
||||||
|
Spacer()
|
||||||
|
.frame(height: 10)
|
||||||
|
|
||||||
|
AppsListView(search: $search, showPopover: $showPopover, filteredApps: filteredApps)
|
||||||
|
.padding(.top, 25)
|
||||||
|
|
||||||
|
Divider()
|
||||||
|
|
||||||
|
HStack(spacing: 10) {
|
||||||
|
|
||||||
|
|
||||||
|
SearchBar(search: $search, darker: (mini || menubarEnabled) ? false : true, glass: glass)
|
||||||
|
|
||||||
|
|
||||||
|
if search.isEmpty {
|
||||||
|
Button("More") {
|
||||||
|
self.showMenu.toggle()
|
||||||
|
}
|
||||||
|
.buttonStyle(SimpleButtonStyle(icon: "ellipsis.circle", help: "More"))
|
||||||
|
.popover(isPresented: $showMenu) {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
|
||||||
|
if mini && !menubarEnabled {
|
||||||
|
Button("") {
|
||||||
|
withAnimation(.easeInOut(duration: 0.5)) {
|
||||||
|
appState.currentView = .empty
|
||||||
|
appState.appInfo = AppInfo.empty
|
||||||
|
showPopover = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.buttonStyle(SimpleButtonStyle(icon: "plus.square.dashed", label: "Drop Target", help: "Drop Target"))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Button("Leftover Files") {
|
||||||
|
showMenu = false
|
||||||
|
withAnimation(.easeInOut(duration: 0.5)) {
|
||||||
|
showPopover = false
|
||||||
|
appState.appInfo = .empty
|
||||||
|
appState.selectedZombieItems = []
|
||||||
|
if appState.zombieFile.fileSize.keys.isEmpty {
|
||||||
|
appState.currentView = .zombie
|
||||||
|
appState.showProgress.toggle()
|
||||||
|
showPopover.toggle()
|
||||||
|
reversePreloader(allApps: appState.sortedApps, appState: appState, locations: locations, reverseAddon: true)
|
||||||
|
} else {
|
||||||
|
appState.currentView = .zombie
|
||||||
|
showPopover.toggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.buttonStyle(SimpleButtonStyle(icon: "circle.fill", label: "Leftover Files", help: "Leftover Files", size: 5))
|
||||||
|
|
||||||
|
|
||||||
|
if #available(macOS 14.0, *) {
|
||||||
|
SettingsLink {}
|
||||||
|
.buttonStyle(SimpleButtonStyle(icon: "circle.fill", label: "Settings", help: "Settings", size: 5))
|
||||||
|
} else {
|
||||||
|
Button("Settings") {
|
||||||
|
NSApp.sendAction(Selector(("showPreferencesWindow:")), to: NSApp.delegate, from: nil)
|
||||||
|
showMenu = false
|
||||||
|
}
|
||||||
|
.buttonStyle(SimpleButtonStyle(icon: "circle.fill", label: "Settings", help: "Settings", size: 5))
|
||||||
|
}
|
||||||
|
|
||||||
|
if menubarEnabled {
|
||||||
|
Button("Quit") {
|
||||||
|
NSApp.terminate(nil)
|
||||||
|
}
|
||||||
|
.buttonStyle(SimpleButtonStyle(icon: "x.circle.fill", label: "Quit Pearcleaner", help: "Quit Pearcleaner"))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
.background(backgroundView(themeSettings: themeSettings, glass: glass).padding(-80))
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
.padding(.horizontal, search.isEmpty ? 10 : 5)
|
||||||
|
.padding(.vertical, 5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var filteredApps: [AppInfo] {
|
||||||
|
if search.isEmpty {
|
||||||
|
return appState.sortedApps
|
||||||
|
} else {
|
||||||
|
return appState.sortedApps.filter { $0.appName.localizedCaseInsensitiveContains(search) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct SimpleSearchStyle: TextFieldStyle {
|
||||||
|
@State private var isHovered = false
|
||||||
|
@FocusState private var isFocused: Bool
|
||||||
|
@State var trash: Bool = false
|
||||||
|
@Binding var text: String
|
||||||
|
@State var darker: Bool = false
|
||||||
|
@State var glass: Bool = false
|
||||||
|
@State var padding: CGFloat = 5
|
||||||
|
@EnvironmentObject var appState: AppState
|
||||||
|
@EnvironmentObject var themeSettings: ThemeSettings
|
||||||
|
@AppStorage("settings.general.mini") private var mini: Bool = false
|
||||||
|
|
||||||
|
func _body(configuration: TextField<Self._Label>) -> some View {
|
||||||
|
|
||||||
|
ZStack {
|
||||||
|
RoundedRectangle(cornerRadius: 8)
|
||||||
|
.fill(darker ? themeSettings.themeColor.darker(by: 5) : themeSettings.themeColor)
|
||||||
|
.allowsHitTesting(false)
|
||||||
|
.frame(height: 30)
|
||||||
|
.opacity(glass ? 0.0 : 1.0)
|
||||||
|
|
||||||
|
|
||||||
|
ZStack {
|
||||||
|
if text.isEmpty {
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
Text(isFocused ? "Type to search" : "Click to search")
|
||||||
|
.font(.subheadline)
|
||||||
|
.foregroundColor(Color("mode").opacity(0.2))
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HStack {
|
||||||
|
configuration
|
||||||
|
.font(.title3)
|
||||||
|
.textFieldStyle(PlainTextFieldStyle())
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
if trash && text != "" {
|
||||||
|
Button("") {
|
||||||
|
text = ""
|
||||||
|
}
|
||||||
|
.buttonStyle(SimpleButtonStyle(icon: "delete.left.fill", help: "Clear text", size: 14, padding: padding))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.padding(.horizontal, 8)
|
||||||
|
|
||||||
|
}
|
||||||
|
.onHover { hovering in
|
||||||
|
withAnimation(Animation.easeInOut(duration: 0.15)) {
|
||||||
|
self.isHovered = hovering
|
||||||
|
self.isFocused = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.focused($isFocused)
|
||||||
|
.onAppear {
|
||||||
|
updateOnMain {
|
||||||
|
self.isFocused = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide blinking textfield caret
|
||||||
|
extension NSTextView {
|
||||||
|
open override var frame: CGRect {
|
||||||
|
didSet {
|
||||||
|
insertionPointColor = .clear
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SearchBar: View {
|
||||||
|
@Binding var search: String
|
||||||
|
@State var darker: Bool = false
|
||||||
|
@State var glass: Bool = false
|
||||||
|
@State var padding: CGFloat = 5
|
||||||
|
@EnvironmentObject var appState: AppState
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
HStack {
|
||||||
|
TextField("", text: $search)
|
||||||
|
.textFieldStyle(SimpleSearchStyle(trash: true, text: $search, darker: darker, glass: glass, padding: padding))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
//
|
|
||||||
// TopBar.swift
|
|
||||||
// Pearcleaner
|
|
||||||
//
|
|
||||||
// Created by Alin Lupascu on 11/10/23.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct TopBar: View {
|
|
||||||
@AppStorage("displayMode") var displayMode: DisplayMode = .system
|
|
||||||
@AppStorage("settings.general.glass") private var glass: Bool = false
|
|
||||||
@AppStorage("settings.sentinel.enable") private var sentinel: Bool = false
|
|
||||||
@AppStorage("settings.general.mini") private var mini: Bool = false
|
|
||||||
@EnvironmentObject var appState: AppState
|
|
||||||
@Binding var showPopover: Bool
|
|
||||||
@EnvironmentObject var locations: Locations
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
HStack(alignment: .center, spacing: 0) {
|
|
||||||
|
|
||||||
// Spacer()
|
|
||||||
//
|
|
||||||
// if appState.isReminderVisible {
|
|
||||||
// Text("CMD + Z to undo")
|
|
||||||
// .font(.title2)
|
|
||||||
// .foregroundStyle(Color("mode").opacity(0.5))
|
|
||||||
// .fontWeight(.medium)
|
|
||||||
// .onAppear {
|
|
||||||
// DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
|
|
||||||
// withAnimation {
|
|
||||||
// appState.isReminderVisible = false
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
HStack() {
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
if appState.currentView == .zombie {
|
|
||||||
Button("Rescan") {
|
|
||||||
updateOnMain {
|
|
||||||
appState.zombieFile = .empty
|
|
||||||
appState.showProgress.toggle()
|
|
||||||
reversePreloader(allApps: appState.sortedApps, appState: appState, locations: locations, reverseAddon: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.buttonStyle(SimpleButtonStyle(icon: "arrow.counterclockwise.circle.fill", help: "Rescan files"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if appState.currentView != .zombie {
|
|
||||||
Button("") {
|
|
||||||
withAnimation(.easeInOut(duration: 0.5)) {
|
|
||||||
updateOnMain {
|
|
||||||
appState.appInfo = .empty
|
|
||||||
appState.selectedZombieItems = []
|
|
||||||
if appState.zombieFile.fileSize.keys.count == 0 {
|
|
||||||
appState.currentView = .zombie
|
|
||||||
appState.showProgress.toggle()
|
|
||||||
showPopover.toggle()
|
|
||||||
reversePreloader(allApps: appState.sortedApps, appState: appState, locations: locations, reverseAddon: true)
|
|
||||||
} else {
|
|
||||||
appState.currentView = .zombie
|
|
||||||
showPopover.toggle()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.buttonStyle(SimpleButtonStyle(icon: "clock.arrow.circlepath", help: "Leftover Files"))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if appState.currentView == .files || appState.currentView == .zombie {
|
|
||||||
Button("") {
|
|
||||||
withAnimation(.easeInOut(duration: 0.5)) {
|
|
||||||
appState.currentView = .empty
|
|
||||||
appState.appInfo = AppInfo.empty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.buttonStyle(SimpleButtonStyle(icon: "plus.square.dashed", help: "Drop Target"))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
.padding(6)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
//
|
|
||||||
// TopBarMini.swift
|
|
||||||
// Pearcleaner
|
|
||||||
//
|
|
||||||
// Created by Alin Lupascu on 11/14/23.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct TopBarMini: View {
|
|
||||||
@AppStorage("displayMode") var displayMode: DisplayMode = .system
|
|
||||||
@AppStorage("settings.sentinel.enable") private var sentinel: Bool = false
|
|
||||||
@AppStorage("settings.general.mini") private var mini: Bool = false
|
|
||||||
@Binding var search: String
|
|
||||||
@Binding var showPopover: Bool
|
|
||||||
@EnvironmentObject var appState: AppState
|
|
||||||
@EnvironmentObject var locations: Locations
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
HStack(alignment: .center, spacing: 0) {
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
if appState.currentView == .empty {
|
|
||||||
|
|
||||||
HStack {
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
Button("") {
|
|
||||||
withAnimation(.easeInOut(duration: 0.5)) {
|
|
||||||
showPopover = false
|
|
||||||
updateOnMain {
|
|
||||||
if appState.zombieFile.fileSize.keys.count == 0 {
|
|
||||||
appState.currentView = .zombie
|
|
||||||
appState.showProgress.toggle()
|
|
||||||
showPopover.toggle()
|
|
||||||
reversePreloader(allApps: appState.sortedApps, appState: appState, locations: locations, reverseAddon: true)
|
|
||||||
} else {
|
|
||||||
appState.currentView = .zombie
|
|
||||||
showPopover.toggle()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.buttonStyle(SimpleButtonStyle(icon: "clock.arrow.circlepath", help: "Leftover Files"))
|
|
||||||
|
|
||||||
Button("") {
|
|
||||||
withAnimation(.easeInOut(duration: 0.5)) {
|
|
||||||
appState.currentView = .apps
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.buttonStyle(SimpleButtonStyle(icon: "square.grid.3x3.square", help: "Apps List"))
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if appState.currentView != .empty {
|
|
||||||
HStack {
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
Button("") {
|
|
||||||
withAnimation(.easeInOut(duration: 0.5)) {
|
|
||||||
showPopover = false
|
|
||||||
updateOnMain {
|
|
||||||
appState.appInfo = .empty
|
|
||||||
appState.selectedZombieItems = []
|
|
||||||
if appState.zombieFile.fileSize.keys.count == 0 {
|
|
||||||
appState.currentView = .zombie
|
|
||||||
appState.showProgress.toggle()
|
|
||||||
showPopover.toggle()
|
|
||||||
reversePreloader(allApps: appState.sortedApps, appState: appState, locations: locations, reverseAddon: true)
|
|
||||||
} else {
|
|
||||||
appState.currentView = .zombie
|
|
||||||
showPopover.toggle()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.buttonStyle(SimpleButtonStyle(icon: "clock.arrow.circlepath", help: "Leftover Files"))
|
|
||||||
|
|
||||||
Button("") {
|
|
||||||
withAnimation(.easeInOut(duration: 0.5)) {
|
|
||||||
appState.currentView = .empty
|
|
||||||
appState.appInfo = AppInfo.empty
|
|
||||||
showPopover = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.buttonStyle(SimpleButtonStyle(icon: "plus.square.dashed", help: "Drop Target"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
.padding(.horizontal, 10)
|
|
||||||
.padding(.top, 10)
|
|
||||||
.padding(.bottom, 5)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct SearchBarMini: View {
|
|
||||||
@Binding var search: String
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
HStack {
|
|
||||||
TextField("Search", text: $search)
|
|
||||||
.textFieldStyle(AnimatedSearchStyle(text: $search))
|
|
||||||
}
|
|
||||||
.frame(height: 20)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SearchBarMiniBottom: View {
|
|
||||||
@Binding var search: String
|
|
||||||
@EnvironmentObject var appState: AppState
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
HStack {
|
|
||||||
TextField(" Search", text: $search)
|
|
||||||
.textFieldStyle(SimpleSearchStyle(trash: true, text: $search))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -13,6 +13,7 @@ struct ZombieView: View {
|
|||||||
@EnvironmentObject var locations: Locations
|
@EnvironmentObject var locations: Locations
|
||||||
@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.general.glass") private var glass: Bool = false
|
||||||
@AppStorage("settings.sentinel.enable") private var sentinel: Bool = false
|
@AppStorage("settings.sentinel.enable") private var sentinel: Bool = false
|
||||||
@AppStorage("settings.menubar.enabled") private var menubarEnabled: Bool = false
|
@AppStorage("settings.menubar.enabled") private var menubarEnabled: Bool = false
|
||||||
@AppStorage("settings.general.selectedSort") var selectedSortAlpha: Bool = true
|
@AppStorage("settings.general.selectedSort") var selectedSortAlpha: Bool = true
|
||||||
@@ -108,19 +109,9 @@ struct ZombieView: View {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Titlebar
|
// Titlebar
|
||||||
if !regularWin {
|
|
||||||
HStack(spacing: 0) {
|
HStack(spacing: 0) {
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
Button("Rescan") {
|
|
||||||
updateOnMain {
|
|
||||||
appState.zombieFile = .empty
|
|
||||||
appState.showProgress.toggle()
|
|
||||||
reversePreloader(allApps: appState.sortedApps, appState: appState, locations: locations, reverseAddon: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.buttonStyle(SimpleButtonStyle(icon: "arrow.counterclockwise.circle.fill", help: "Rescan files"))
|
|
||||||
|
|
||||||
Button("Close") {
|
Button("Close") {
|
||||||
updateOnMain {
|
updateOnMain {
|
||||||
appState.appInfo = AppInfo.empty
|
appState.appInfo = AppInfo.empty
|
||||||
@@ -129,10 +120,11 @@ struct ZombieView: View {
|
|||||||
showPopover = false
|
showPopover = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.buttonStyle(SimpleButtonStyle(icon: "x.circle.fill", help: "Close"))
|
.buttonStyle(SimpleButtonStyle(icon: "x.circle", iconFlip: "x.circle.fill", help: "Close"))
|
||||||
}
|
|
||||||
.padding([.horizontal, .top], 5)
|
|
||||||
}
|
}
|
||||||
|
.padding(.top, 6)
|
||||||
|
.padding(.trailing, (mini || menubarEnabled) ? 6 : 0)
|
||||||
|
|
||||||
|
|
||||||
VStack() {
|
VStack() {
|
||||||
// Main Group
|
// Main Group
|
||||||
@@ -141,7 +133,7 @@ struct ZombieView: View {
|
|||||||
VStack(alignment: .center) {
|
VStack(alignment: .center) {
|
||||||
|
|
||||||
HStack(alignment: .center) {
|
HStack(alignment: .center) {
|
||||||
Image(systemName: "clock.arrow.circlepath")
|
Image(systemName: "doc.badge.clock.fill")
|
||||||
.resizable()
|
.resizable()
|
||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
.frame(width: 50, height: 50)
|
.frame(width: 50, height: 50)
|
||||||
@@ -185,9 +177,11 @@ struct ZombieView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
|
.toggleStyle(SimpleCheckboxToggleStyle())
|
||||||
|
.help("All checkboxes")
|
||||||
|
|
||||||
SearchBarMiniBottom(search: $searchZ)
|
|
||||||
// .padding(.top)
|
SearchBar(search: $searchZ, darker: true, glass: glass)
|
||||||
.padding(.horizontal)
|
.padding(.horizontal)
|
||||||
|
|
||||||
|
|
||||||
@@ -212,11 +206,7 @@ struct ZombieView: View {
|
|||||||
let iconImage = fileIcon.map(Image.init(nsImage:))
|
let iconImage = fileIcon.map(Image.init(nsImage:))
|
||||||
VStack {
|
VStack {
|
||||||
ZombieFileDetailsItem(size: fileSize, sizeL: fileSizeL, icon: iconImage, path: file)
|
ZombieFileDetailsItem(size: fileSize, sizeL: fileSizeL, icon: iconImage, path: file)
|
||||||
.padding(.trailing)
|
.padding(.vertical, 5)
|
||||||
|
|
||||||
if index < filteredAndSortedFiles.0.count - 1 {
|
|
||||||
Divider().padding(.leading, 40).opacity(0.5)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,8 +216,9 @@ struct ZombieView: View {
|
|||||||
.onChange(of: sizeType) { _ in
|
.onChange(of: sizeType) { _ in
|
||||||
localKey = UUID()
|
localKey = UUID()
|
||||||
}
|
}
|
||||||
.id(localKey)
|
|
||||||
}
|
}
|
||||||
|
.id(localKey)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
@@ -236,30 +227,45 @@ struct ZombieView: View {
|
|||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
|
Button("Rescan") {
|
||||||
|
updateOnMain {
|
||||||
|
appState.zombieFile = .empty
|
||||||
|
appState.showProgress.toggle()
|
||||||
|
reversePreloader(allApps: appState.sortedApps, appState: appState, locations: locations, reverseAddon: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.buttonStyle(RescanButton())
|
||||||
|
|
||||||
Button("\(sizeType == "Logical" ? totalSelectedZombieSize.logical : sizeType == "Finder" ? totalSelectedZombieSize.finder : totalSelectedZombieSize.real)") {
|
Button("\(sizeType == "Logical" ? totalSelectedZombieSize.logical : sizeType == "Finder" ? totalSelectedZombieSize.finder : totalSelectedZombieSize.real)") {
|
||||||
Task {
|
Task {
|
||||||
|
if appState.selectedZombieItems.count == appState.zombieFile.fileSize.keys.count {
|
||||||
updateOnMain {
|
updateOnMain {
|
||||||
appState.zombieFile = .empty
|
appState.zombieFile = .empty
|
||||||
search = ""
|
search = ""
|
||||||
if !regularWin {
|
searchZ = ""
|
||||||
|
if mini || menubarEnabled {
|
||||||
appState.currentView = .apps
|
appState.currentView = .apps
|
||||||
showPopover = false
|
showPopover = false
|
||||||
} else {
|
} else {
|
||||||
appState.currentView = .empty
|
appState.currentView = .empty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let selectedItemsArray = Array(appState.selectedZombieItems)
|
let selectedItemsArray = Array(appState.selectedZombieItems)
|
||||||
|
|
||||||
killApp(appId: appState.appInfo.bundleIdentifier) {
|
|
||||||
moveFilesToTrash(at: selectedItemsArray) {
|
moveFilesToTrash(at: selectedItemsArray) {
|
||||||
withAnimation {
|
withAnimation {
|
||||||
showPopover = false
|
showPopover = false
|
||||||
// updateOnMain {
|
|
||||||
// appState.isReminderVisible.toggle()
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
updateOnMain {
|
||||||
|
// Remove items from the list
|
||||||
|
appState.zombieFile.fileSize = appState.zombieFile.fileSize.filter { !appState.selectedZombieItems.contains($0.key) }
|
||||||
|
// Update the selectedZombieFiles to remove references that are no longer present
|
||||||
|
appState.selectedZombieItems.removeAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -267,20 +273,16 @@ struct ZombieView: View {
|
|||||||
}
|
}
|
||||||
.buttonStyle(UninstallButton(isEnabled: !appState.selectedZombieItems.isEmpty))
|
.buttonStyle(UninstallButton(isEnabled: !appState.selectedZombieItems.isEmpty))
|
||||||
.disabled(appState.selectedZombieItems.isEmpty)
|
.disabled(appState.selectedZombieItems.isEmpty)
|
||||||
.padding(.top)
|
|
||||||
|
|
||||||
|
|
||||||
// Spacer()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
.padding(.top)
|
||||||
}
|
}
|
||||||
.transition(.opacity)
|
.transition(.opacity)
|
||||||
.padding([.horizontal, .bottom], 20)
|
.padding([.horizontal, .bottom], 20)
|
||||||
.padding(.top, !mini ? 10 : 0)
|
.padding(.top, !mini ? 10 : 0)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -309,6 +311,7 @@ struct ZombieFileDetailsItem: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
|
.toggleStyle(SimpleCheckboxToggleStyle())
|
||||||
|
|
||||||
if let appIcon = icon {
|
if let appIcon = icon {
|
||||||
appIcon
|
appIcon
|
||||||
@@ -316,10 +319,9 @@ struct ZombieFileDetailsItem: View {
|
|||||||
.aspectRatio(contentMode: .fit)
|
.aspectRatio(contentMode: .fit)
|
||||||
.frame(width: 30, height: 30)
|
.frame(width: 30, height: 30)
|
||||||
.clipShape(RoundedRectangle(cornerRadius: 8))
|
.clipShape(RoundedRectangle(cornerRadius: 8))
|
||||||
.brightness(isHovered ? 0.2 : 0)
|
|
||||||
.shadow(color: Color("mode"), radius: isHovered ? 2 : 0)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 5) {
|
VStack(alignment: .leading, spacing: 5) {
|
||||||
|
|
||||||
HStack(alignment: .center) {
|
HStack(alignment: .center) {
|
||||||
@@ -328,6 +330,17 @@ struct ZombieFileDetailsItem: View {
|
|||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
.truncationMode(.tail)
|
.truncationMode(.tail)
|
||||||
.help(path.lastPathComponent)
|
.help(path.lastPathComponent)
|
||||||
|
.overlay{
|
||||||
|
if (isHovered) {
|
||||||
|
VStack {
|
||||||
|
Spacer()
|
||||||
|
RoundedRectangle(cornerRadius: 10)
|
||||||
|
.fill(Color("mode").opacity(0.5))
|
||||||
|
.frame(height: 1.5)
|
||||||
|
.offset(y: 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let imageView = folderImages(for: path.path) {
|
if let imageView = folderImages(for: path.path) {
|
||||||
imageView
|
imageView
|
||||||
@@ -341,6 +354,14 @@ struct ZombieFileDetailsItem: View {
|
|||||||
.opacity(0.5)
|
.opacity(0.5)
|
||||||
.help(path.path)
|
.help(path.path)
|
||||||
}
|
}
|
||||||
|
.onHover { hovering in
|
||||||
|
withAnimation(Animation.easeIn(duration: 0.2)) {
|
||||||
|
self.isHovered = hovering
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onTapGesture {
|
||||||
|
NSWorkspace.shared.selectFile(path.path, inFileViewerRootedAtPath: path.deletingLastPathComponent().path)
|
||||||
|
}
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
@@ -351,14 +372,6 @@ struct ZombieFileDetailsItem: View {
|
|||||||
Text("\(displaySize)")
|
Text("\(displaySize)")
|
||||||
|
|
||||||
}
|
}
|
||||||
.onHover { hovering in
|
|
||||||
withAnimation(Animation.easeIn(duration: 0.2)) {
|
|
||||||
self.isHovered = hovering
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.onTapGesture {
|
|
||||||
NSWorkspace.shared.selectFile(path.path, inFileViewerRootedAtPath: path.deletingLastPathComponent().path)
|
|
||||||
}
|
|
||||||
.contextMenu {
|
.contextMenu {
|
||||||
if path.pathExtension == "app" {
|
if path.pathExtension == "app" {
|
||||||
Button("Open \(path.deletingPathExtension().lastPathComponent)") {
|
Button("Open \(path.deletingPathExtension().lastPathComponent)") {
|
||||||
|
|||||||
Reference in New Issue
Block a user