]> git.cameronkatri.com Git - tweaks.git/commitdiff
I lost track of all the changes
authorCameron Katri <me@cameronkatri.com>
Mon, 27 Dec 2021 06:08:28 +0000 (01:08 -0500)
committerCameron Katri <me@cameronkatri.com>
Mon, 27 Dec 2021 06:08:28 +0000 (01:08 -0500)
.gitignore
QuickActions/DragonMake [new file with mode: 0644]
QuickActions/Makefile [deleted file]
QuickActions/QuickActionsPrefs/Makefile [deleted file]
QuickActions/QuickActionsPrefs/PSDetailController.h [new file with mode: 0644]
QuickActions/QuickActionsPrefs/QASAppSelectorController.h [new file with mode: 0644]
QuickActions/QuickActionsPrefs/QASAppSelectorController.m [new file with mode: 0644]
QuickActions/QuickActionsPrefs/Resources/Root.plist
QuickActions/Tweak.h
QuickActions/Tweak.x
QuickActions/control [deleted file]

index 18796dcdaa1f902b369544d80be34e57e56c1d19..c5d1f0e656058fc14f66205c92c3b808a615481a 100644 (file)
@@ -1,3 +1,7 @@
 .theos
 packages
 .DS_Store
+.cache
+.vscode
+compile_commands.json
+.dragon
diff --git a/QuickActions/DragonMake b/QuickActions/DragonMake
new file mode 100644 (file)
index 0000000..f75e655
--- /dev/null
@@ -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 <me@cameronkatri.com>
+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 (file)
index 0c2b480..0000000
+++ /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 (file)
index df9918b..0000000
+++ /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 (file)
index 0000000..571b091
--- /dev/null
@@ -0,0 +1,30 @@
+#import <Preferences/PSViewController.h>
+
+@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 (file)
index 0000000..13ffe60
--- /dev/null
@@ -0,0 +1,18 @@
+#import <UIKit/UIKit.h>
+#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<UITableViewDataSource,
+UITableViewDelegate>
+@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 (file)
index 0000000..cfb6c7a
--- /dev/null
@@ -0,0 +1,310 @@
+#import <Foundation/Foundation.h>
+#include <objc/NSObject.h>
+#import <UIKit/UIKit.h>
+#import <Preferences/PSSpecifier.h>
+#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<LSApplicationProxy *> *)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
index 728dc93306f17db7244558fbfb6a662dd0217cbd..1eb885362a6211f2f98a30531a6f3b95ac225cd3 100644 (file)
@@ -7,76 +7,94 @@
                <dict>
                        <key>cell</key>
                        <string>PSGroupCell</string>
+                       <key>label</key>
+                       <string>Left</string>
                </dict>
                <dict>
                        <key>cell</key>
                        <string>PSLinkListCell</string>
-                       <key>defaults</key>
-                       <string>com.cameronkatri.quickactions</string>
                        <key>label</key>
-                       <string>Left Apps</string>
+                       <string>Left Buttons</string>
                        <key>detail</key>
-                       <string>ATLApplicationListMultiSelectionController</string>
+                       <string>QASAppSelectorController</string>
+                       <key>defaults</key>
+                       <string>com.cameronkatri.quickactions</string>
                        <key>key</key>
                        <string>leftButtons</string>
-                       <key>cellClass</key>
-                       <string>ATLApplicationSelectionCell</string>
-                       <key>sections</key>
-                       <array>
-                               <dict>
-                                       <key>sectionType</key>
-                                       <string>System</string>
-                               </dict>
-                               <dict>
-                                       <key>sectionType</key>
-                                       <string>User</string>
-                               </dict>
-                       </array>
-                       <key>useSearchBar</key>
-                       <true/>
-                       <key>hideSearchBarWhileScrolling</key>
-                       <false/>
-                       <key>showIdentifiersAsSubtitle</key>
+               </dict>
+               <dict>
+                       <key>cell</key>
+                       <string>PSEditTextCell</string>
+                       <key>label</key>
+                       <string>Offset X</string>
+                       <key>key</key>
+                       <string>LeftOffsetX</string>
+                       <key>defaults</key>
+                       <string>com.cameronkatri.quickactions</string>
+                       <key>isDecimalPad</key>
                        <true/>
