Skip to content

Commit 1f6adf8

Browse files
committed
[+][f] added the functionality of the xmark button, fixed the error with the springboard crash when closing applications
1 parent ab8dde0 commit 1f6adf8

File tree

7 files changed

+93
-37
lines changed

7 files changed

+93
-37
lines changed

Extensions/Extensions.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
#import <UIKit/UIKit.h>
33
#import <CoreText/CoreText.h>
44
#import <rootless.h>
5-
#include <RemoteLog.h>
65

76
#define WITCHER_PLIST_SETTINGS ROOT_PATH_NS(@"/var/mobile/Library/Preferences/dr.erast.witcherprefs.plist")
87
#define WITCHER_PREFERENCES_BUNDLE_PATH ROOT_PATH_NS(@"/Library/PreferenceBundles/WitcherPreferences.bundle")

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ https://github.com/MatoiDev/Witcher/assets/78802792/9b2195ae-b183-4e2c-b4de-7560
1111
- [X] Make Logo
1212
- [X] Preferences integration
1313
- [X] Add support to hardware-button devices
14-
- [ ] Add options to preferences
14+
- [X] Add options to preferences
15+
- [X] Add xmark button functional
1516
- [ ] Add support to iOS 16+
16-
- [ ] Add xmark button functional
1717

1818

1919
### For testers

UI/Router/RouterView.m

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ -(void)setupStaticCell {
9393
-(void)setupQuickActionButtons {
9494

9595
closeAppButton = [[UIButton alloc] init];
96-
[closeAppButton setEnabled:NO];
9796
[closeAppButton addTarget:self action:@selector(closeApp) forControlEvents:UIControlEventTouchUpInside];
9897
[closeAppButton setImage:[UIImage systemImageNamed:@"xmark"] forState:UIControlStateNormal];
9998

@@ -156,6 +155,7 @@ -(void)updateCellsWithNewApplications:(NSArray<WitcherApplicationLayoutStruct *>
156155
}
157156

158157
[goToPreviousAppButton setEnabled:[layoutStructs count] > 0];
158+
[closeAppButton setEnabled:[layoutStructs count] + flag > 0];
159159

160160
[self updateStaticCellPosition];
161161

@@ -394,7 +394,6 @@ -(void)updateActionButtonsWithState:(_Bool)state {
394394
[searchButton setHidden:state];
395395
[closeAppButton setHidden:state];
396396

397-
[searchButton setUserInteractionEnabled:NO];
398397

399398
actionButtonsIsActive = !state;
400399
}

Witcher.x

Lines changed: 60 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
#import "Witcher.h"
22

33

4-
/* TODO
5-
- (Not implemented) Kill aplications with quick action button: https://www.reddit.com/r/jailbreakdevelopers/comments/d6wbla/remove_app_from_app_switcher/
6-
*/
7-
84
#pragma mark - Views
95
RouterView *router = nil;
106
WitcherApplicationLayoutContainer *container = nil;
@@ -17,6 +13,7 @@ SBMainSwitcherViewController *mainAppSwitcherVC;
1713

1814
#pragma mark - Generators
1915
UIImpactFeedbackGenerator *impactFeedbackGenerator = nil;
16+
UIImpactFeedbackGenerator *heavyImpactFeedbackGenerator = nil;
2017

2118
#pragma mark - Data
2219
NSMutableDictionary<NSString *, WitcherApplicationLayoutStruct *> *mutableReusableContainersData = nil;
@@ -35,6 +32,7 @@ NSUserDefaults *prefs;
3532

3633
_Bool isEnabled;
3734
_Bool hardwareButtonMode;
35+
_Bool killNowPlayingApplication;
3836

3937
static UIColor* colorFromHex(NSString *hexString, BOOL useAlpha);
4038
static void updateSettings();
@@ -68,12 +66,33 @@ static void updateSettings();
6866
}
6967
else if ([[notification name] isEqualToString: @"ReleaseFrontMostApplication"]) {
7068
SBApplication *frontApp = [(SpringBoard*)[UIApplication sharedApplication] _accessibilityFrontMostApplication];
71-
if (!frontApp) {
72-
NSArray<SBAppLayout *> *recentAppLayouts = [self performSelector:@selector(getApps)];
73-
for (SBAppLayout *appLayout in recentAppLayouts) {
74-
[self performSelector:@selector(removeAppLayout:) withObject:appLayout];
75-
}
69+
70+
if (!heavyImpactFeedbackGenerator) {
71+
heavyImpactFeedbackGenerator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleHeavy];
72+
[heavyImpactFeedbackGenerator prepare];
7673
}
74+
75+
[heavyImpactFeedbackGenerator impactOccurred];
76+
77+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.35 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
78+
[UIView animateWithDuration:0.5
79+
delay:0
80+
usingSpringWithDamping:0.7
81+
initialSpringVelocity:0.2
82+
options:UIViewAnimationOptionCurveEaseInOut
83+
animations:^{
84+
if (!frontApp) {
85+
NSArray<SBAppLayout *> *recentAppLayouts = [self performSelector:@selector(getApps)];
86+
for (SBAppLayout *appLayout in recentAppLayouts) {
87+
[self performSelector:@selector(removeAppLayout:) withObject:appLayout];
88+
}
89+
} else {
90+
[self performSelector:@selector(removeFrontMostApplication:) withObject:frontApp];
91+
}
92+
}
93+
completion:nil];
94+
});
95+
7796
}
7897
else if ([[notification name] isEqualToString: @"OpenRecentApplication"]) {
7998
SBApplication *frontApp = [(SpringBoard*)[UIApplication sharedApplication] _accessibilityFrontMostApplication];
@@ -114,15 +133,17 @@ static void updateSettings();
114133
}
115134

