From 15240ea1e0dc4fc86a3f36cffe5b9c14ff0b2c93 Mon Sep 17 00:00:00 2001 From: Cameron Katri Date: Mon, 27 Dec 2021 01:08:28 -0500 Subject: I lost track of all the changes --- QuickActions/DragonMake | 32 +++ QuickActions/Makefile | 19 -- QuickActions/QuickActionsPrefs/Makefile | 16 -- .../QuickActionsPrefs/PSDetailController.h | 30 ++ .../QuickActionsPrefs/QASAppSelectorController.h | 18 ++ .../QuickActionsPrefs/QASAppSelectorController.m | 310 +++++++++++++++++++++ .../QuickActionsPrefs/Resources/Root.plist | 110 +++++--- QuickActions/Tweak.h | 41 ++- QuickActions/Tweak.x | 184 ++++++++++-- QuickActions/control | 9 - 10 files changed, 659 insertions(+), 110 deletions(-) create mode 100644 QuickActions/DragonMake delete mode 100644 QuickActions/Makefile delete mode 100644 QuickActions/QuickActionsPrefs/Makefile create mode 100644 QuickActions/QuickActionsPrefs/PSDetailController.h create mode 100644 QuickActions/QuickActionsPrefs/QASAppSelectorController.h create mode 100644 QuickActions/QuickActionsPrefs/QASAppSelectorController.m delete mode 100644 QuickActions/control (limited to 'QuickActions') diff --git a/QuickActions/DragonMake b/QuickActions/DragonMake new file mode 100644 index 0000000..f75e655 --- /dev/null +++ b/QuickActions/DragonMake @@ -0,0 +1,32 @@ +name: QuickActions +id: com.cameronkatri.quickactions +depends: mobilesubstrate +architecture: iphoneos-arm +version: 1.0.0 +description: Quickly launch apps from the lockscreen +author: Cameron Katri +section: Tweaks +depends: mobilesubstrate, preferenceloader +icmd: sbreload + +QuickActions: + type: tweak + filter: + executables: + - SpringBoard + files: + - Tweak.x + frameworks: + - CoverSheet + - SpringBoardFoundation + targetvers: 13.0 + +QuickActionsPrefs: + type: prefs + dir: QuickActionsPrefs + files: + - QASRootListController.m + - QASAppSelectorController.m + frameworks: + - MobileCoreServices + targetvers: 13.0 \ No newline at end of file diff --git a/QuickActions/Makefile b/QuickActions/Makefile deleted file mode 100644 index 0c2b480..0000000 --- a/QuickActions/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -THEOS_DEVICE_IP = localhost -THEOS_DEVICE_PORT = 2222 - -TARGET := iphone:clang:14.4:13.0 -INSTALL_TARGET_PROCESSES = SpringBoard - -ARCHS := arm64 arm64e - -include $(THEOS)/makefiles/common.mk - -TWEAK_NAME = QuickActions - -QuickActions_FILES = Tweak.x -QuickActions_CFLAGS = -fobjc-arc -QuickActions_PRIVATE_FRAMEWORKS = CoverSheet SpringBoardFoundation - -include $(THEOS_MAKE_PATH)/tweak.mk -SUBPROJECTS += QuickActionsPrefs -include $(THEOS_MAKE_PATH)/aggregate.mk diff --git a/QuickActions/QuickActionsPrefs/Makefile b/QuickActions/QuickActionsPrefs/Makefile deleted file mode 100644 index df9918b..0000000 --- a/QuickActions/QuickActionsPrefs/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -TARGET := iphone:clang:14.4:13.0 - -include $(THEOS)/makefiles/common.mk - -ARCHS := arm64 arm64e - -BUNDLE_NAME = QuickActionsPrefs - -QuickActionsPrefs_FILES = QASRootListController.m -QuickActionsPrefs_FRAMEWORKS = UIKit -QuickActionsPrefs_PRIVATE_FRAMEWORKS = Preferences -QuickActionsPrefs_EXTRA_FRAMEWORKS = AltList -QuickActionsPrefs_INSTALL_PATH = /Library/PreferenceBundles -QuickActionsPrefs_CFLAGS = -fobjc-arc - -include $(THEOS_MAKE_PATH)/bundle.mk diff --git a/QuickActions/QuickActionsPrefs/PSDetailController.h b/QuickActions/QuickActionsPrefs/PSDetailController.h new file mode 100644 index 0000000..571b091 --- /dev/null +++ b/QuickActions/QuickActionsPrefs/PSDetailController.h @@ -0,0 +1,30 @@ +#import + +@class PSEditingPane; + +@interface PSDetailController : PSViewController { + + PSEditingPane* _pane; + +} + +@property (assign,nonatomic) PSEditingPane * pane; +-(void)willAnimateRotationToInterfaceOrientation:(long long)arg1 duration:(double)arg2 ; +-(void)willRotateToInterfaceOrientation:(long long)arg1 duration:(double)arg2 ; +-(PSEditingPane *)pane; +-(void)didRotateFromInterfaceOrientation:(long long)arg1 ; +-(void)viewWillDisappear:(BOOL)arg1 ; +-(void)viewDidLayoutSubviews; +-(void)setPane:(PSEditingPane *)arg1 ; +-(CGRect)paneFrame; +-(void)loadPane; +-(void)dealloc; +-(id)title; +-(void)viewDidAppear:(BOOL)arg1 ; +-(void)loadView; +-(void)suspend; +-(void)viewDidUnload; +-(void)viewWillAppear:(BOOL)arg1 ; +-(void)saveChanges; +-(void)statusBarWillAnimateByHeight:(double)arg1 ; +@end diff --git a/QuickActions/QuickActionsPrefs/QASAppSelectorController.h b/QuickActions/QuickActionsPrefs/QASAppSelectorController.h new file mode 100644 index 0000000..13ffe60 --- /dev/null +++ b/QuickActions/QuickActionsPrefs/QASAppSelectorController.h @@ -0,0 +1,18 @@ +#import +#import "PSDetailController.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 +@property (nonatomic) UITableView *tableView; +@property (nonatomic) NSMutableArray *enabled; +@property (nonatomic) NSMutableArray *disabled; +@property (nonatomic) NSArray *systemAvailable; +@property (nonatomic) NSMutableArray *systemDisabled; +@property (nonatomic) NSString *key; +@property (nonatomic) NSString *defaults; +@end \ No newline at end of file diff --git a/QuickActions/QuickActionsPrefs/QASAppSelectorController.m b/QuickActions/QuickActionsPrefs/QASAppSelectorController.m new file mode 100644 index 0000000..cfb6c7a --- /dev/null +++ b/QuickActions/QuickActionsPrefs/QASAppSelectorController.m @@ -0,0 +1,310 @@ +#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 + +@implementation QASAppSelectorController +-(void)viewDidLoad +{ + [super viewDidLoad]; + + PSSpecifier *specifier = [self specifier]; + + self.defaults = [specifier propertyForKey:@"defaults"]; + self.key = [specifier propertyForKey:@"key"]; + + self.disabled = [NSMutableArray new]; + self.enabled = [NSMutableArray new]; + + NSArray *defaults = [[[NSUserDefaults alloc] initWithSuiteName:self.defaults] arrayForKey:self.key]; + + if (defaults == nil) { + if ([self.key isEqualToString:@"leftButtons"]) + [self.enabled addObject:@"com.apple.flashlight"]; + else if ([self.key isEqualToString:@"rightButtons"]) + [self.enabled addObject:@"com.apple.camera"]; + } else + [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 ([self.enabled indexOfObject:@"com.apple.flashlight"] == NSNotFound) + [self.disabled addObject:@"com.apple.flashlight"]; + + if ([self.enabled indexOfObject:@"com.apple.donotdisturb"] == NSNotFound) + [self.disabled addObject:@"com.apple.donotdisturb"]; + + [self.disabled sortApps]; +} + +-(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; + + [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 @""; +} + +-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +{ + return 2; +} + +-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + if (section == 0) + return self.enabled.count; + else + return self.disabled.count; +} + +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + NSString *bundleid = indexPath.section == 0 ? self.enabled[indexPath.row] : self.disabled[indexPath.row]; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"com.cameronkatri.quickactions"]; + + if (cell == nil) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"com.cameronkatri.quickactions"]; + + 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"]) { + 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]; + } else { + cell.textLabel.text = [[LSApplicationProxy applicationProxyForIdentifier:bundleid] localizedNameForContext:nil]; + if (cell.textLabel.text == nil) { + cell.textLabel.text = bundleid; + cell.detailTextLabel.text = nil; + } else { + cell.detailTextLabel.text = bundleid; + } + cell.detailTextLabel.textColor = [UIColor secondaryLabelColor]; + cell.imageView.image = [UIImage _applicationIconImageForBundleIdentifier:bundleid format:0 scale:[UIScreen mainScreen].scale]; + } + + cell.showsReorderControl = indexPath.section == 0 ? YES : FALSE; + + return cell; +} + +-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath +{ + return indexPath.section == 0 ? UITableViewCellEditingStyleDelete : UITableViewCellEditingStyleInsert; +} + +-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath +{ + return indexPath.section == 0 ? 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]; + } + + [self.disabled sortApps]; + [tableView reloadData]; + + [[[NSUserDefaults alloc] initWithSuiteName:self.defaults] setObject:self.enabled forKey:self.key]; +} + +-(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]; + } + 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; + + if (editingStyle == UITableViewCellEditingStyleDelete) { + [self.enabled removeObject:item]; + [self.disabled addObject:item]; + [self.disabled sortApps]; + + insertPath = [NSIndexPath indexPathForRow:[self.disabled indexOfObject:item] inSection:1]; + } else if (editingStyle == UITableViewCellEditingStyleInsert) { + [self.disabled removeObject:item]; + [self.enabled addObject:item]; + + insertPath = [NSIndexPath indexPathForRow:([self.enabled count] - 1) inSection:0]; + } + + [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; + } + }]; + + 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; + } + + 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 diff --git a/QuickActions/QuickActionsPrefs/Resources/Root.plist b/QuickActions/QuickActionsPrefs/Resources/Root.plist index 728dc93..1eb8853 100644 --- a/QuickActions/QuickActionsPrefs/Resources/Root.plist +++ b/QuickActions/QuickActionsPrefs/Resources/Root.plist @@ -7,76 +7,94 @@ cell PSGroupCell + label + Left cell PSLinkListCell - defaults - com.cameronkatri.quickactions label - Left Apps + Left Buttons detail - ATLApplicationListMultiSelectionController + QASAppSelectorController + defaults + com.cameronkatri.quickactions key leftButtons - cellClass - ATLApplicationSelectionCell - sections - - - sectionType - System - - - sectionType - User - - - useSearchBar - - hideSearchBarWhileScrolling - - showIdentifiersAsSubtitle + + + cell + PSEditTextCell + label + Offset X + key + LeftOffsetX + defaults + com.cameronkatri.quickactions + isDecimalPad - includeIdentifiersInSearch + placeholder + 0 + + + cell + PSEditTextCell + label + Offset Y + key + LeftOffsetY + defaults + com.cameronkatri.quickactions + isDecimalPad + placeholder + 0 cell PSGroupCell + label + Right cell PSLinkListCell - defaults - com.cameronkatri.quickactions label - Right Apps + Right Buttons detail - ATLApplicationListMultiSelectionController + QASAppSelectorController + defaults + com.cameronkatri.quickactions key rightButtons - cellClass - ATLApplicationSelectionCell - sections - - - sectionType - System - - - sectionType - User - - - useSearchBar - - hideSearchBarWhileScrolling - - showIdentifiersAsSubtitle + + + cell + PSEditTextCell + label + Offset X + key + RightOffsetX + defaults + com.cameronkatri.quickactions + isDecimalPad - includeIdentifiersInSearch + placeholder + 0 + + + cell + PSEditTextCell + label + Offset Y + key + RightOffsetY + defaults + com.cameronkatri.quickactions + isDecimalPad + placeholder + 0 cell diff --git a/QuickActions/Tweak.h b/QuickActions/Tweak.h index fe08749..41f64fd 100644 --- a/QuickActions/Tweak.h +++ b/QuickActions/Tweak.h @@ -47,18 +47,51 @@ -(void)setBackgroundEffectViewGroupName:(NSString *)arg1; -(id)initWithType:(long long)type; -(void)setImage:(UIImage *)arg1; +-(void)setSelectedImage:(UIImage *)arg1; -(void)setSelected:(BOOL)arg; +-(UIImage *)_imageWithName:(NSString *)arg1; -(UIImage *)image; -(UIImage *)selectedImage; -(void)setEdgeInsets:(UIEdgeInsets)arg; +-(void)setLatching:(BOOL)arg1; @property (nonatomic,retain) NSString * bundleID; @end +@interface CSAction : NSObject ++(id)actionWithType:(long long)arg1; +@end + +@interface CSQuickActionsViewController : UIViewController +-(void)_launchCamera; +-(void)_toggleFlashlight; +-(void)_resetIdleTimer; +-(void)sendAction:(id)arg1; +@end + + +@interface DNDModeAssertionService ++(DNDModeAssertionService *)serviceForClientIdentifier:(NSString *)arg; +-(void)takeModeAssertionWithDetails:(id)arg1 error:(id)error; +-(void)invalidateAllActiveModeAssertionsWithError:(id)error; +@end + +@interface DNDModeAssertionDetails ++(DNDModeAssertionDetails *)userRequestedAssertionDetailsWithIdentifier:(NSString *)arg1 modeIdentifier:(NSString *)arg2 lifetime:(id)arg3; +@end + +@interface DNDStateService ++(id)serviceForClientIdentifier:(id)arg1; +-(id)queryCurrentStateWithError:(id*)arg1; +-(void)addStateUpdateListener:(id)arg1 withCompletionHandler:(id /* block */)arg2; +@end + @interface CSQuickActionsView : UIView @property (nonatomic,retain) CSQuickActionsButton * flashlightButton; @property (nonatomic,retain) CSQuickActionsButton * cameraButton; @property (nonatomic,retain) NSObject * legibilitySettings; +@property (assign,nonatomic) CSQuickActionsViewController * delegate; +@property (nonatomic,retain) DNDStateService *stateService; -(id)_buttonGroupName; -(id)initWithFrame:(CGRect)arg1 delegate:(id)arg2; -(void)handleButtonTouchEnded:(id)button; @@ -66,7 +99,9 @@ -(void)handleButtonPress:(id)button; -(void)_addTargetsToButton:(id)arg1 ; -(UIEdgeInsets)_buttonOutsets; +@end +@interface CSQuickActionsView (QuickActions) @property (nonatomic,retain) NSMutableArray * leftButtons; @property (nonatomic,retain) NSMutableArray * rightButtons; @property (nonatomic) BOOL leftOpen; @@ -75,6 +110,10 @@ @property (nonatomic) BOOL collapseRight; -(CGRect)leftFrameForButton:(CSQuickActionsButton*)button; -(CGRect)rightFrameForButton:(CSQuickActionsButton*)button; +-(void)setDoNotDisturb:(BOOL)state; +-(BOOL)isDNDActive; +-(void)updateDND:(NSNotification *)notif; +-(void)stateService:(id)arg1 didRecieveDoNotDisturbStateUpdate:(id)arg2; @end @interface NSUserDefaults (Private) @@ -86,4 +125,4 @@ @property (nonatomic, readonly) CGRect _referenceBounds; @end -int SBFEffectiveHomeButtonType(); +int SBFEffectiveHomeButtonType(); \ No newline at end of file diff --git a/QuickActions/Tweak.x b/QuickActions/Tweak.x index f5f4e39..64b69eb 100644 --- a/QuickActions/Tweak.x +++ b/QuickActions/Tweak.x @@ -46,6 +46,7 @@ void openApplication(NSString *bundleID) %property (nonatomic) BOOL rightOpen; %property (nonatomic) BOOL collapseLeft; %property (nonatomic) BOOL collapseRight; +%property (nonatomic,retain) DNDStateService *stateService; -(id)initWithFrame:(CGRect)arg1 delegate:(id)arg2 { @@ -53,8 +54,12 @@ void openApplication(NSString *bundleID) NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:@"com.cameronkatri.quickactions"]; - NSArray *leftButtons = (NSArray*)[defaults objectForKey:@"leftButtons"]; - NSArray *rightButtons = (NSArray*)[defaults objectForKey:@"rightButtons"]; + NSArray *leftButtons = [defaults arrayForKey:@"leftButtons"]; + if (leftButtons == nil) + leftButtons = @[@"com.apple.flashlight"]; + NSArray *rightButtons = [defaults arrayForKey:@"rightButtons"]; + if (rightButtons == nil) + rightButtons = @[@"com.apple.camera"]; self.leftButtons = [[NSMutableArray alloc] init]; self.rightButtons = [[NSMutableArray alloc] init]; @@ -62,7 +67,9 @@ void openApplication(NSString *bundleID) self.collapseLeft = [leftButtons count] > 1 ? true : false; self.leftOpen = !self.collapseLeft; - if ([leftButtons count] == 1) { + if ([leftButtons count] == 0) { + [self.flashlightButton setHidden:1]; + } else if ([leftButtons count] == 1) { [self.flashlightButton setBundleID:leftButtons[0]]; } else if ([leftButtons count] > 1) { [self.flashlightButton setImage:nil]; @@ -83,7 +90,9 @@ void openApplication(NSString *bundleID) self.collapseRight = [rightButtons count] > 1 ? true : false; self.rightOpen = !self.collapseRight; - if ([rightButtons count] == 1) { + if ([rightButtons count] == 0) { + [self.cameraButton setHidden:1]; + } else if ([rightButtons count] == 1) { [self.cameraButton setBundleID:rightButtons[0]]; } else if ([rightButtons count] > 1) { [self.cameraButton setImage:nil]; @@ -101,6 +110,11 @@ void openApplication(NSString *bundleID) } } + // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateDND:) name:@"SBQuietModeStatusChangedNotification" object:nil]; + // [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateDND:) name:@"QuickActionsUpdateDND" object:nil]; + self.stateService = (DNDStateService *)[objc_getClass("DNDStateService") serviceForClientIdentifier:@"com.apple.donotdisturb.control-center.module"]; + [self.stateService addStateUpdateListener:self withCompletionHandler:nil]; + return o; } @@ -110,7 +124,7 @@ void openApplication(NSString *bundleID) CGRect cameraFrame = [[self cameraButton] frame]; if (self.rightOpen) { return CGRectMake(cameraFrame.origin.x, - cameraFrame.origin.y - ((cameraFrame.size.height * 3/4) * ((button.type + 1) / 2)), + cameraFrame.origin.y - ((cameraFrame.size.height * 3/4) * (button.type - 1)), cameraFrame.size.width, cameraFrame.size.height); } else { return cameraFrame; @@ -163,6 +177,18 @@ void openApplication(NSString *bundleID) buttonWidth, buttonHeight); } + NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:@"com.cameronkatri.quickactions"]; + + CGRect frame = self.flashlightButton.frame; + frame.origin.x += [defaults floatForKey:@"LeftOffsetX"]; + frame.origin.y -= [defaults floatForKey:@"LeftOffsetY"]; + self.flashlightButton.frame = frame; + + frame = self.cameraButton.frame; + frame.origin.x -= [defaults floatForKey:@"RightOffsetX"]; + frame.origin.y -= [defaults floatForKey:@"RightOffsetY"]; + self.cameraButton.frame = frame; + UIImageSymbolConfiguration *imageConfig = [UIImageSymbolConfiguration configurationWithTextStyle:UIFontTextStyleTitle1]; UIImage *image = [UIImage systemImageNamed:@"ellipsis" withConfiguration:imageConfig]; if ([self.leftButtons count] > 1) { @@ -177,11 +203,15 @@ void openApplication(NSString *bundleID) for (CSQuickActionsButton *button in [self leftButtons]) { [button setEdgeInsets:insets]; button.frame = [self leftFrameForButton:button]; + [button setHidden:!self.rightOpen]; } for (CSQuickActionsButton *button in [self rightButtons]) { [button setEdgeInsets:insets]; button.frame = [self rightFrameForButton:button]; + [button setHidden:!self.rightOpen]; } + + [self updateDND:nil]; } -(void)handleButtonPress:(CSQuickActionsButton *)button @@ -189,31 +219,54 @@ void openApplication(NSString *bundleID) [button setSelected:false]; if (button.type == 0 && self.collapseRight) { + self.rightOpen = !self.rightOpen; [UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^(void){ - for (CSQuickActionsButton *button in [self rightButtons]) { - button.frame = [self rightFrameForButton:button]; - } + for (CSQuickActionsButton *button in [self rightButtons]) { + button.frame = [self rightFrameForButton:button]; + if (self.rightOpen) + [button setHidden:0]; + } } - completion:NULL]; - self.rightOpen = !self.rightOpen; + completion:^(BOOL finished) { + for (CSQuickActionsButton *button in [self rightButtons]) + [button setHidden:!self.rightOpen]; + }]; } else if (button.type == 1 && self.collapseLeft) { + self.leftOpen = !self.leftOpen; [UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseOut - animations:^(void){ - for (CSQuickActionsButton *button in [self leftButtons]) { - button.frame = [self leftFrameForButton:button]; - } + animations:^(void) { + for (CSQuickActionsButton *button in [self leftButtons]) { + button.frame = [self leftFrameForButton:button]; + if (self.leftOpen) + [button setHidden:0]; + } } - completion:NULL]; - self.leftOpen = !self.leftOpen; - } else if (button.bundleID) { + completion:^(BOOL finished) { + for (CSQuickActionsButton *button in [self leftButtons]) + [button setHidden:!self.leftOpen]; + }]; + } else if ([button.bundleID isEqualToString:@"com.apple.flashlight"]) { + [self.delegate _toggleFlashlight]; + } else if ([button.bundleID isEqualToString:@"com.apple.camera"]) { + [self.delegate _launchCamera]; + } else if ([button.bundleID isEqualToString:@"com.apple.donotdisturb"]) { + [self setDoNotDisturb:!self.isDNDActive]; + } else if (button.bundleID) openApplication(button.bundleID); - } else + else { %orig; + return; + } + + /* This will make the CC module be correct */ + [self.delegate _resetIdleTimer]; + [self.delegate sendAction:[CSAction actionWithType:5]]; + return; } @@ -235,6 +288,68 @@ void openApplication(NSString *bundleID) %orig; } +-(void)setFlashlightOn:(BOOL)arg +{ + if ([self.flashlightButton.bundleID isEqualToString:@"com.apple.flashlight"]) + [self.flashlightButton setSelected:arg]; + if ([self.cameraButton.bundleID isEqualToString:@"com.apple.flashlight"]) + [self.cameraButton setSelected:arg]; + for (CSQuickActionsButton *button in [self leftButtons]) + if ([button.bundleID isEqualToString:@"com.apple.flashlight"]) + [button setSelected:arg]; + for (CSQuickActionsButton *button in [self rightButtons]) + if ([button.bundleID isEqualToString:@"com.apple.flashlight"]) + [button setSelected:arg]; +} + +%new +-(void)setDoNotDisturb:(BOOL)state +{ + DNDModeAssertionService *assertionService = (DNDModeAssertionService *)[objc_getClass("DNDModeAssertionService") serviceForClientIdentifier:@"com.apple.donotdisturb.control-center.module"]; + + if (state) { + DNDModeAssertionDetails *newAssertion = [objc_getClass("DNDModeAssertionDetails") userRequestedAssertionDetailsWithIdentifier:@"com.apple.control-center.manual-toggle" modeIdentifier:@"com.apple.donotdisturb.mode.default" lifetime:nil]; + [assertionService takeModeAssertionWithDetails:newAssertion error:NULL]; + } else { + [assertionService invalidateAllActiveModeAssertionsWithError:NULL]; + } + + [[NSNotificationCenter defaultCenter] postNotificationName:@"SBQuietModeStatusChangedNotification" object:nil]; +} + +%new +-(BOOL)isDNDActive +{ + + // DNDStateService *stateService = (DNDStateService *)[objc_getClass("DNDStateService") serviceForClientIdentifier:@"com.apple.donotdisturb.control-center.module"]; + return [[self.stateService queryCurrentStateWithError:nil] isActive]; +} + +%new +-(void)updateDND:(NSNotification *)notif +{ + BOOL active = [self isDNDActive]; + + if ([self.flashlightButton.bundleID isEqualToString:@"com.apple.donotdisturb"]) + [self.flashlightButton setSelected:active]; + if ([self.cameraButton.bundleID isEqualToString:@"com.apple.donotdisturb"]) + [self.cameraButton setSelected:active]; + for (CSQuickActionsButton *button in [self leftButtons]) + if ([button.bundleID isEqualToString:@"com.apple.donotdisturb"]) + [button setSelected:active]; + for (CSQuickActionsButton *button in [self rightButtons]) + if ([button.bundleID isEqualToString:@"com.apple.donotdisturb"]) + [button setSelected:active]; +} + +%new +-(void)stateService:(id)arg1 didReceiveDoNotDisturbStateUpdate:(id)arg2 +{ + dispatch_async(dispatch_get_main_queue(), ^{ + [self updateDND:nil]; + }); +} + %end %hook CSQuickActionsButton @@ -250,7 +365,28 @@ void openApplication(NSString *bundleID) -(void)setBundleID:(NSString*)bundleID { %orig; - [self setImage:[UIImage _applicationIconImageForBundleIdentifier:bundleID format:0 scale:[UIScreen mainScreen].scale]]; + if ([bundleID isEqualToString:@"com.apple.camera"]) { + [self setImage:[self _imageWithName:@"OrbCamera"]]; + [self setLatching:FALSE]; + } else if ([bundleID isEqualToString:@"com.apple.flashlight"]) { + [self setImage:[self _imageWithName:@"OrbFlashlightOff"]]; + [self setSelectedImage:[self _imageWithName:@"OrbFlashlightOff"]]; + [self setLatching:TRUE]; + } else if (([bundleID isEqualToString:@"com.apple.donotdisturb"])) { + UIImageSymbolConfiguration *imageConfig = [UIImageSymbolConfiguration configurationWithTextStyle:UIFontTextStyleTitle2]; + [self setImage:[UIImage systemImageNamed:@"moon.fill" withConfiguration:imageConfig]]; + [self setSelectedImage:[UIImage systemImageNamed:@"moon.fill" withConfiguration:imageConfig]]; + ((UIImageView *)[self valueForKey:@"_contentView"]).contentMode = UIViewContentModeScaleAspectFit; + [self setLatching:TRUE]; + } else { + [self setImage:[UIImage _applicationIconImageForBundleIdentifier:bundleID format:0 scale:[UIScreen mainScreen].scale]]; + [self setLatching:FALSE]; + } +} + +-(void)setPermitted:(BOOL)permitted +{ + %orig(YES); } %end @@ -274,4 +410,14 @@ void openApplication(NSString *bundleID) %end +// %hook DNDNotificationsService + +// -(void)stateService:(id)arg1 didReceiveDoNotDisturbStateUpdate:(id)arg2{ +// %orig; + +// [[NSNotificationCenter defaultCenter] postNotificationName:@"QuickActionsUpdateDND" object:nil]; +// } + +// %end + // vim: filetype=logos diff --git a/QuickActions/control b/QuickActions/control deleted file mode 100644 index 0ad7375..0000000 --- a/QuickActions/control +++ /dev/null @@ -1,9 +0,0 @@ -Package: com.cameronkatri.quickactions -Name: QuickActions -Version: 1.0.0 -Architecture: iphoneos-arm -Description: Quickly launch apps from the lockscreen -Maintainer: Cameron Katri -Author: Cameron Katri -Section: Tweaks -Depends: com.opa334.altlist, mobilesubstrate (>= 0.9.5000), preferenceloader -- cgit v1.2.3-56-ge451