-                       <key>includeIdentifiersInSearch</key>
+                       <key>placeholder</key>
+                       <string>0</string>
+               </dict>
+               <dict>
+                       <key>cell</key>
+                       <string>PSEditTextCell</string>
+                       <key>label</key>
+                       <string>Offset Y</string>
+                       <key>key</key>
+                       <string>LeftOffsetY</string>
+                       <key>defaults</key>
+                       <string>com.cameronkatri.quickactions</string>
+                       <key>isDecimalPad</key>
                        <true/>
+                       <key>placeholder</key>
+                       <string>0</string>
                </dict>
                <dict>
                        <key>cell</key>
                        <string>PSGroupCell</string>
+                       <key>label</key>
+                       <string>Right</string>
                </dict>
                <dict>
                        <key>cell</key>
                        <string>PSLinkListCell</string>
-                       <key>defaults</key>
-                       <string>com.cameronkatri.quickactions</string>
                        <key>label</key>
-                       <string>Right Apps</string>
+                       <string>Right Buttons</string>
                        <key>detail</key>
-                       <string>ATLApplicationListMultiSelectionController</string>
+                       <string>QASAppSelectorController</string>
+                       <key>defaults</key>
+                       <string>com.cameronkatri.quickactions</string>
                        <key>key</key>
                        <string>rightButtons</string>
-                       <key>cellClass</key>
-                       <string>ATLApplicationSelectionCell</string>
-                       <key>sections</key>
-                       <array>
-                               <dict>
-                                       <key>sectionType</key>
-                                       <string>System</string>
-                               </dict>
-                               <dict>
-                                       <key>sectionType</key>
-                                       <string>User</string>
-                               </dict>
-                       </array>
-                       <key>useSearchBar</key>
-                       <true/>
-                       <key>hideSearchBarWhileScrolling</key>
-                       <false/>
-                       <key>showIdentifiersAsSubtitle</key>
+               </dict>
+               <dict>
+                       <key>cell</key>
+                       <string>PSEditTextCell</string>
+                       <key>label</key>
+                       <string>Offset X</string>
+                       <key>key</key>
+                       <string>RightOffsetX</string>
+                       <key>defaults</key>
+                       <string>com.cameronkatri.quickactions</string>
+                       <key>isDecimalPad</key>
                        <true/>
-                       <key>includeIdentifiersInSearch</key>
+                       <key>placeholder</key>
+                       <string>0</string>
+               </dict>
+               <dict>
+                       <key>cell</key>
+                       <string>PSEditTextCell</string>
+                       <key>label</key>
+                       <string>Offset Y</string>
+                       <key>key</key>
+                       <string>RightOffsetY</string>
+                       <key>defaults</key>
+                       <string>com.cameronkatri.quickactions</string>
+                       <key>isDecimalPad</key>
                        <true/>
+                       <key>placeholder</key>
+                       <string>0</string>
                </dict>
                <dict>
                        <key>cell</key>
index fe087490122c4983a7ee1b4817cc0893a4b1dc7f..41f64fdccd7776b114c09474ffb03cc32598068c 100644 (file)
 -(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<CSQuickActionsButton*> * leftButtons;
 @property (nonatomic,retain) NSMutableArray<CSQuickActionsButton*> * rightButtons;
 @property (nonatomic) BOOL leftOpen;
 @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)
 @property (nonatomic, readonly) CGRect _referenceBounds;
 @end
 
-int SBFEffectiveHomeButtonType();
+int SBFEffectiveHomeButtonType();
\ No newline at end of file
index f5f4e39603103c2acb3415c43ad1c15550b6c2d3..64b69ebe2e95732a3ed73d669950b27f5f54310b 100644 (file)
@@ -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 (file)
index 0ad7375..0000000
+++ /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 <me@cameronkatri.com>
-Author: Cameron Katri <me@cameronkatri.com>
-Section: Tweaks
-Depends: com.opa334.altlist, mobilesubstrate (>= 0.9.5000), preferenceloader