116135
-(void)_deleteAppLayoutsMatchingBundleIdentifier:(id)arg1 {
117-
118-
%orig;
119136
if (!mutableReusableContainersData) { mutableReusableContainersData = [[NSMutableDictionary<NSString *, WitcherApplicationLayoutStruct *> alloc] init]; }
120137
[mutableReusableContainersData removeObjectForKey:arg1];
121-
if (sbfTouchPassThroughTransitionView) {
122-
SBApplication *frontApp = [(SpringBoard*)[UIApplication sharedApplication] _accessibilityFrontMostApplication];
123-
[sbfTouchPassThroughTransitionView performSelector:@selector(updateRouterWithFrontMostApplications:) withObject:frontApp];
124-
}
125-
RLog(@"%@ removed from dictionary", arg1);
138+
139+
// CAUSE OF CRASH
140+
// ----------------------------------------------------------------------------------------------------------------
141+
// if (sbfTouchPassThroughTransitionView) {
142+
// SBApplication *frontApp = [(SpringBoard*)[UIApplication sharedApplication] _accessibilityFrontMostApplication];
143+
// [sbfTouchPassThroughTransitionView performSelector:@selector(updateRouterWithFrontMostApplications:) withObject:frontApp];
144+
// }
145+
// ----------------------------------------------------------------------------------------------------------------
146+
%orig;
126147
}
127148

128149
%new
@@ -134,11 +155,10 @@ static void updateSettings();
134155
-(void)logBundles {
135156
NSArray<SBAppLayout *> *layouts = [self performSelector:@selector(getApps)];
136157
appLayouts = layouts;
137-
int counter = 1;
158+
__unused int counter = 1;
138159
for (SBAppLayout *appLayout in layouts) {
139160
NSString *bundleId = [self performSelector:@selector(getBundleIDFromAppLayout:) withObject:appLayout];
140161
if (bundleId) {
141-
RLog(@"%d) %@", counter, bundleId);
142162
counter += 1;
143163
}
144164
}
@@ -151,17 +171,30 @@ static void updateSettings();
151171
if (itemBundleID) {
152172
NSString *nowPlayingID = [[[%c(SBMediaController) sharedInstance] nowPlayingApplication] bundleIdentifier];
153173

154-
if (![itemBundleID isEqualToString: nowPlayingID]) {
155-
if (@available(iOS 14.0, *)) {
156-
[self _deleteAppLayoutsMatchingBundleIdentifier:itemBundleID];
157-
} else {
158-
[self _deleteAppLayout:item forReason: 1];
159-
}
174+
if (!killNowPlayingApplication && [itemBundleID isEqualToString: nowPlayingID]) return;
175+
176+
if (@available(iOS 14.0, *)) {
177+
[self _deleteAppLayoutsMatchingBundleIdentifier:itemBundleID];
178+
} else {
179+
[self _deleteAppLayout:item forReason: 1];
160180
}
181+
161182
}
162183
}
163184

185+
%new
186+
-(void)removeFrontMostApplication:(SBApplication *)application {
187+
NSString *itemBundleID = [application bundleIdentifier];
188+
if (itemBundleID) {
189+
NSString *nowPlayingID = [[[%c(SBMediaController) sharedInstance] nowPlayingApplication] bundleIdentifier];
190+
191+
if (!killNowPlayingApplication && [itemBundleID isEqualToString: nowPlayingID]) return;
164192

193+
if (@available(iOS 14.0, *)) {
194+
[self _deleteAppLayoutsMatchingBundleIdentifier:itemBundleID];
195+
}
196+
}
197+
}
165198

166199
%new
167200
-(NSString *_Nullable)getBundleIDFromAppLayout:(SBAppLayout *_Nullable)appLayout {
@@ -276,12 +309,11 @@ static void updateSettings();
276309

277310
%new
278311
-(void)showWitcherView {
279-
312+
if (!isEnabled) { return; }
280313
SBApplication *frontApp = [(SpringBoard*)[UIApplication sharedApplication] _accessibilityFrontMostApplication];
281314
// NOTE: This message also update data
282-
WitcherApplicationLayoutStruct *applicationStruct = [self performSelector:@selector(getPackedLayoutStructForApplication:) withObject:frontApp];
315+
__unused WitcherApplicationLayoutStruct *applicationStruct = [self performSelector:@selector(getPackedLayoutStructForApplication:) withObject:frontApp];
283316

284-
RLog(@"New layoutStruct! %@", applicationStruct);
285317
if (!isEnabled) { return; }
286318
[self performSelector:@selector(updateRouterWithFrontMostApplications:) withObject:frontApp];
287319

@@ -602,6 +634,7 @@ static void updateSettings() {
602634
NSDictionary *prefs = [NSDictionary dictionaryWithContentsOfFile:WITCHER_PLIST_SETTINGS];
603635
isEnabled = prefs[@"isEnabled"] ? [prefs[@"isEnabled"] boolValue] : YES;
604636
hardwareButtonMode = prefs[@"hardwareButtonMode"] ? [prefs[@"hardwareButtonMode"] boolValue] : NO;
637+
killNowPlayingApplication = prefs[@"killNPA"] ? [prefs[@"killNPA"] boolValue] : NO;
605638

606639
if (router) {
607640
[router updateMainColor:colorFromHex(prefs[@"mainTintColor"] ? prefs[@"mainTintColor"] : @"FFFFFF", YES)];

WitcherPreferences/UI/Cells/AuthorCell/AuthorCell.m

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,10 @@ -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSStri
2525
}
2626

2727
- (void)handleLeftTap {
28-
RLog(@"left view was tapped");
2928
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:profileURL] options:@{} completionHandler:nil];
3029
}
3130

3231
- (void)handleRightTap {
33-
RLog(@"right view was tapped");
3432
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:projectURL] options:@{} completionHandler:nil];
3533
}
3634

