From a2e2d87eb7352a9aaecea33da6aa27e55af4e38d Mon Sep 17 00:00:00 2001 From: Cameron Katri Date: Fri, 24 Dec 2021 09:20:23 -0500 Subject: QuickActions: Massive improvements Relicense everything as AGPLv3 --- QuickActions/Makefile | 1 + .../QuickActionsPrefs/QASRootListController.h | 16 ++ .../QuickActionsPrefs/QASRootListController.m | 35 +++ .../QuickActionsPrefs/Resources/Root.plist | 50 ++-- QuickActions/Tweak.h | 33 ++- QuickActions/Tweak.x | 256 ++++++++++++++++----- QuickActions/control | 2 +- 7 files changed, 300 insertions(+), 93 deletions(-) (limited to 'QuickActions') diff --git a/QuickActions/Makefile b/QuickActions/Makefile index bec96ec..0c2b480 100644 --- a/QuickActions/Makefile +++ b/QuickActions/Makefile @@ -12,6 +12,7 @@ TWEAK_NAME = QuickActions QuickActions_FILES = Tweak.x QuickActions_CFLAGS = -fobjc-arc +QuickActions_PRIVATE_FRAMEWORKS = CoverSheet SpringBoardFoundation include $(THEOS_MAKE_PATH)/tweak.mk SUBPROJECTS += QuickActionsPrefs diff --git a/QuickActions/QuickActionsPrefs/QASRootListController.h b/QuickActions/QuickActionsPrefs/QASRootListController.h index 6b45016..4ab9029 100644 --- a/QuickActions/QuickActionsPrefs/QASRootListController.h +++ b/QuickActions/QuickActionsPrefs/QASRootListController.h @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2021 Cameron Katri + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ #import @interface QASRootListController : PSListController diff --git a/QuickActions/QuickActionsPrefs/QASRootListController.m b/QuickActions/QuickActionsPrefs/QASRootListController.m index e781ab6..2fe7cb2 100644 --- a/QuickActions/QuickActionsPrefs/QASRootListController.m +++ b/QuickActions/QuickActionsPrefs/QASRootListController.m @@ -1,5 +1,22 @@ +/* + * Copyright (C) 2021 Cameron Katri + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ #import #import "QASRootListController.h" +#include @implementation QASRootListController @@ -12,9 +29,27 @@ return _specifiers; } +-(void)viewDidLoad +{ + [super viewDidLoad]; + UIBarButtonItem *respringButton = [[UIBarButtonItem alloc] initWithTitle:@"Respring" + style:UIBarButtonItemStylePlain + target:self + action:@selector(respring)]; + respringButton.tintColor = [UIColor systemRedColor]; + [self.navigationItem setRightBarButtonItem:respringButton]; +} + -(void)openSource { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://git.cameronkatri.com/tweaks/tree/QuickActions"] options:@{} completionHandler:nil]; } +-(void)respring +{ + pid_t pid; + const char *args[] = {"sbreload", NULL, NULL, NULL}; + posix_spawn(&pid, "usr/bin/sbreload", NULL, NULL, (char *const *)args, NULL); +} + @end diff --git a/QuickActions/QuickActionsPrefs/Resources/Root.plist b/QuickActions/QuickActionsPrefs/Resources/Root.plist index 5b0c436..728dc93 100644 --- a/QuickActions/QuickActionsPrefs/Resources/Root.plist +++ b/QuickActions/QuickActionsPrefs/Resources/Root.plist @@ -7,22 +7,6 @@ cell PSGroupCell - label - QuickActions - - - cell - PSSwitchCell - defaults - com.cameronkatri.quickactions - key - leftOn - label - Custom Left Button - default - - PostNotification - com.cameronkatri.quickactions/ReloadPrefs cell @@ -30,11 +14,11 @@ defaults com.cameronkatri.quickactions label - Left App + Left Apps detail - ATLApplicationListSelectionController + ATLApplicationListMultiSelectionController key - leftApp + leftButtons cellClass ATLApplicationSelectionCell sections @@ -56,22 +40,10 @@ includeIdentifiersInSearch - PostNotification - com.cameronkatri.quickactions/ReloadPrefs cell - PSSwitchCell - defaults - com.cameronkatri.quickactions - key - rightOn - label - Custom Right Button - default - - PostNotification - com.cameronkatri.quickactions/ReloadPrefs + PSGroupCell cell @@ -79,11 +51,11 @@ defaults com.cameronkatri.quickactions label - Right App + Right Apps detail - ATLApplicationListSelectionController + ATLApplicationListMultiSelectionController key - rightApp + rightButtons cellClass ATLApplicationSelectionCell sections @@ -105,8 +77,12 @@ includeIdentifiersInSearch - PostNotification - com.cameronkatri.quickactions/ReloadPrefs + + + cell + PSGroupCell + label + Links cell diff --git a/QuickActions/Tweak.h b/QuickActions/Tweak.h index f2855db..fe08749 100644 --- a/QuickActions/Tweak.h +++ b/QuickActions/Tweak.h @@ -1,3 +1,4 @@ +#import #import @interface UIImage (Private) @@ -36,27 +37,53 @@ @interface CSQuickActionsButton : UIView { UIImageView* _contentView; + id _legibilitySettings; } @property (assign,nonatomic) long long type; +@property (nonatomic,retain) id legibilitySettings; +@property (nonatomic,copy) NSString * backgroundEffectViewGroupName; +@property (assign,nonatomic) BOOL permitted; +-(id)legibilitySettings; +-(void)setBackgroundEffectViewGroupName:(NSString *)arg1; -(id)initWithType:(long long)type; -(void)setImage:(UIImage *)arg1; -(void)setSelected:(BOOL)arg; -(UIImage *)image; -(UIImage *)selectedImage; +-(void)setEdgeInsets:(UIEdgeInsets)arg; -@property (nonatomic,retain) UIImage *originalImage; --(void)loadImage; +@property (nonatomic,retain) NSString * bundleID; @end -@interface CSQuickActionsView : NSObject +@interface CSQuickActionsView : UIView @property (nonatomic,retain) CSQuickActionsButton * flashlightButton; @property (nonatomic,retain) CSQuickActionsButton * cameraButton; +@property (nonatomic,retain) NSObject * legibilitySettings; +-(id)_buttonGroupName; +-(id)initWithFrame:(CGRect)arg1 delegate:(id)arg2; -(void)handleButtonTouchEnded:(id)button; -(void)handleButtonTouchBegan:(id)button; -(void)handleButtonPress:(id)button; +-(void)_addTargetsToButton:(id)arg1 ; +-(UIEdgeInsets)_buttonOutsets; + +@property (nonatomic,retain) NSMutableArray * leftButtons; +@property (nonatomic,retain) NSMutableArray * rightButtons; +@property (nonatomic) BOOL leftOpen; +@property (nonatomic) BOOL rightOpen; +@property (nonatomic) BOOL collapseLeft; +@property (nonatomic) BOOL collapseRight; +-(CGRect)leftFrameForButton:(CSQuickActionsButton*)button; +-(CGRect)rightFrameForButton:(CSQuickActionsButton*)button; @end @interface NSUserDefaults (Private) -(id)objectForKey:(NSString *)key inDomain:(NSString *)domain; -(void)setObject:(id)value forKey:(NSString *)key inDomain:(NSString *)domain; @end + +@interface UIScreen (Private) +@property (nonatomic, readonly) CGRect _referenceBounds; +@end + +int SBFEffectiveHomeButtonType(); diff --git a/QuickActions/Tweak.x b/QuickActions/Tweak.x index 61d6a65..d5c21f5 100644 --- a/QuickActions/Tweak.x +++ b/QuickActions/Tweak.x @@ -1,12 +1,25 @@ +/* + * Copyright (C) 2021 Cameron Katri + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ #import +#import +#import #import "Tweak.h" -static bool leftOn; -static NSString *leftApp; -static bool rightOn; -static NSString *rightApp; - void openApplication(NSString *bundleID) { FBSOpenApplicationOptions* opts = [%c(FBSOpenApplicationOptions) optionsWithDictionary:@{ @@ -27,51 +40,197 @@ void openApplication(NSString *bundleID) %hook CSQuickActionsView +%property (nonatomic, retain) NSMutableArray * leftButtons; +%property (nonatomic, retain) NSMutableArray * rightButtons; +%property (nonatomic) BOOL leftOpen; +%property (nonatomic) BOOL rightOpen; +%property (nonatomic) BOOL collapseLeft; +%property (nonatomic) BOOL collapseRight; + +-(id)initWithFrame:(CGRect)arg1 delegate:(id)arg2 +{ + id o = %orig; + + NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:@"com.cameronkatri.quickactions"]; + + NSArray *leftButtons = (NSArray*)[defaults objectForKey:@"leftButtons"]; + NSArray *rightButtons = (NSArray*)[defaults objectForKey:@"rightButtons"]; + + + self.leftButtons = [[NSMutableArray alloc] init]; + self.rightButtons = [[NSMutableArray alloc] init]; + + self.collapseLeft = [leftButtons count] > 1 ? true : false; + self.leftOpen = !self.collapseLeft; + + if ([leftButtons count] == 1) { + [self.flashlightButton setBundleID:leftButtons[0]]; + } else if ([leftButtons count] > 1) { + [self.flashlightButton setImage:nil]; + for (int i = 0; i < [leftButtons count]; i++) { + CSQuickActionsButton *button = [[CSQuickActionsButton alloc] initWithType:(i + 2)]; + [button setBundleID:leftButtons[i]]; + + [button setBackgroundEffectViewGroupName:[self _buttonGroupName]]; + [button setLegibilitySettings:[self legibilitySettings]]; + [button setPermitted:1]; + + [self insertSubview:button belowSubview:self.flashlightButton]; + [self _addTargetsToButton:button]; + [self.leftButtons addObject:button]; + } + } + + self.collapseRight = [rightButtons count] > 1 ? true : false; + self.rightOpen = !self.collapseRight; + + if ([rightButtons count] == 1) { + [self.cameraButton setBundleID:rightButtons[0]]; + } else if ([rightButtons count] > 1) { + [self.cameraButton setImage:nil]; + for (int i = 0; i < [rightButtons count]; i++) { + CSQuickActionsButton *button = [[CSQuickActionsButton alloc] initWithType:(i + 2)]; + [button setBundleID:rightButtons[i]]; + + [button setBackgroundEffectViewGroupName:[self _buttonGroupName]]; + [button setLegibilitySettings:[self legibilitySettings]]; + [button setPermitted:1]; + + [self insertSubview:button belowSubview:self.cameraButton]; + [self _addTargetsToButton:button]; + [self.rightButtons addObject:button]; + } + } + + return o; +} + +%new +-(CGRect)rightFrameForButton:(CSQuickActionsButton*)button +{ + 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.size.width, cameraFrame.size.height); + } else { + return cameraFrame; + } +} + +%new +-(CGRect)leftFrameForButton:(CSQuickActionsButton*)button +{ + CGRect flashlightFrame = [[self flashlightButton] frame]; + if (self.leftOpen) { + return CGRectMake(flashlightFrame.origin.x, + flashlightFrame.origin.y - ((flashlightFrame.size.height * 3/4) * (button.type - 1)), + flashlightFrame.size.width, flashlightFrame.size.height); + } else { + return flashlightFrame; + } +} + +-(void)setLegibilitySettings:(id)legibilitySettings +{ + %orig; + for (CSQuickActionsButton *button in [self leftButtons]) + [button setLegibilitySettings:legibilitySettings]; + for (CSQuickActionsButton *button in [self rightButtons]) + [button setLegibilitySettings:legibilitySettings]; +} + +-(void)_layoutQuickActionButtons +{ + %orig; + + UIEdgeInsets insets = [self _buttonOutsets]; + if (SBFEffectiveHomeButtonType() != 2) { + CGRect bounds = [[UIScreen mainScreen] _referenceBounds]; + + CGFloat buttonWidth = 50 + insets.right + insets.left; + CGFloat buttonHeight = 50 + insets.top + insets.bottom; + + [[self flashlightButton] setEdgeInsets:insets]; + + self.flashlightButton.frame = CGRectMake(insets.left, + bounds.size.height - buttonHeight - insets.bottom, + buttonWidth, buttonHeight); + + [[self cameraButton] setEdgeInsets:insets]; + + self.cameraButton.frame = CGRectMake(bounds.size.width - insets.left - buttonWidth, + bounds.size.height - buttonHeight - insets.bottom, + buttonWidth, buttonHeight); + + } + + for (CSQuickActionsButton *button in [self leftButtons]) { + [button setEdgeInsets:insets]; + button.frame = [self leftFrameForButton:button]; + } + for (CSQuickActionsButton *button in [self rightButtons]) { + [button setEdgeInsets:insets]; + button.frame = [self rightFrameForButton:button]; + } +} + -(void)handleButtonPress:(CSQuickActionsButton *)button { [button setSelected:false]; - if (leftOn && button.type == 1) - openApplication(leftApp); - else if (rightOn && button.type == 0) - openApplication(rightApp); - else + + if (button.type == 0 && self.collapseRight) { + [UIView animateWithDuration:0.25 + delay:0 + options:UIViewAnimationOptionCurveEaseOut + animations:^(void){ + for (CSQuickActionsButton *button in [self rightButtons]) { + button.frame = [self rightFrameForButton:button]; + } + } + completion:NULL]; + self.rightOpen = !self.rightOpen; + } else if (button.type == 1 && self.collapseLeft) { + [UIView animateWithDuration:0.25 + delay:0 + options:UIViewAnimationOptionCurveEaseOut + animations:^(void){ + for (CSQuickActionsButton *button in [self leftButtons]) { + button.frame = [self leftFrameForButton:button]; + } + } + completion:NULL]; + self.leftOpen = !self.leftOpen; + } else if (button.bundleID) { + openApplication(button.bundleID); + } else %orig; return; } -(void)handleButtonTouchBegan:(CSQuickActionsButton *)button { - if ((leftOn && button.type == 1) || - (rightOn && button.type == 0)) + if (button.bundleID != nil || + (button.type == 0 && self.collapseRight) || + (button.type == 1 && self.collapseLeft)) return; - else - %orig; + %orig; } -(void)handleButtonTouchEnded:(CSQuickActionsButton *)button { - if ((leftOn && button.type == 1) || - (rightOn && button.type == 0)) + if (button.bundleID != nil || + (button.type == 0 && self.collapseRight) || + (button.type == 1 && self.collapseLeft)) return; - else - %orig; + %orig; } %end %hook CSQuickActionsButton -%property (nonatomic, retain) UIImage *originalImage; - --(id)initWithType:(long long)type -{ - id o = %orig; - if (!self.originalImage) - self.originalImage = [self image]; - [self loadImage]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loadImage) name:@"com.cameronkatri.quickactions/ReloadImages" object:nil]; - return o; -} +%property (nonatomic, retain) NSString *bundleID; -(void)setImage:(UIImage *)img { @@ -79,38 +238,31 @@ void openApplication(NSString *bundleID) [[self valueForKey:@"_contentView"] setImage:img]; } -%new --(void)loadImage +-(void)setBundleID:(NSString*)bundleID { - if (self.type == 1 && leftOn) - [self setImage:[UIImage _applicationIconImageForBundleIdentifier:leftApp format:0 scale:[UIScreen mainScreen].scale]]; - else if (self.type == 0 && rightOn) - [self setImage:[UIImage _applicationIconImageForBundleIdentifier:rightApp format:0 scale:[UIScreen mainScreen].scale]]; - else - [self setImage:self.originalImage]; + %orig; + [self setImage:[UIImage _applicationIconImageForBundleIdentifier:bundleID format:0 scale:[UIScreen mainScreen].scale]]; } %end -static void updatePrefs(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userinfo) +%hook CSQuickActionsViewController + +-(BOOL)hasCamera { - NSNumber *leftOnValue = (NSNumber *)[[NSUserDefaults standardUserDefaults] objectForKey:@"leftOn" inDomain:@"com.cameronkatri.quickactions"]; - NSNumber *rightOnValue = (NSNumber *)[[NSUserDefaults standardUserDefaults] objectForKey:@"rightOn" inDomain:@"com.cameronkatri.quickactions"]; - leftApp = (NSString *)[[NSUserDefaults standardUserDefaults] objectForKey:@"leftApp" inDomain:@"com.cameronkatri.quickactions"]; - rightApp = (NSString *)[[NSUserDefaults standardUserDefaults] objectForKey:@"rightApp" inDomain:@"com.cameronkatri.quickactions"]; - leftOn = leftOnValue ? [leftOnValue boolValue] : false; - rightOn = leftOnValue ? [rightOnValue boolValue] : false; - if ([leftApp isEqual:@""] || [leftApp length] == 0) - leftOn = false; - if ([rightApp isEqual:@""] || [rightApp length] == 0) - rightOn = false; - [[NSNotificationCenter defaultCenter] postNotificationName:@"com.cameronkatri.quickactions/ReloadImages" object:nil]; + return true; } -%ctor +-(BOOL)hasFlashlight { - updatePrefs(NULL, NULL, NULL, NULL, NULL); - CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, updatePrefs, (CFStringRef)@"com.cameronkatri.quickactions/ReloadPrefs", NULL, CFNotificationSuspensionBehaviorCoalesce); + return true; } ++(BOOL)deviceSupportsButtons +{ + return true; +} + +%end + // vim: filetype=logos diff --git a/QuickActions/control b/QuickActions/control index a721377..0ad7375 100644 --- a/QuickActions/control +++ b/QuickActions/control @@ -6,4 +6,4 @@ Description: Quickly launch apps from the lockscreen Maintainer: Cameron Katri Author: Cameron Katri Section: Tweaks -Depends: com.opa334.altlist, mobilesubstrate (>= 0.9.5000) +Depends: com.opa334.altlist, mobilesubstrate (>= 0.9.5000), preferenceloader -- cgit v1.2.3-56-ge451