From 451ec46218d0a5ac206441a48e5aa5b926209eb0 Mon Sep 17 00:00:00 2001 From: Cameron Katri Date: Wed, 29 Dec 2021 10:41:53 -0500 Subject: I hate this project --- .../QuickActionsPrefs/LSApplicationProxy+AltList.h | 28 ++ .../QuickActionsPrefs/LSApplicationProxy+AltList.m | 125 ++++++++ .../QuickActionsPrefs/QASAppSelectorController.h | 22 +- .../QuickActionsPrefs/QASAppSelectorController.m | 341 +++++++++------------ .../QuickActionsPrefs/QASRootListController.m | 3 +- 5 files changed, 314 insertions(+), 205 deletions(-) create mode 100644 QuickActions/QuickActionsPrefs/LSApplicationProxy+AltList.h create mode 100644 QuickActions/QuickActionsPrefs/LSApplicationProxy+AltList.m (limited to 'QuickActions/QuickActionsPrefs') diff --git a/QuickActions/QuickActionsPrefs/LSApplicationProxy+AltList.h b/QuickActions/QuickActionsPrefs/LSApplicationProxy+AltList.h new file mode 100644 index 0000000..65866ab --- /dev/null +++ b/QuickActions/QuickActionsPrefs/LSApplicationProxy+AltList.h @@ -0,0 +1,28 @@ +#import + +@interface LSApplicationRecord : NSObject +@property (nonatomic,readonly) NSArray* appTags; +@property (getter=isLaunchProhibited,readonly) BOOL launchProhibited; +@end + +@interface LSApplicationProxy : NSObject +@property (nonatomic,readonly) NSArray* appTags; +@property (getter=isLaunchProhibited,nonatomic,readonly) BOOL launchProhibited; +@property (nonatomic,readonly) NSString* localizedName; ++(LSApplicationProxy *)applicationProxyForIdentifier:(NSString *)id; +-(NSString *)localizedNameForContext:(id)arg; +-(NSURL *)bundleURL; +-(NSString *)bundleIdentifier; +-(LSApplicationRecord *)correspondingApplicationRecord; +@end + +@interface LSApplicationProxy (AltList) +-(BOOL)atl_isHidden; +-(NSString *)atl_fastDisplayName; +-(NSString *)atl_nameToDisplay; +@end + +@interface LSApplicationWorkspace : NSObject ++(LSApplicationWorkspace *)defaultWorkspace; +-(NSArray *)allApplications; +@end \ No newline at end of file diff --git a/QuickActions/QuickActionsPrefs/LSApplicationProxy+AltList.m b/QuickActions/QuickActionsPrefs/LSApplicationProxy+AltList.m new file mode 100644 index 0000000..ab6c292 --- /dev/null +++ b/QuickActions/QuickActionsPrefs/LSApplicationProxy+AltList.m @@ -0,0 +1,125 @@ +#import +#import "LSApplicationProxy+AltList.h" + +@implementation LSApplicationProxy (AltList) +// the tag " hidden " is also valid, so we need to check if any strings contain "hidden" instead +BOOL tagArrayContainsTag(NSArray* tagArr, NSString* tag) +{ + if(!tagArr || !tag) return NO; + + __block BOOL found = NO; + + [tagArr enumerateObjectsUsingBlock:^(NSString* tagToCheck, NSUInteger idx, BOOL* stop) + { + if(![tagToCheck isKindOfClass:[NSString class]]) + { + return; + } + + if([tagToCheck rangeOfString:tag options:0].location != NSNotFound) + { + found = YES; + *stop = YES; + } + }]; + + return found; +} + +// always returns NO on iOS 7 +- (BOOL)atl_isHidden +{ + NSArray* appTags; + NSArray* recordAppTags; + NSArray* sbAppTags; + + BOOL launchProhibited = NO; + + if([self respondsToSelector:@selector(correspondingApplicationRecord)]) + { + // On iOS 14, self.appTags is always empty but the application record still has the correct ones + LSApplicationRecord* record = [self correspondingApplicationRecord]; + recordAppTags = record.appTags; + launchProhibited = record.launchProhibited; + } + if([self respondsToSelector:@selector(appTags)]) + { + appTags = self.appTags; + } + if(!launchProhibited && [self respondsToSelector:@selector(isLaunchProhibited)]) + { + launchProhibited = self.launchProhibited; + } + + NSURL* bundleURL = self.bundleURL; + if(bundleURL && [bundleURL checkResourceIsReachableAndReturnError:nil]) + { + NSBundle* bundle = [NSBundle bundleWithURL:bundleURL]; + sbAppTags = [bundle objectForInfoDictionaryKey:@"SBAppTags"]; + } + + BOOL isWebApplication = ([self.bundleIdentifier rangeOfString:@"com.apple.webapp" options:NSCaseInsensitiveSearch].location != NSNotFound); + return tagArrayContainsTag(appTags, @"hidden") || tagArrayContainsTag(recordAppTags, @"hidden") || tagArrayContainsTag(sbAppTags, @"hidden") || isWebApplication || launchProhibited; +} + +// Getting the display name is slow (up to 2ms) because it uses an IPC call +// this stacks up if you do it for every single application +// This method provides a faster way (around 0.5ms) to get the display name +// This reduces the overall time needed to sort the applications from ~230 to ~120ms on my test device +- (NSString*)atl_fastDisplayName +{ + NSString* cachedDisplayName = [self valueForKey:@"_localizedName"]; + if(cachedDisplayName && ![cachedDisplayName isEqualToString:@""]) + { + return cachedDisplayName; + } + + NSString* localizedName; + + NSURL* bundleURL = self.bundleURL; + if(!bundleURL || ![bundleURL checkResourceIsReachableAndReturnError:nil]) + { + localizedName = self.localizedName; + } + else + { + NSBundle* bundle = [NSBundle bundleWithURL:bundleURL]; + + localizedName = [bundle objectForInfoDictionaryKey:@"CFBundleDisplayName"]; + if(![localizedName isKindOfClass:[NSString class]]) localizedName = nil; + if(!localizedName || [localizedName isEqualToString:@""]) + { + localizedName = [bundle objectForInfoDictionaryKey:@"CFBundleName"]; + if(![localizedName isKindOfClass:[NSString class]]) localizedName = nil; + if(!localizedName || [localizedName isEqualToString:@""]) + { + localizedName = [bundle objectForInfoDictionaryKey:@"CFBundleExecutable"]; + if(![localizedName isKindOfClass:[NSString class]]) localizedName = nil; + if(!localizedName || [localizedName isEqualToString:@""]) + { + //last possible fallback: use slow IPC call + localizedName = self.localizedName; + } + } + } + } + + [self setValue:localizedName forKey:@"_localizedName"]; + return localizedName; +} + +- (NSString*)atl_nameToDisplay +{ + NSString* localizedName = [self atl_fastDisplayName]; + + if([self.bundleIdentifier rangeOfString:@"carplay" options:NSCaseInsensitiveSearch].location != NSNotFound) + { + if([localizedName rangeOfString:@"carplay" options:NSCaseInsensitiveSearch range:NSMakeRange(0, localizedName.length) locale:[NSLocale currentLocale]].location == NSNotFound) + { + return [localizedName stringByAppendingString:@" (CarPlay)"]; + } + } + + return localizedName; +} +@end \ No newline at end of file diff --git a/QuickActions/QuickActionsPrefs/QASAppSelectorController.h b/QuickActions/QuickActionsPrefs/QASAppSelectorController.h index 13ffe60..f439fcb 100644 --- a/QuickActions/QuickActionsPrefs/QASAppSelectorController.h +++ b/QuickActions/QuickActionsPrefs/QASAppSelectorController.h @@ -1,18 +1,28 @@ #import #import "PSDetailController.h" +#import "LSApplicationProxy+AltList.h" @interface UIImage (Private) +(instancetype)_applicationIconImageForBundleIdentifier:(NSString*)bundleIdentifier format:(int)format scale:(CGFloat)scale; -(UIImage *)_applicationIconImageForFormat:(int)format precomposed:(BOOL)precomposed scale:(CGFloat)scale; @end -@interface QASAppSelectorController : PSDetailController +typedef enum { + ENABLED = 0, + SYSTEM, + APPS +} ItemType; + +@interface QASAppSelectorController : PSDetailController { + UISearchController *_searchController; + NSString *_searchKey; +} @property (nonatomic) UITableView *tableView; -@property (nonatomic) NSMutableArray *enabled; -@property (nonatomic) NSMutableArray *disabled; -@property (nonatomic) NSArray *systemAvailable; -@property (nonatomic) NSMutableArray *systemDisabled; +@property (nonatomic) NSMutableArray *enabled; +@property (nonatomic) NSMutableArray*disabled; +@property (nonatomic) NSArray *systemDisabled; @property (nonatomic) NSString *key; @property (nonatomic) NSString *defaults; +-(NSArray *)filteredDisabled; @end \ No newline at end of file diff --git a/QuickActions/QuickActionsPrefs/QASAppSelectorController.m b/QuickActions/QuickActionsPrefs/QASAppSelectorController.m index cfb6c7a..cadca5c 100644 --- a/QuickActions/QuickActionsPrefs/QASAppSelectorController.m +++ b/QuickActions/QuickActionsPrefs/QASAppSelectorController.m @@ -1,45 +1,9 @@ #import -#include #import #import -#import "QASAppSelectorController.h" -@interface LSApplicationRecord -@property (readonly) NSArray * appTags; -@property (getter=isLaunchProhibited,readonly) BOOL launchProhibited; -@end - -@interface LSApplicationProxy : NSObject -@property (getter=isLaunchProhibited, nonatomic, readonly) BOOL launchProhibited; -@property (nonatomic, readonly) NSArray *appTags; -@property (nonatomic,readonly) LSApplicationRecord * correspondingApplicationRecord; -+ (id)applicationProxyForIdentifier:(id)arg1; -- (id)localizedNameForContext:(id)arg1; -- (NSString *)bundleIdentifier; -- (NSString *)applicationType; -- (NSURL *)bundleURL; -@end - -@interface LSApplicationProxy (StolenFromAltList) -- (BOOL)atl_isHidden; -@end - -@interface LSApplicationWorkspace : NSObject -+(id)defaultWorkspace; --(NSArray *)allApplications; -@end - -@interface NSMutableArray (Custom) --(void)sortApps; -@end - -// @interface ListItem : NSObject -// @property (nonatomic, retain) NSString *name; -// @property (nonatomic, retain) NSString *bundleID; -// @property (nonatomic, retain) NSString *type; -// @property (nonatomic, retain) UIImage *icon; -// -(ListItem *)initWithName:(NSString *)name bundleID:(NSString *)bundleID type:(NSString *)type icon:(UIImage *)icon; -// @end +#import "QASAppSelectorController.h" +#import "LSApplicationProxy+AltList.h" @implementation QASAppSelectorController -(void)viewDidLoad @@ -54,6 +18,8 @@ self.disabled = [NSMutableArray new]; self.enabled = [NSMutableArray new]; + self.systemDisabled = @[ @"com.apple.camera", @"com.apple.donotdisturb", @"com.apple.flashlight" ]; + NSArray *defaults = [[[NSUserDefaults alloc] initWithSuiteName:self.defaults] arrayForKey:self.key]; if (defaults == nil) { @@ -65,56 +31,92 @@ [self.enabled addObjectsFromArray:defaults]; for (LSApplicationProxy *proxy in [[LSApplicationWorkspace defaultWorkspace] allApplications]) { - if (![proxy atl_isHidden] && [self.enabled indexOfObject:proxy.bundleIdentifier] == NSNotFound) - [self.disabled addObject:proxy.bundleIdentifier]; + if (![proxy atl_isHidden] && ![[proxy bundleIdentifier] isEqualToString:@"com.apple.camera"]) { + [self.disabled addObject:proxy]; + } } - if ([self.enabled indexOfObject:@"com.apple.flashlight"] == NSNotFound) - [self.disabled addObject:@"com.apple.flashlight"]; + [self.disabled sortUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"atl_fastDisplayName" + ascending:YES + selector:@selector(localizedCaseInsensitiveCompare:)]]]; - if ([self.enabled indexOfObject:@"com.apple.donotdisturb"] == NSNotFound) - [self.disabled addObject:@"com.apple.donotdisturb"]; + _searchController = [[UISearchController alloc] initWithSearchResultsController:nil]; + _searchController.searchResultsUpdater = self; + _searchController.obscuresBackgroundDuringPresentation = NO; + _searchController.searchBar.delegate = self; - [self.disabled sortApps]; + self.navigationItem.searchController = _searchController; + self.navigationItem.hidesSearchBarWhenScrolling = NO; + + self.definesPresentationContext = YES; +} + +-(void)updateSearchResultsForSearchController:(UISearchController *)searchController { + _searchKey = searchController.searchBar.text; + [self.tableView reloadData]; } +-(BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar { return YES; } + -(void)viewWillAppear:(BOOL)animated { - self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped]; - self.tableView.delegate = self; - self.tableView.dataSource = self; - self.tableView.editing = TRUE; + [super viewWillAppear:animated]; - [self.view addSubview:self.tableView]; + if (self.tableView == nil) { + self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped]; + self.tableView.delegate = self; + self.tableView.dataSource = self; + self.tableView.editing = TRUE; + + [self.view addSubview:self.tableView]; + } } -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { - if (section == 0) - return @"Enabled"; - else if (section == 1) - return @"Disabled"; - else - return @""; + switch ((ItemType)section) { + case ENABLED: + return @"Enabled"; + case SYSTEM: + return @"System"; + case APPS: + return @"Apps"; + } } -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 2; + return 3; } -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - if (section == 0) - return self.enabled.count; - else - return self.disabled.count; + switch ((ItemType)section) { + case ENABLED: + return self.enabled.count; + case SYSTEM: + return self.systemDisabled.count; + case APPS: + return self.filteredDisabled.count; + } } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - NSString *bundleid = indexPath.section == 0 ? self.enabled[indexPath.row] : self.disabled[indexPath.row]; - + NSObject *item; + + switch ((ItemType)indexPath.section) { + case ENABLED: + item = self.enabled[indexPath.row]; + break; + case SYSTEM: + item = self.systemDisabled[indexPath.row]; + break; + case APPS: + item = self.filteredDisabled[indexPath.row]; + break; + } + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"com.cameronkatri.quickactions"]; if (cell == nil) { @@ -122,32 +124,45 @@ cell.selectionStyle = UITableViewCellSelectionStyleNone; } - - if ([bundleid isEqualToString:@"com.apple.flashlight"]) { - cell.textLabel.text = @"Flashlight"; - cell.detailTextLabel.text = nil; - NSBundle *flashlightModule = [NSBundle bundleWithPath:@"/System/Library/ControlCenter/Bundles/FlashlightModule.bundle"]; - cell.imageView.image = [[UIImage imageNamed:@"SettingsIcon" - inBundle:flashlightModule - compatibleWithTraitCollection:nil] _applicationIconImageForFormat:0 precomposed:YES scale:[UIScreen mainScreen].scale]; - } else if ([bundleid isEqualToString:@"com.apple.donotdisturb"]) { + + if ([item isKindOfClass:[NSString class]] && [(NSString*)item isEqualToString:@"com.apple.donotdisturb"]) { cell.textLabel.text = @"Do Not Disturb"; cell.detailTextLabel.text = nil; + NSBundle *doNotDisturbBundle = [NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/DoNotDisturb.framework/PlugIns/DoNotDisturbIntents.appex"]; cell.imageView.image = [[UIImage imageNamed:@"DoNotDisturb" - inBundle:doNotDisturbBundle - compatibleWithTraitCollection:nil] _applicationIconImageForFormat:0 precomposed:YES scale:[UIScreen mainScreen].scale]; + inBundle:doNotDisturbBundle + compatibleWithTraitCollection:nil] _applicationIconImageForFormat:0 + precomposed:YES + scale:[UIScreen mainScreen].scale]; + } else if ([item isKindOfClass:[NSString class]] && [(NSString*)item isEqualToString:@"com.apple.flashlight"]) { + cell.textLabel.text = @"Flashlight"; + cell.detailTextLabel.text = nil; + NSBundle *flashlightModule = [NSBundle bundleWithPath:@"/System/Library/ControlCenter/Bundles/FlashlightModule.bundle"]; + cell.imageView.image = [[UIImage imageNamed:@"SettingsIcon" + inBundle:flashlightModule + compatibleWithTraitCollection:nil] _applicationIconImageForFormat:0 + precomposed:YES + scale:[UIScreen mainScreen].scale]; } else { - cell.textLabel.text = [[LSApplicationProxy applicationProxyForIdentifier:bundleid] localizedNameForContext:nil]; - if (cell.textLabel.text == nil) { - cell.textLabel.text = bundleid; - cell.detailTextLabel.text = nil; + LSApplicationProxy *proxy; + if ([item isKindOfClass:[NSString class]]) { + proxy = [LSApplicationProxy applicationProxyForIdentifier:(NSString*)item]; } else { - cell.detailTextLabel.text = bundleid; + proxy = (LSApplicationProxy*)item; } + cell.textLabel.text = [proxy atl_nameToDisplay]; + if (cell.textLabel.text == nil) { + cell.textLabel.text = [proxy bundleIdentifier]; + cell.detailTextLabel.text = nil; + } else + cell.detailTextLabel.text = [proxy bundleIdentifier]; cell.detailTextLabel.textColor = [UIColor secondaryLabelColor]; - cell.imageView.image = [UIImage _applicationIconImageForBundleIdentifier:bundleid format:0 scale:[UIScreen mainScreen].scale]; + cell.imageView.image = [UIImage _applicationIconImageForBundleIdentifier:[proxy bundleIdentifier] + format:0 + scale:[UIScreen mainScreen].scale]; } + cell.showsReorderControl = indexPath.section == 0 ? YES : FALSE; @@ -156,29 +171,32 @@ -(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { - return indexPath.section == 0 ? UITableViewCellEditingStyleDelete : UITableViewCellEditingStyleInsert; + return indexPath.section == ENABLED ? UITableViewCellEditingStyleDelete : UITableViewCellEditingStyleInsert; } -(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { - return indexPath.section == 0 ? YES : FALSE; + return indexPath.section == ENABLED ? YES : FALSE; } -(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(nonnull NSIndexPath *)sourceIndexPath toIndexPath:(nonnull NSIndexPath *)destinationIndexPath { - if (sourceIndexPath.section == 0) { - if (destinationIndexPath.section == 0) - [self.enabled exchangeObjectAtIndex:sourceIndexPath.row withObjectAtIndex:destinationIndexPath.row]; - else { - [self.disabled addObject:self.enabled[sourceIndexPath.row]]; - [self.enabled removeObjectAtIndex:sourceIndexPath.row]; - } - } else { - [self.enabled insertObject:self.disabled[sourceIndexPath.row] atIndex:destinationIndexPath.row]; - [self.disabled removeObjectAtIndex:sourceIndexPath.row]; + switch ((ItemType)sourceIndexPath.section) { + case ENABLED: + if (destinationIndexPath.section == ENABLED) { + NSString *item = self.enabled[sourceIndexPath.row]; + [self.enabled removeObjectAtIndex:sourceIndexPath.row]; + [self.enabled insertObject:item atIndex:destinationIndexPath.row]; + } + break; + case SYSTEM: + [self.enabled insertObject:self.systemDisabled[sourceIndexPath.row] atIndex:destinationIndexPath.row]; + break; + case APPS: + [self.enabled insertObject:self.filteredDisabled[sourceIndexPath.row].bundleIdentifier atIndex:destinationIndexPath.row]; + break; } - [self.disabled sortApps]; [tableView reloadData]; [[[NSUserDefaults alloc] initWithSuiteName:self.defaults] setObject:self.enabled forKey:self.key]; @@ -186,125 +204,52 @@ -(NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath { - if (sourceIndexPath.section == 0 && proposedDestinationIndexPath.section == 1) { - NSUInteger insPoint = [self.disabled - indexOfObject:self.enabled[sourceIndexPath.row] - inSortedRange:NSMakeRange(0, [self.disabled count]) - options:NSBinarySearchingInsertionIndex - usingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2) { - if ([obj1 isEqualToString:@"com.apple.flashlight"]) - return NSOrderedAscending; - else if ([obj2 isEqualToString:@"com.apple.flashlight"]) - return NSOrderedDescending; - NSString *obj1Name = [[LSApplicationProxy applicationProxyForIdentifier:obj1] localizedNameForContext:nil]; - NSString *obj2Name = [[LSApplicationProxy applicationProxyForIdentifier:obj2] localizedNameForContext:nil]; - return ([obj1Name localizedCaseInsensitiveCompare:obj2Name]); - }]; - return [NSIndexPath indexPathForRow:insPoint inSection:1]; - } + if (sourceIndexPath.section == ENABLED && proposedDestinationIndexPath.section != ENABLED) + return [NSIndexPath indexPathForRow:(self.enabled.count - 1) inSection:0]; + return proposedDestinationIndexPath; } -(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(nonnull NSIndexPath *)indexPath { - NSString *item = indexPath.section == 0 ? self.enabled[indexPath.row] : self.disabled[indexPath.row]; - NSIndexPath *insertPath; + NSString *item; + switch ((ItemType)indexPath.section) { + case ENABLED: + item = self.enabled[indexPath.row]; + break; + case SYSTEM: + item = self.systemDisabled[indexPath.row]; + break; + case APPS: + item = self.filteredDisabled[indexPath.row].bundleIdentifier; + break; + } - if (editingStyle == UITableViewCellEditingStyleDelete) { - [self.enabled removeObject:item]; - [self.disabled addObject:item]; - [self.disabled sortApps]; + [tableView beginUpdates]; - insertPath = [NSIndexPath indexPathForRow:[self.disabled indexOfObject:item] inSection:1]; + if (editingStyle == UITableViewCellEditingStyleDelete) { + [self.enabled removeObjectAtIndex:indexPath.row]; + [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; } else if (editingStyle == UITableViewCellEditingStyleInsert) { - [self.disabled removeObject:item]; - [self.enabled addObject:item]; - - insertPath = [NSIndexPath indexPathForRow:([self.enabled count] - 1) inSection:0]; + [self.enabled insertObject:item atIndex:self.enabled.count]; + [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:([self.enabled count] - 1) inSection:0]] withRowAnimation:UITableViewRowAnimationFade]; } - - [tableView beginUpdates]; - [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:insertPath] withRowAnimation:UITableViewRowAnimationFade]; - [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; + [tableView endUpdates]; [[[NSUserDefaults alloc] initWithSuiteName:self.defaults] setObject:self.enabled forKey:self.key]; } -@end - -@implementation NSMutableArray (Custom) --(void)sortApps { - [self sortUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2) { - if ([obj1 isEqualToString:@"com.apple.flashlight"]) - return NSOrderedAscending; - else if ([obj2 isEqualToString:@"com.apple.flashlight"]) - return NSOrderedDescending; - - NSString *obj1Name = [[LSApplicationProxy applicationProxyForIdentifier:obj1] localizedNameForContext:nil]; - NSString *obj2Name = [[LSApplicationProxy applicationProxyForIdentifier:obj2] localizedNameForContext:nil]; - - return ([obj1Name localizedCaseInsensitiveCompare:obj2Name]); - }]; -} -@end - -@implementation LSApplicationProxy (StolenFromAltList) -BOOL tagArrayContainsTag(NSArray* tagArr, NSString* tag) -{ - if(!tagArr || !tag) return NO; - - __block BOOL found = NO; - - [tagArr enumerateObjectsUsingBlock:^(NSString* tagToCheck, NSUInteger idx, BOOL* stop) - { - if(![tagToCheck isKindOfClass:[NSString class]]) - { - return; - } - - if([tagToCheck rangeOfString:tag options:0].location != NSNotFound) - { - found = YES; - *stop = YES; +-(NSArray *)filteredDisabled { + if ([_searchKey length] == 0) { + return self.disabled; + } else { + NSMutableArray *filteredArray = [NSMutableArray new]; + for (LSApplicationProxy *proxy in self.disabled) { + if ([proxy.bundleIdentifier rangeOfString:_searchKey options:NSCaseInsensitiveSearch].location != NSNotFound || [proxy.atl_fastDisplayName rangeOfString:_searchKey options:NSCaseInsensitiveSearch range:NSMakeRange(0, [proxy.atl_fastDisplayName length]) locale:[NSLocale currentLocale]].location != NSNotFound) + [filteredArray addObject:proxy]; } - }]; - - return found; -} - -- (BOOL)atl_isHidden -{ - NSArray* appTags; - NSArray* recordAppTags; - NSArray* sbAppTags; - - BOOL launchProhibited = NO; - - if([self respondsToSelector:@selector(correspondingApplicationRecord)]) - { - // On iOS 14, self.appTags is always empty but the application record still has the correct ones - LSApplicationRecord* record = [self correspondingApplicationRecord]; - recordAppTags = record.appTags; - launchProhibited = record.launchProhibited; - } - if([self respondsToSelector:@selector(appTags)]) - { - appTags = self.appTags; - } - if(!launchProhibited && [self respondsToSelector:@selector(isLaunchProhibited)]) - { - launchProhibited = self.launchProhibited; + return filteredArray; } - - NSURL* bundleURL = self.bundleURL; - if(bundleURL && [bundleURL checkResourceIsReachableAndReturnError:nil]) - { - NSBundle* bundle = [NSBundle bundleWithURL:bundleURL]; - sbAppTags = [bundle objectForInfoDictionaryKey:@"SBAppTags"]; - } - - BOOL isWebApplication = ([self.bundleIdentifier rangeOfString:@"com.apple.webapp" options:NSCaseInsensitiveSearch].location != NSNotFound); - return tagArrayContainsTag(appTags, @"hidden") || tagArrayContainsTag(recordAppTags, @"hidden") || tagArrayContainsTag(sbAppTags, @"hidden") || isWebApplication || launchProhibited; } -@end +@end \ No newline at end of file diff --git a/QuickActions/QuickActionsPrefs/QASRootListController.m b/QuickActions/QuickActionsPrefs/QASRootListController.m index 2fe7cb2..0d26dc7 100644 --- a/QuickActions/QuickActionsPrefs/QASRootListController.m +++ b/QuickActions/QuickActionsPrefs/QASRootListController.m @@ -14,6 +14,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ +#import "Preferences/PSTableCell.h" #import #import "QASRootListController.h" #include @@ -32,7 +33,7 @@ -(void)viewDidLoad { [super viewDidLoad]; - UIBarButtonItem *respringButton = [[UIBarButtonItem alloc] initWithTitle:@"Respring" + UIBarButtonItem *respringButton = [[UIBarButtonItem alloc] initWithTitle:@"Apply" style:UIBarButtonItemStylePlain target:self action:@selector(respring)]; -- cgit v1.2.3-56-ge451