@interface KAIBatteryStack : UIStackView | |||||
@interface KAIBatteryPlatter : UIStackView | |||||
@property (nonatomic, assign) NSInteger number; | @property (nonatomic, assign) NSInteger number; | ||||
@property (nonatomic, assign) NSInteger oldCountOfDevices; | @property (nonatomic, assign) NSInteger oldCountOfDevices; | ||||
@property (nonatomic, strong) NSLayoutConstraint *heightConstraint; | @property (nonatomic, strong) NSLayoutConstraint *heightConstraint; | ||||
@property (nonatomic, strong) KAIStackView *stack; | |||||
@property (nonatomic, assign) BOOL isUpdating; | @property (nonatomic, assign) BOOL isUpdating; | ||||
@property (nonatomic, assign) BOOL queued; | @property (nonatomic, assign) BOOL queued; | ||||
+(KAIBatteryStack *)sharedInstance; | |||||
+(KAIBatteryPlatter *)sharedInstance; | |||||
-(instancetype)init; | -(instancetype)init; | ||||
-(void)refreshForPrefs; | -(void)refreshForPrefs; | ||||
-(void)updateBattery; | -(void)updateBattery; |
#import "KAIBatteryStack.h" | |||||
#import "KAIBatteryPlatter.h" | |||||
KAIBatteryStack *instance; | |||||
KAIBatteryPlatter *instance; | |||||
NSTimer *queueTimer = nil; | NSTimer *queueTimer = nil; | ||||
@implementation KAIBatteryStack | |||||
@implementation KAIBatteryPlatter | |||||
-(instancetype)init { | -(instancetype)init { | ||||
self = [super init]; | self = [super init]; | ||||
instance = self; | instance = self; | ||||
if (self) { | if (self) { | ||||
self.axis = 1; | |||||
self.distribution = 0; | |||||
self.spacing = 0; | |||||
self.alignment = 0; | |||||
self.stack = [[KAIStackView alloc] init]; | |||||
self.stack.axis = 1; | |||||
self.stack.distribution = 0; | |||||
self.stack.spacing = 0; | |||||
self.stack.alignment = 0; | |||||
self.oldCountOfDevices = -100; | self.oldCountOfDevices = -100; | ||||
self.queued = NO; | self.queued = NO; | ||||
[self addSubview:self.stack]; | |||||
[self updateBattery]; | [self updateBattery]; | ||||
self.userInteractionEnabled = NO; | |||||
} | } | ||||
return self; | return self; | ||||
} | } | ||||
long long lastPercentage; | long long lastPercentage; | ||||
-(void)updateBattery { | -(void)updateBattery { | ||||
if(!self.stack.widthAnchor) { | |||||
[self.stack.widthAnchor constraintEqualToAnchor:self.widthAnchor].active = YES; | |||||
} | |||||
dispatch_async(dispatch_get_main_queue(), ^{ | dispatch_async(dispatch_get_main_queue(), ^{ | ||||
BCBatteryDeviceController *bcb = [BCBatteryDeviceController sharedInstance]; | BCBatteryDeviceController *bcb = [BCBatteryDeviceController sharedInstance]; | ||||
NSArray *devices = MSHookIvar<NSArray *>(bcb, "_sortedDevices"); | NSArray *devices = MSHookIvar<NSArray *>(bcb, "_sortedDevices"); | ||||
shouldAdd = YES; | shouldAdd = YES; | ||||
} | } | ||||
if(![self.subviews containsObject:cell] && shouldAdd && [devices containsObject:device]) { | |||||
if(![self.stack.subviews containsObject:cell] && shouldAdd && [devices containsObject:device]) { | |||||
//[cell setFrame:CGRectMake(0,0,self.frame.size.width, bannerHeight)]; | //[cell setFrame:CGRectMake(0,0,self.frame.size.width, bannerHeight)]; | ||||
cell.alpha = 0; | cell.alpha = 0; | ||||
[self addSubview:cell]; | |||||
[self addArrangedSubview:cell]; | |||||
[self.stack addSubview:cell]; | |||||
[self.stack addArrangedSubview:cell]; | |||||
[UIView animateWithDuration:0.3 animations:^{ | [UIView animateWithDuration:0.3 animations:^{ | ||||
cell.alpha = 1; | cell.alpha = 1; | ||||
}]; | }]; | ||||
} else if([self.subviews containsObject:cell] && !shouldAdd){ | |||||
} else if([self.stack.subviews containsObject:cell] && !shouldAdd){ | |||||
[UIView animateWithDuration:0.3 animations:^{ | [UIView animateWithDuration:0.3 animations:^{ | ||||
cell.alpha = 0; | cell.alpha = 0; | ||||
} completion:^(BOOL finished) { | } completion:^(BOOL finished) { | ||||
[cell removeFromSuperview]; | [cell removeFromSuperview]; | ||||
[self removeArrangedSubview:cell]; | |||||
[self.stack removeArrangedSubview:cell]; | |||||
cell.alpha = 1; | cell.alpha = 1; | ||||
}]; | }]; | ||||
} | } | ||||
} | } | ||||
for(KAIBatteryCell *cell in self.subviews) { | |||||
for(KAIBatteryCell *cell in self.stack.subviews) { | |||||
if(![devices containsObject:cell.device]) { | if(![devices containsObject:cell.device]) { | ||||
[UIView animateWithDuration:0.3 animations:^{ | [UIView animateWithDuration:0.3 animations:^{ | ||||
cell.alpha = 0; | cell.alpha = 0; | ||||
} completion:^(BOOL finished) { | } completion:^(BOOL finished) { | ||||
[cell removeFromSuperview]; | [cell removeFromSuperview]; | ||||
[self removeArrangedSubview:cell]; | |||||
[self.stack removeArrangedSubview:cell]; | |||||
cell.alpha = 1; | cell.alpha = 1; | ||||
}]; | }]; | ||||
} | } | ||||
self.oldCountOfDevices = [devices count]; | self.oldCountOfDevices = [devices count]; | ||||
self.number = [self.subviews count]; | |||||
self.number = [self.stack.subviews count]; | |||||
if([self.superview.superview.superview respondsToSelector:@selector(fixComplicationsViewFrame)]) { | if([self.superview.superview.superview respondsToSelector:@selector(fixComplicationsViewFrame)]) { | ||||
[(NCNotificationListView *)(self.superview.superview.superview) fixComplicationsViewFrame]; | [(NCNotificationListView *)(self.superview.superview.superview) fixComplicationsViewFrame]; | ||||
if(!self.heightConstraint) { | if(!self.heightConstraint) { | ||||
self.heightConstraint = [self.heightAnchor constraintEqualToConstant:(self.number * (bannerHeight + spacing))]; | self.heightConstraint = [self.heightAnchor constraintEqualToConstant:(self.number * (bannerHeight + spacing))]; | ||||
self.stack.heightConstraint = [self.heightAnchor constraintEqualToConstant:(self.number * (bannerHeight + spacing))]; | |||||
self.heightConstraint.active = YES; | self.heightConstraint.active = YES; | ||||
self.stack.heightConstraint.active = YES; | |||||
} else { | } else { | ||||
int height = (self.number * (bannerHeight + spacing)); | int height = (self.number * (bannerHeight + spacing)); | ||||
//if([self.superview.subviews count]>1) { | |||||
// height = (self.number * (bannerHeight + spacing)) - spacing; | |||||
//} | |||||
if([self.superview.subviews count]>1) { | |||||
height = (self.number * (bannerHeight + spacing)) - spacing; | |||||
} | |||||
self.heightConstraint.constant = height; | self.heightConstraint.constant = height; | ||||
self.stack.heightConstraint.constant = height; | |||||
UIStackView *s = (UIStackView *)(self.superview); | UIStackView *s = (UIStackView *)(self.superview); | ||||
s.frame = CGRectMake(s.frame.origin.x, s.frame.origin.y, s.frame.size.width, (s.frame.size.height - 1)); | s.frame = CGRectMake(s.frame.origin.x, s.frame.origin.y, s.frame.size.width, (s.frame.size.height - 1)); | ||||
-(void)addArrangedSubview:(UIView *)view { | -(void)addArrangedSubview:(UIView *)view { | ||||
[super addArrangedSubview:view]; | [super addArrangedSubview:view]; | ||||
self.number = [self.subviews count]; | |||||
self.number = [self.stack.subviews count]; | |||||
if([self.superview.superview.superview respondsToSelector:@selector(fixComplicationsViewFrame)]) { | if([self.superview.superview.superview respondsToSelector:@selector(fixComplicationsViewFrame)]) { | ||||
[(NCNotificationListView *)(self.superview.superview.superview) fixComplicationsViewFrame]; | [(NCNotificationListView *)(self.superview.superview.superview) fixComplicationsViewFrame]; | ||||
} | } | ||||
-(void)removeArrangedSubview:(UIView *)view { | -(void)removeArrangedSubview:(UIView *)view { | ||||
[super removeArrangedSubview:view]; | [super removeArrangedSubview:view]; | ||||
self.number = [self.subviews count]; | |||||
self.number = [self.stack.subviews count]; | |||||
if([self.superview.superview.superview respondsToSelector:@selector(fixComplicationsViewFrame)]) { | if([self.superview.superview.superview respondsToSelector:@selector(fixComplicationsViewFrame)]) { | ||||
[(NCNotificationListView *)(self.superview.superview.superview) fixComplicationsViewFrame]; | [(NCNotificationListView *)(self.superview.superview.superview) fixComplicationsViewFrame]; | ||||
} | } | ||||
} | } | ||||
-(void)refreshForPrefs { | -(void)refreshForPrefs { | ||||
for( UIView *view in self.subviews ) { | |||||
for( UIView *view in self.stack.subviews ) { | |||||
@try { | @try { | ||||
[view removeFromSuperview]; | [view removeFromSuperview]; | ||||
} @catch (NSException *exception) { | } @catch (NSException *exception) { | ||||
queueTimer = nil; | queueTimer = nil; | ||||
} | } | ||||
+(KAIBatteryStack *)sharedInstance { | |||||
+(KAIBatteryPlatter *)sharedInstance { | |||||
return instance; | return instance; | ||||
} | } | ||||
#import "KAIBatteryStack.h" | |||||
KAIBatteryStack *instance; | |||||
//NSMutableArray *showingCells = [[NSMutableArray alloc] init]; | |||||
@implementation KAIBatteryStack | |||||
-(instancetype)init { | |||||
self = [super init]; | |||||
instance = self; | |||||
if (self) { | |||||
self.displayingDevices = [[NSMutableArray alloc] init]; | |||||
self.axis = 1; | |||||
self.distribution = 0; | |||||
self.spacing = spacing; | |||||
self.alignment = 0; | |||||
[self updateBattery]; | |||||
self.clipsToBounds = YES; | |||||
self.userInteractionEnabled = NO; | |||||
} | |||||
return self; | |||||
} | |||||
long long batteryPercentage; | |||||
long long lastPercentage; | |||||
-(void)updateBattery { | |||||
self.spacing = spacing; | |||||
dispatch_async(dispatch_get_main_queue(), ^{ | |||||
//NSLog(@"kai: battery platter called to update"); | |||||
if(!self.isUpdating) { | |||||
//NSLog(@"kai: IS Updating"); | |||||
self.isUpdating = YES; | |||||
//self.number = 0; | |||||
float y = 0; | |||||
BCBatteryDeviceController *bcb = [BCBatteryDeviceController sharedInstance]; | |||||
NSArray *devices = MSHookIvar<NSArray *>(bcb, "_sortedDevices"); | |||||
if([devices count]!=0) { | |||||
//NSLog(@"kai: info is good, will proceed"); | |||||
float ytwo = 0; | |||||
for(KAIBatteryStackCell *cell in self.subviews) { | |||||
if([cell respondsToSelector:@selector(updateInfo)] && ![devices containsObject:cell.device]) { //to confirm is a cell and battery device does not exist | |||||
//dispatch_async(dispatch_get_main_queue(), ^{ | |||||
[UIView animateWithDuration:0.2 animations:^{ | |||||
cell.alpha = 0; | |||||
} completion:^(BOOL finished){ | |||||
[cell removeFromSuperview]; | |||||
}]; | |||||
//}); | |||||
} else if([cell respondsToSelector:@selector(updateInfo)]) { | |||||
cell.frame = CGRectMake(0, y, self.frame.size.width, bannerHeight); | |||||
[cell updateInfo]; | |||||
ytwo+= bannerHeight + spacing; | |||||
} | |||||
} | |||||
for (BCBatteryDevice *device in devices) { | |||||
NSString *deviceName = MSHookIvar<NSString *>(device, "_name"); | |||||
//double batteryPercentage = MSHookIvar<long long>(device, "_percentCharge"); | |||||
BOOL charging = MSHookIvar<long long>(device, "_charging"); | |||||
//BOOL LPM = MSHookIvar<BOOL>(device, "_batterySaverModeActive"); | |||||
BOOL shouldAdd = NO; | |||||
if(showAll) { | |||||
shouldAdd = YES; | |||||
//NSLog(@"Kai: SHOULD ADD"); | |||||
} else if(!showAll && charging) { | |||||
shouldAdd = YES; | |||||
//NSLog(@"Kai: SHOULD ADD"); | |||||
} | |||||
KAIBatteryStackCell *cell = [KAIBatteryStackCell cellForDeviceIfExists:device frameToCreateNew:CGRectMake(0, y, self.frame.size.width, bannerHeight)]; | |||||
cell.frame = CGRectMake(0, y, self.frame.size.width, bannerHeight); | |||||
if(cell) { | |||||
cell.device = device; | |||||
//cell.frame = cell.frame = CGRectMake(0, y, self.frame.size.width, bannerHeight); //bro im like creating my own stack view | |||||
//[cell updateInfo]; | |||||
} | |||||
if(shouldAdd && [deviceName length]!=0) { | |||||
if(![self.subviews containsObject:cell]) { | |||||
cell.frame = CGRectMake(0, y, self.frame.size.width, bannerHeight); | |||||
cell.alpha = 0; | |||||
[self addSubview:cell]; | |||||
[UIView animateWithDuration:0.3 animations:^{ | |||||
cell.alpha = 1; | |||||
}]; | |||||
} | |||||
y+=bannerHeight + spacing; | |||||
} else if(!shouldAdd) { | |||||
//dispatch_async(dispatch_get_main_queue(), ^{ | |||||
[UIView animateWithDuration:0.2 animations:^{ | |||||
cell.alpha = 0; | |||||
} completion:^(BOOL finished){ | |||||
[cell removeFromSuperview]; | |||||
}]; | |||||
//}); | |||||
} | |||||
} | |||||
//[self.heightAnchor constraintEqualToConstant:(self.number * 85)].active = YES; | |||||
self.number = [self.subviews count]; | |||||
//[(CSAdjunctListView *)self.superview.superview KaiUpdate]; | |||||
} | |||||
self.isUpdating = NO; | |||||
//NSLog(@"kai: finished update"); | |||||
//[(CSAdjunctListView *)self.superview.superview KaiUpdate]; | |||||
[(CSAdjunctListView *)self.superview.superview performSelector:@selector(KaiUpdate) withObject:(CSAdjunctListView *)self.superview.superview afterDelay:0.2]; | |||||
} | |||||
}); | |||||
} | |||||
-(void)removeAllAndRefresh { | |||||
for( UIView *view in self.subviews ) { | |||||
@try { | |||||
[view removeFromSuperview]; | |||||
} @catch (NSException *exception) { | |||||
//Panik | |||||
} | |||||
} | |||||
[KAIBatteryStackCell resetArray]; | |||||
//self.displayingDevices = [[NSMutableArray alloc] init]; | |||||
//addedCells = nil; | |||||
[self updateBattery]; | |||||
} | |||||
+(KAIBatteryStack *)sharedInstance { | |||||
return instance; | |||||
} | |||||
@end |
@interface KAIStackView : UIStackView | |||||
@property (nonatomic, strong) NSLayoutConstraint *heightConstraint; | |||||
@end |
#import "KAIStackView.h" | |||||
@implementation KAIStackView | |||||
-(id)initWithFrame:(CGRect)arg1 { | |||||
self = [super initWithFrame:arg1]; | |||||
self.translatesAutoresizingMaskIntoConstraints = NO; | |||||
return self; | |||||
} | |||||
@end |
#import "NSTask.h" | #import "NSTask.h" | ||||
#define KAISelf ((CSAdjunctListView *)self) //for use when calling self in KAITarget | #define KAISelf ((CSAdjunctListView *)self) //for use when calling self in KAITarget | ||||
//#define KAIBatteryStack UHDUEIHGCEBCHYDEICVKEVSAGJKBCXAHJGKVXHAS //lmao | |||||
//#define KAIBatteryPlatter UHDUEIHGCEBCHYDEICVKEVSAGJKBCXAHJGKVXHAS //lmao | |||||
//#define KAIBatteryCell HDEIUOGEUBGUYOEXHNOPUSZIOJIGECEXIUSHXJXBE //very good | //#define KAIBatteryCell HDEIUOGEUBGUYOEXHNOPUSZIOJIGECEXIUSHXJXBE //very good | ||||
@interface CSAdjunctListView : UIView | @interface CSAdjunctListView : UIView | ||||
//by importing here, I can use vars in the .mm files | //by importing here, I can use vars in the .mm files | ||||
#import "KAIBatteryCell.mm" | #import "KAIBatteryCell.mm" | ||||
#import "KAIBatteryStack.mm" | |||||
#import "KAIStackView.mm" | |||||
#import "KAIBatteryPlatter.mm" | |||||
#define PLIST_PATH @"/User/Library/Preferences/com.burritoz.kaiprefs.plist" | #define PLIST_PATH @"/User/Library/Preferences/com.burritoz.kaiprefs.plist" | ||||
#define kIdentifier @"com.burritoz.kaiprefs" | #define kIdentifier @"com.burritoz.kaiprefs" | ||||
isUpdating = YES; | isUpdating = YES; | ||||
[[KAIBatteryStack sharedInstance] refreshForPrefs]; //so hard (not) | |||||
[(CSAdjunctListView *)([KAIBatteryStack sharedInstance].superview.superview) _layoutStackView]; | |||||
[[KAIBatteryPlatter sharedInstance] refreshForPrefs]; //so hard (not) | |||||
[(CSAdjunctListView *)([KAIBatteryPlatter sharedInstance].superview.superview) _layoutStackView]; | |||||
isUpdating = NO; | isUpdating = NO; | ||||
NSInteger lastSlot = [[self stackView].subviews count] -1; | NSInteger lastSlot = [[self stackView].subviews count] -1; | ||||
//this code is used to determine if kai is at the bottom of the stack view | //this code is used to determine if kai is at the bottom of the stack view | ||||
if([[self stackView].subviews objectAtIndex:lastSlot] != [KAIBatteryStack sharedInstance] && belowMusic) { | |||||
if([[self stackView].subviews objectAtIndex:lastSlot] != [KAIBatteryPlatter sharedInstance] && belowMusic) { | |||||
//if it is not, but the option to have kai below music is on, i simply remove from it's current pos. | //if it is not, but the option to have kai below music is on, i simply remove from it's current pos. | ||||
//and insert into last slot. | //and insert into last slot. | ||||
[[self stackView] removeArrangedSubview:[KAIBatteryStack sharedInstance]]; | |||||
[[self stackView] insertArrangedSubview:[KAIBatteryStack sharedInstance] atIndex:lastSlot]; | |||||
[[self stackView] removeArrangedSubview:[KAIBatteryPlatter sharedInstance]]; | |||||
[[self stackView] insertArrangedSubview:[KAIBatteryPlatter sharedInstance] atIndex:lastSlot]; | |||||
} | } | ||||
if([KAISelf.superview respondsToSelector:@selector(fixComplicationsViewFrame)]) { | if([KAISelf.superview respondsToSelector:@selector(fixComplicationsViewFrame)]) { | ||||
[(NCNotificationListView *)(KAISelf.superview) fixComplicationsViewFrame]; | [(NCNotificationListView *)(KAISelf.superview) fixComplicationsViewFrame]; | ||||
} | } | ||||
[[KAIBatteryStack sharedInstance] setNumber:[KAIBatteryStack sharedInstance].number]; | |||||
[[KAIBatteryPlatter sharedInstance] setNumber:[KAIBatteryPlatter sharedInstance].number]; | |||||
%orig; | %orig; | ||||
} | } | ||||
-(void)setStackView:(UIStackView *)arg1 { | -(void)setStackView:(UIStackView *)arg1 { | ||||
if(!KAISelf.hasKai) { | if(!KAISelf.hasKai) { | ||||
KAIBatteryStack *battery = [[KAIBatteryStack alloc] init]; | |||||
KAIBatteryPlatter *battery = [[KAIBatteryPlatter alloc] init]; | |||||
//Add noti observer | //Add noti observer | ||||
[[NSNotificationCenter defaultCenter] addObserver:self | [[NSNotificationCenter defaultCenter] addObserver:self | ||||
//NSLog(@"kai: kai info will update"); | //NSLog(@"kai: kai info will update"); | ||||
dispatch_async(dispatch_get_main_queue(), ^{ | dispatch_async(dispatch_get_main_queue(), ^{ | ||||
[[KAIBatteryStack sharedInstance] updateBattery]; | |||||
if([KAIBatteryStack sharedInstance].number == 0) { | |||||
[[KAIBatteryStack sharedInstance] removeFromSuperview]; | |||||
[[self stackView] removeArrangedSubview:[KAIBatteryStack sharedInstance]]; | |||||
} else if(![[self stackView].subviews containsObject:[KAIBatteryStack sharedInstance]]) { | |||||
[[self stackView] addSubview:[KAIBatteryStack sharedInstance]]; | |||||
[[self stackView] addArrangedSubview:[KAIBatteryStack sharedInstance]]; | |||||
[[KAIBatteryPlatter sharedInstance] updateBattery]; | |||||
if([KAIBatteryPlatter sharedInstance].number == 0) { | |||||
[[KAIBatteryPlatter sharedInstance] removeFromSuperview]; | |||||
[[self stackView] removeArrangedSubview:[KAIBatteryPlatter sharedInstance]]; | |||||
} else if(![[self stackView].subviews containsObject:[KAIBatteryPlatter sharedInstance]]) { | |||||
[[self stackView] addSubview:[KAIBatteryPlatter sharedInstance]]; | |||||
[[self stackView] addArrangedSubview:[KAIBatteryPlatter sharedInstance]]; | |||||
} | } | ||||
if([KAISelf.superview respondsToSelector:@selector(fixComplicationsViewFrame)]) { | if([KAISelf.superview respondsToSelector:@selector(fixComplicationsViewFrame)]) { | ||||
[KAISelf.superview performSelector:@selector(fixComplicationsViewFrame) withObject:KAISelf.superview afterDelay:0.35]; | [KAISelf.superview performSelector:@selector(fixComplicationsViewFrame) withObject:KAISelf.superview afterDelay:0.35]; | ||||
%new | %new | ||||
-(id)kaiCellForDevice { | -(id)kaiCellForDevice { | ||||
if(self && self.kaiCell == nil) { | if(self && self.kaiCell == nil) { | ||||
self.kaiCell = [[KAIBatteryCell alloc] initWithFrame:CGRectMake(0,0,[KAIBatteryStack sharedInstance].frame.size.width,0) device:self]; } | |||||
self.kaiCell = [[KAIBatteryCell alloc] initWithFrame:CGRectMake(0,0,[KAIBatteryPlatter sharedInstance].frame.size.width,0) device:self]; } | |||||
((KAIBatteryCell *)self.kaiCell).translatesAutoresizingMaskIntoConstraints = NO; | ((KAIBatteryCell *)self.kaiCell).translatesAutoresizingMaskIntoConstraints = NO; | ||||
[(KAIBatteryCell *)self.kaiCell updateInfo]; | [(KAIBatteryCell *)self.kaiCell updateInfo]; | ||||
%new | %new | ||||
-(void)resetKaiCellForNewPrefs { | -(void)resetKaiCellForNewPrefs { | ||||
self.kaiCell = [[KAIBatteryCell alloc] initWithFrame:CGRectMake(0,0,[KAIBatteryStack sharedInstance].frame.size.width,0) device:self]; | |||||
self.kaiCell = [[KAIBatteryCell alloc] initWithFrame:CGRectMake(0,0,[KAIBatteryPlatter sharedInstance].frame.size.width,0) device:self]; | |||||
((KAIBatteryCell *)self.kaiCell).translatesAutoresizingMaskIntoConstraints = NO; | ((KAIBatteryCell *)self.kaiCell).translatesAutoresizingMaskIntoConstraints = NO; | ||||
[(KAIBatteryCell *)self.kaiCell updateInfo]; | [(KAIBatteryCell *)self.kaiCell updateInfo]; | ||||
} | } |