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
95RouterView *router = nil ;
106WitcherApplicationLayoutContainer *container = nil ;
@@ -17,6 +13,7 @@ SBMainSwitcherViewController *mainAppSwitcherVC;
1713
1814#pragma mark - Generators
1915UIImpactFeedbackGenerator *impactFeedbackGenerator = nil ;
16+ UIImpactFeedbackGenerator *heavyImpactFeedbackGenerator = nil ;
2017
2118#pragma mark - Data
2219NSMutableDictionary <NSString *, WitcherApplicationLayoutStruct *> *mutableReusableContainersData = nil ;
@@ -35,6 +32,7 @@ NSUserDefaults *prefs;
3532
3633_Bool isEnabled;
3734_Bool hardwareButtonMode;
35+ _Bool killNowPlayingApplication;
3836
3937static UIColor* colorFromHex (NSString *hexString, BOOL useAlpha);
4038static 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 )];
0 commit comments