Device battery indicators on your Lock Screen
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Kai.xm 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. #import "Kai.h"
  2. CSAdjunctListView *list;
  3. %group main
  4. %hook SBMediaController
  5. - (BOOL)isPlaying {
  6. Class cls = kCFCoreFoundationVersionNumber > 1600 ? ([objc_getClass("CSAdjunctListView") class]) : ([objc_getClass("SBDashBoardAdjunctListView") class]);
  7. BOOL playing = %orig;
  8. if(!removeForMedia) {
  9. [cls reorderKai];
  10. return playing;
  11. }
  12. // if removeForMedia
  13. if(self.nowPlayingApplication && shouldBeAdded) {
  14. // a valid playing app, and it was shown
  15. shouldBeAdded = NO;
  16. [[KAIBatteryPlatter sharedInstance] removeFromSuperview];
  17. [[[cls sharedListViewForKai] stackView] removeArrangedSubview:[KAIBatteryPlatter sharedInstance]];
  18. return playing;
  19. } else if(!playing && self.nowPlayingApplication == nil) {
  20. // not playing and the app is nil
  21. shouldBeAdded = YES;
  22. // if we don't want to hide kai, fix its order
  23. [cls reorderKai];
  24. }
  25. return playing;
  26. }
  27. %end
  28. %hook KAITarget // This class is defined in %ctor, KAITarget is not a class name.
  29. %property (nonatomic, assign) BOOL hasKai;
  30. - (void)setClipsToBounds:(BOOL)arg1 {
  31. %orig(YES);
  32. }
  33. - (void)setStackView:(UIStackView *)arg1 {
  34. KAISelf.clipsToBounds = YES;
  35. if(!KAISelf.hasKai) {
  36. list = self;
  37. KAIBatteryPlatter *battery = [[KAIBatteryPlatter alloc] initWithFrame:[self stackView].frame];
  38. // Add noti observer
  39. [[NSNotificationCenter defaultCenter] addObserver:self
  40. selector:@selector(KaiInfo)
  41. name:@"KaiInfoChanged"
  42. object:nil];
  43. KAISelf.hasKai = YES;
  44. if(![arg1.subviews containsObject:battery]) { // if not added
  45. // add kai to the stack view
  46. [self performReorder];
  47. }
  48. [battery updateBattery];
  49. // send the adjusted stackview as arg1
  50. %orig(arg1);
  51. }
  52. }
  53. %new
  54. - (void)KaiInfo {
  55. if(!isUpdating) {
  56. isUpdating = YES;
  57. dispatch_async(dispatch_get_main_queue(), ^{
  58. [[KAIBatteryPlatter sharedInstance] updateBattery];
  59. if([KAIBatteryPlatter sharedInstance].number == 0) {
  60. [[KAIBatteryPlatter sharedInstance] removeFromSuperview];
  61. [[self stackView] removeArrangedSubview:[KAIBatteryPlatter sharedInstance]];
  62. } else if(![[self stackView].subviews containsObject:[KAIBatteryPlatter sharedInstance]] && shouldBeAdded) {
  63. [[self stackView] addSubview:[KAIBatteryPlatter sharedInstance]];
  64. [[self stackView] addArrangedSubview:[KAIBatteryPlatter sharedInstance]];
  65. }
  66. if([KAISelf.superview respondsToSelector:@selector(fixComplicationsViewFrame)]) {
  67. [KAISelf.superview performSelector:@selector(fixComplicationsViewFrame) withObject:KAISelf.superview afterDelay:0.35];
  68. }
  69. isUpdating = NO;
  70. });
  71. }
  72. }
  73. %new
  74. - (NSInteger)getMediaIndexForClass:(Class)cls {
  75. UIView *mediaPlayer;
  76. int index = 0;
  77. for(UIView *subview in [self stackView].subviews) {
  78. if([subview isKindOfClass:cls]) {
  79. return index;
  80. }
  81. index++;
  82. }
  83. return NSNotFound;
  84. }
  85. %new
  86. - (void)performReorder {
  87. UIStackView *stack = [self stackView];
  88. if(placement == 1) { //top
  89. BOOL isAperio = NO;
  90. @try {
  91. isAperio = [stack.subviews[0] isKindOfClass:%c(APEPlatter)];
  92. // index 0 would be the platter, 1 would be placeholder
  93. } @catch(NSException *exc) {}
  94. [stack removeArrangedSubview:[KAIBatteryPlatter sharedInstance]];
  95. [stack insertArrangedSubview:[KAIBatteryPlatter sharedInstance] atIndex:isAperio];
  96. // so, 0 if not aperio, 1 if aperio
  97. } else if(placement == 2) { //after media
  98. Class mediaClass = kCFCoreFoundationVersionNumber > 1600 ? %c(CSAdjunctItemView) : %c(SBDashBoardAdjunctItemView);
  99. NSInteger mediaIndex = [self getMediaIndexForClass:mediaClass];
  100. if(mediaIndex == NSNotFound) mediaIndex = 0;
  101. [stack removeArrangedSubview:[KAIBatteryPlatter sharedInstance]];
  102. [stack insertArrangedSubview:[KAIBatteryPlatter sharedInstance] atIndex:mediaIndex];
  103. } else if(placement == 3) { // bottom
  104. [stack removeArrangedSubview:[KAIBatteryPlatter sharedInstance]];
  105. [stack addArrangedSubview:[KAIBatteryPlatter sharedInstance]];
  106. }
  107. }
  108. %new
  109. + (id)sharedListViewForKai {
  110. return list;
  111. }
  112. %new
  113. + (void)reorderKai {
  114. NSLog(@"[Kai]: Reordering kai");
  115. [[self sharedListViewForKai] performReorder];
  116. }
  117. %end
  118. %hook SBCoverSheetPrimarySlidingViewController
  119. - (void)viewDidDisappear:(BOOL)animated {
  120. if(reAlignSelf)
  121. [[NSNotificationCenter defaultCenter] postNotificationName:@"KaiResetOffset" object:nil userInfo:nil];
  122. %orig;
  123. }
  124. - (void)viewDidAppear:(BOOL)animated {
  125. if(reAlignSelf)
  126. [[NSNotificationCenter defaultCenter] postNotificationName:@"KaiResetOffset" object:nil userInfo:nil];
  127. %orig;
  128. }
  129. %end
  130. %hook BCBatteryDevice
  131. %property (nonatomic, strong) KAIBatteryCell *kaiCell;
  132. - (void)setCharging:(BOOL)arg1 {
  133. // sends the noti to update battery info
  134. [[NSNotificationCenter defaultCenter] postNotificationName:@"KaiInfoChanged" object:nil userInfo:nil];
  135. %orig;
  136. }
  137. - (void)setBatterySaverModeActive:(BOOL)arg1 {
  138. // sends the noti to update battery info
  139. [[NSNotificationCenter defaultCenter] postNotificationName:@"KaiInfoChanged" object:nil userInfo:nil];
  140. %orig;
  141. }
  142. - (void)setPercentCharge:(NSInteger)arg1 {
  143. // sends the noti to update battery info
  144. if(arg1 != 0) {
  145. [[NSNotificationCenter defaultCenter] postNotificationName:@"KaiInfoChanged" object:nil userInfo:nil];
  146. }
  147. %orig;
  148. }
  149. - (void)dealloc {
  150. %orig;
  151. [[NSNotificationCenter defaultCenter] postNotificationName:@"KaiInfoChanged" object:nil userInfo:nil];
  152. }
  153. %new
  154. - (id)kaiCellForDevice {
  155. if(self && self.kaiCell == nil) {
  156. self.kaiCell = [[KAIBatteryCell alloc] initWithFrame:CGRectMake(0,0,[KAIBatteryPlatter sharedInstance].frame.size.width,0) device:self]; }
  157. ((KAIBatteryCell *)self.kaiCell).translatesAutoresizingMaskIntoConstraints = NO;
  158. [(KAIBatteryCell *)self.kaiCell updateInfo];
  159. return self.kaiCell;
  160. }
  161. %new
  162. - (void)resetKaiCellForNewPrefs {
  163. self.kaiCell = [[KAIBatteryCell alloc] initWithFrame:CGRectMake(0,0,[KAIBatteryPlatter sharedInstance].frame.size.width,0) device:self];
  164. ((KAIBatteryCell *)self.kaiCell).translatesAutoresizingMaskIntoConstraints = NO;
  165. [(KAIBatteryCell *)self.kaiCell updateInfo];
  166. }
  167. %end
  168. %hook KAICSTarget // Again, not a class
  169. - (void)_transitionChargingViewToVisible:(BOOL)arg1 showBattery:(BOOL)arg2 animated:(BOOL)arg3 {
  170. if(hideChargingAnimation) {
  171. // Yeah bro this just makes the method never call to show the charging thing
  172. %orig(NO,NO,NO);
  173. } else {
  174. %orig(arg1, arg2, arg3);
  175. }
  176. }
  177. - (void)_transitionChargingViewToVisible:(BOOL)arg1 showBattery:(BOOL)arg2 animated:(BOOL)arg3 force:(BOOL)arg4 { // might just be ios12
  178. if(hideChargingAnimation) {
  179. // Same idea
  180. %orig(NO,NO,NO,NO);
  181. } else {
  182. %orig(arg1, arg2, arg3, arg4);
  183. }
  184. }
  185. %end
  186. %end
  187. %ctor {
  188. preferencesChanged();
  189. CFNotificationCenterAddObserver(
  190. CFNotificationCenterGetDarwinNotifyCenter(),
  191. &observer,
  192. (CFNotificationCallback)applyPrefs,
  193. kSettingsChangedNotification,
  194. NULL,
  195. CFNotificationSuspensionBehaviorDeliverImmediately
  196. );
  197. // Bro Muirey helped me figure out a logical way to do this because iOS 12-13 classes have changed
  198. Class cls = kCFCoreFoundationVersionNumber > 1600 ? %c(CSAdjunctListView) : %c(SBDashBoardAdjunctListView);
  199. Class CSCls = kCFCoreFoundationVersionNumber > 1600 ? %c(CSCoverSheetViewController) : %c(SBDashBoardViewController);
  200. if(kCFCoreFoundationVersionNumber < 1740) {
  201. ios13 = YES; // wow very pog version you have
  202. }
  203. if(enabled) {
  204. %init(main, KAITarget = cls, KAICSTarget = CSCls); // BIG BRAIN BRO!!
  205. }
  206. NSLog(@"[kai]: loaded into %@", [NSBundle mainBundle].bundleIdentifier);
  207. }