#import "Kai.h" CSAdjunctListView *list; %group main %hook SBMediaController - (BOOL)isPlaying { Class cls = kCFCoreFoundationVersionNumber > 1600 ? ([objc_getClass("CSAdjunctListView") class]) : ([objc_getClass("SBDashBoardAdjunctListView") class]); BOOL playing = %orig; if(!removeForMedia) { [cls reorderKai]; return playing; } // if removeForMedia if(self.nowPlayingApplication && shouldBeAdded) { // a valid playing app, and it was shown shouldBeAdded = NO; [[KAIBatteryPlatter sharedInstance] removeFromSuperview]; [[[cls sharedListViewForKai] stackView] removeArrangedSubview:[KAIBatteryPlatter sharedInstance]]; [[cls sharedListViewForKai] _layoutStackView]; return playing; } else if(!playing && self.nowPlayingApplication == nil) { // not playing and the app is nil shouldBeAdded = YES; // if we don't want to hide kai, fix its order [cls reorderKai]; } return playing; } %end %hook KAITarget // This class is defined in %ctor, KAITarget is not a class name. %property (nonatomic, assign) BOOL hasKai; - (void)setClipsToBounds:(BOOL)arg1 { %orig(YES); } - (void)setStackView:(UIStackView *)arg1 { KAISelf.clipsToBounds = YES; if(!KAISelf.hasKai) { list = self; KAIBatteryPlatter *battery = [[KAIBatteryPlatter alloc] initWithFrame:[self stackView].frame]; // Add noti observer [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(KaiInfo) name:@"KaiInfoChanged" object:nil]; KAISelf.hasKai = YES; if(![arg1.subviews containsObject:battery]) { // if not added // add kai to the stack view [self performReorder]; } [battery updateBattery]; // send the adjusted stackview as arg1 %orig(arg1); } } %new - (void)KaiInfo { if(!isUpdating) { isUpdating = YES; dispatch_async(dispatch_get_main_queue(), ^{ [[KAIBatteryPlatter sharedInstance] updateBattery]; if([KAIBatteryPlatter sharedInstance].number == 0) { [[KAIBatteryPlatter sharedInstance] removeFromSuperview]; [[self stackView] removeArrangedSubview:[KAIBatteryPlatter sharedInstance]]; } else if(![[self stackView].subviews containsObject:[KAIBatteryPlatter sharedInstance]] && shouldBeAdded) { [[self stackView] addSubview:[KAIBatteryPlatter sharedInstance]]; [[self stackView] addArrangedSubview:[KAIBatteryPlatter sharedInstance]]; } if([KAISelf.superview respondsToSelector:@selector(fixComplicationsViewFrame)]) { [KAISelf.superview performSelector:@selector(fixComplicationsViewFrame) withObject:KAISelf.superview afterDelay:0.35]; } isUpdating = NO; }); } } %new - (NSInteger)getMediaIndexForClass:(Class)cls { UIView *mediaPlayer; int index = 0; for(UIView *subview in [self stackView].subviews) { if([subview isKindOfClass:cls]) { return index; } index++; } return NSNotFound; } %new - (void)performReorder { UIStackView *stack = [self stackView]; if(placement == 1) { //top BOOL isAperio = NO; @try { isAperio = [stack.subviews[0] isKindOfClass:%c(APEPlatter)]; // index 0 would be the platter, 1 would be placeholder } @catch(NSException *exc) {} [stack removeArrangedSubview:[KAIBatteryPlatter sharedInstance]]; [stack insertArrangedSubview:[KAIBatteryPlatter sharedInstance] atIndex:isAperio]; // so, 0 if not aperio, 1 if aperio } else if(placement == 2) { //after media Class mediaClass = kCFCoreFoundationVersionNumber > 1600 ? %c(CSAdjunctItemView) : %c(SBDashBoardAdjunctItemView); NSInteger mediaIndex = [self getMediaIndexForClass:mediaClass]; if(mediaIndex == NSNotFound) mediaIndex = 0; [stack removeArrangedSubview:[KAIBatteryPlatter sharedInstance]]; [stack insertArrangedSubview:[KAIBatteryPlatter sharedInstance] atIndex:mediaIndex]; } else if(placement == 3) { // bottom [stack removeArrangedSubview:[KAIBatteryPlatter sharedInstance]]; [stack addArrangedSubview:[KAIBatteryPlatter sharedInstance]]; } [self _layoutStackView]; } %new + (id)sharedListViewForKai { return list; } %new + (void)reorderKai { NSLog(@"[Kai]: Reordering kai"); [[self sharedListViewForKai] performReorder]; } %end %hook SBCoverSheetPrimarySlidingViewController - (void)viewDidDisappear:(BOOL)animated { if(reAlignSelf) [[NSNotificationCenter defaultCenter] postNotificationName:@"KaiResetOffset" object:nil userInfo:nil]; %orig; } - (void)viewDidAppear:(BOOL)animated { if(reAlignSelf) [[NSNotificationCenter defaultCenter] postNotificationName:@"KaiResetOffset" object:nil userInfo:nil]; %orig; } %end %hook BCBatteryDevice %property (nonatomic, strong) KAIBatteryCell *kaiCell; - (void)setCharging:(BOOL)arg1 { // sends the noti to update battery info [[NSNotificationCenter defaultCenter] postNotificationName:@"KaiInfoChanged" object:nil userInfo:nil]; %orig; } - (void)setBatterySaverModeActive:(BOOL)arg1 { // sends the noti to update battery info [[NSNotificationCenter defaultCenter] postNotificationName:@"KaiInfoChanged" object:nil userInfo:nil]; %orig; } - (void)setPercentCharge:(NSInteger)arg1 { // sends the noti to update battery info if(arg1 != 0) { [[NSNotificationCenter defaultCenter] postNotificationName:@"KaiInfoChanged" object:nil userInfo:nil]; } %orig; } - (void)dealloc { %orig; [[NSNotificationCenter defaultCenter] postNotificationName:@"KaiInfoChanged" object:nil userInfo:nil]; } %new - (id)kaiCellForDevice { if(self && self.kaiCell == nil) { self.kaiCell = [[KAIBatteryCell alloc] initWithFrame:CGRectMake(0,0,[KAIBatteryPlatter sharedInstance].frame.size.width,0) device:self]; } ((KAIBatteryCell *)self.kaiCell).translatesAutoresizingMaskIntoConstraints = NO; [(KAIBatteryCell *)self.kaiCell updateInfo]; return self.kaiCell; } %new - (void)resetKaiCellForNewPrefs { self.kaiCell = [[KAIBatteryCell alloc] initWithFrame:CGRectMake(0,0,[KAIBatteryPlatter sharedInstance].frame.size.width,0) device:self]; ((KAIBatteryCell *)self.kaiCell).translatesAutoresizingMaskIntoConstraints = NO; [(KAIBatteryCell *)self.kaiCell updateInfo]; } %end %hook KAICSTarget // Again, not a class - (void)_transitionChargingViewToVisible:(BOOL)arg1 showBattery:(BOOL)arg2 animated:(BOOL)arg3 { if(hideChargingAnimation) { // Yeah bro this just makes the method never call to show the charging thing %orig(NO,NO,NO); } else { %orig(arg1, arg2, arg3); } } - (void)_transitionChargingViewToVisible:(BOOL)arg1 showBattery:(BOOL)arg2 animated:(BOOL)arg3 force:(BOOL)arg4 { // might just be ios12 if(hideChargingAnimation) { // Same idea %orig(NO,NO,NO,NO); } else { %orig(arg1, arg2, arg3, arg4); } } %end %end %ctor { preferencesChanged(); CFNotificationCenterAddObserver( CFNotificationCenterGetDarwinNotifyCenter(), &observer, (CFNotificationCallback)applyPrefs, kSettingsChangedNotification, NULL, CFNotificationSuspensionBehaviorDeliverImmediately ); // Bro Muirey helped me figure out a logical way to do this because iOS 12-13 classes have changed Class cls = kCFCoreFoundationVersionNumber > 1600 ? %c(CSAdjunctListView) : %c(SBDashBoardAdjunctListView); Class CSCls = kCFCoreFoundationVersionNumber > 1600 ? %c(CSCoverSheetViewController) : %c(SBDashBoardViewController); if(kCFCoreFoundationVersionNumber < 1740) { ios13 = YES; // wow very pog version you have } if(enabled) { %init(main, KAITarget = cls, KAICSTarget = CSCls); // BIG BRAIN BRO!! } NSLog(@"[kai]: loaded into %@", [NSBundle mainBundle].bundleIdentifier); }