WitcherPreferences/WTRRootListController.m

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ -(NSArray *)specifiers {
8181
cell:PSGroupCell
8282
edit:Nil];
8383

84-
[spec setProperty:@"No need for respring" forKey:@"footerText"];
84+
// [spec setProperty:@"No need for respring" forKey:@"footerText"];
8585
[specifiers addObject:spec];
8686

8787
// ColorPicker for Router
@@ -118,6 +118,17 @@ -(NSArray *)specifiers {
118118
[spec setProperty:@60 forKey:@"height"];
119119
[specifiers addObject:spec];
120120

121+
// Actions
122+
spec = [PSSpecifier preferenceSpecifierNamed:@"Actions"
123+
target:self
124+
set:Nil
125+
get:Nil
126+
detail:Nil
127+
cell:PSGroupCell
128+
edit:Nil];
129+
130+
[specifiers addObject:spec];
131+
121132
// Hide/Show action buttons switch cell
122133
spec = [PSSpecifier preferenceSpecifierNamed:@""
123134
target:self
@@ -134,6 +145,22 @@ -(NSArray *)specifiers {
134145
[spec setProperty:@"actionButtons" forKey:@"key"];
135146
[specifiers addObject:spec];
136147

148+
// Kill playing application
149+
spec = [PSSpecifier preferenceSpecifierNamed:@""
150+
target:self
151+
set:@selector(setPreferenceValue:specifier:)
152+
get:@selector(readPreferenceValue:)
153+
detail:Nil
154+
cell:[PSTableCell cellTypeFromString:@""]
155+
edit:Nil];
156+
157+
[spec setProperty:[WitcherSwitchCell class] forKey:@"cellClass"];
158+
[spec setProperty:@"Kill now playing app" forKey:@"title"];
159+
[spec setProperty:@"Music, video players, etc." forKey:@"subtitle"];
160+
[spec setProperty:@NO forKey:@"default"];
161+
[spec setProperty:@"killNPA" forKey:@"key"];
162+
[specifiers addObject:spec];
163+
137164
_specifiers = [specifiers copy];
138165

139166
}
@@ -173,7 +200,7 @@ -(void)setupTitleView {
173200
self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 10, 10)];
174201

175202
[[self titleLabel] setFont:[UIFont fontWithName:@"UbuntuSans-Bold" size:17]];
176-
[[self titleLabel] setText:@"1.0.0"];
203+
[[self titleLabel] setText:@"1.0.1"];
177204
[[self titleLabel] setTextColor:[UIColor labelColor]];
178205
[[self titleLabel] setTextAlignment:NSTextAlignmentCenter];
179206
[[[self navigationItem] titleView] addSubview:[self titleLabel]];

control

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: dr.erast.witcher
22
Name: Witcher
3-
Version: 1.0.0
3+
Version: 1.0.1
44
Architecture: iphoneos-arm
55
Description: Magical iOS App Switcher
66
Maintainer: Erast <[email protected]>

0 commit comments

Comments
 (0)