Device battery indicators on your Lock Screen
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

234 lines
8.2KB

  1. #import "KAIBatteryStack.h"
  2. KAIBatteryStack *instance;
  3. NSTimer *queueTimer = nil;
  4. //NSMutableArray *showingCells = [[NSMutableArray alloc] init];
  5. @implementation KAIBatteryStack
  6. -(instancetype)init {
  7. self = [super init];
  8. instance = self;
  9. if (self) {
  10. self.displayingDevices = [[NSMutableArray alloc] init];
  11. self.axis = 1;
  12. self.distribution = 0;
  13. self.spacing = 0;
  14. self.alignment = 0;
  15. self.oldCountOfDevices = -100;
  16. self.queued = NO;
  17. [self updateBattery];
  18. //self.clipsToBounds = YES;
  19. self.userInteractionEnabled = NO;
  20. }
  21. return self;
  22. }
  23. long long batteryPercentage;
  24. long long lastPercentage;
  25. -(void)updateBattery {
  26. dispatch_async(dispatch_get_main_queue(), ^{
  27. BCBatteryDeviceController *bcb = [BCBatteryDeviceController sharedInstance];
  28. NSArray *devices = MSHookIvar<NSArray *>(bcb, "_sortedDevices");
  29. if(self.oldCountOfDevices == -100) {
  30. self.oldCountOfDevices = [devices count] + 1;
  31. }
  32. if(!self.isUpdating && self.oldCountOfDevices != 0 && ([devices count] + 1 == self.oldCountOfDevices || [devices count] - 1 == self.oldCountOfDevices || [devices count] == self.oldCountOfDevices)) {
  33. //if(!self.isUpdating) {
  34. self.isUpdating = YES;
  35. for (BCBatteryDevice *device in devices) {
  36. KAIBatteryCell *cell = [device kaiCellForDevice];
  37. BOOL charging = MSHookIvar<long long>(device, "_charging");
  38. BOOL internal = MSHookIvar<BOOL>(device, "_internal");
  39. BOOL shouldAdd = NO;
  40. if(showAll) {
  41. shouldAdd = YES;
  42. } else if(showAllMinusInternal && !internal) {
  43. shouldAdd = YES;
  44. } else if(!showAll && charging) {
  45. shouldAdd = YES;
  46. }
  47. if(![self.subviews containsObject:cell] && shouldAdd && [devices containsObject:device]) {
  48. //[cell setFrame:CGRectMake(0,0,self.frame.size.width, bannerHeight)];
  49. cell.alpha = 0;
  50. [self addSubview:cell];
  51. [self addArrangedSubview:cell];
  52. [UIView animateWithDuration:0.3 animations:^{
  53. cell.alpha = 1;
  54. }];
  55. } else if([self.subviews containsObject:cell] && !shouldAdd){
  56. [UIView animateWithDuration:0.3 animations:^{
  57. cell.alpha = 0;
  58. } completion:^(BOOL finished) {
  59. [cell removeFromSuperview];
  60. [self removeArrangedSubview:cell];
  61. cell.alpha = 1;
  62. }];
  63. }
  64. }
  65. for(KAIBatteryCell *cell in self.subviews) {
  66. if(![devices containsObject:cell.device]) {
  67. [UIView animateWithDuration:0.3 animations:^{
  68. cell.alpha = 0;
  69. } completion:^(BOOL finished) {
  70. [cell removeFromSuperview];
  71. [self removeArrangedSubview:cell];
  72. cell.alpha = 1;
  73. }];
  74. }
  75. }
  76. queueTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(dispatchQueue) userInfo:nil repeats:NO];
  77. self.isUpdating = NO;
  78. } else if(self.isUpdating) {
  79. self.queued = YES;
  80. }
  81. self.oldCountOfDevices = [devices count];
  82. self.number = [self.subviews count];
  83. [UIView animateWithDuration:0.3 animations:^{
  84. if(!self.heightConstraint) {
  85. self.heightConstraint = [self.heightAnchor constraintEqualToConstant:(self.number * (bannerHeight + spacing))];
  86. self.heightConstraint.active = YES;
  87. } else {
  88. int height = (self.number * (bannerHeight + spacing));
  89. self.heightConstraint.constant = height;
  90. UIStackView *s = (UIStackView *)(self.superview);
  91. s.frame = CGRectMake(s.frame.origin.x, s.frame.origin.y, s.frame.size.width, (s.frame.size.height - 1));
  92. //literally does nothing but makes the stack view lay itself out (doesnt adjust frame because translatesAutoreszingMaskIntoConstraints = NO on stack views)
  93. }
  94. }];
  95. if([self.superview.superview.superview respondsToSelector:@selector(fixComplicationsViewFrame)]) {
  96. [(NCNotificationListView *)(self.superview.superview.superview) fixComplicationsViewFrame];
  97. }
  98. });
  99. }
  100. -(void)addArrangedSubview:(UIView *)view {
  101. [super addArrangedSubview:view];
  102. self.number = [self.subviews count];
  103. if([self.superview.superview.superview respondsToSelector:@selector(fixComplicationsViewFrame)]) {
  104. [(NCNotificationListView *)(self.superview.superview.superview) fixComplicationsViewFrame];
  105. }
  106. [UIView animateWithDuration:0.3 animations:^{
  107. if(!self.heightConstraint) {
  108. self.heightConstraint.active = NO;
  109. self.heightConstraint = [self.heightAnchor constraintEqualToConstant:(self.number * (bannerHeight + spacing))];
  110. //set an initial constraint
  111. self.heightConstraint.active = YES;
  112. } else {
  113. int height = (self.number * (bannerHeight + spacing)); //big brain math
  114. //self.heightConstraint.active = NO; //deactivation
  115. self.heightConstraint.constant = height;
  116. //self.heightConstraint.active = YES; //forcing reactivation
  117. UIStackView *s = (UIStackView *)(self.superview);
  118. s.frame = CGRectMake(s.frame.origin.x, s.frame.origin.y, s.frame.size.width, (s.frame.size.height - 1));
  119. //literally does nothing but makes the stack view lay itself out (doesnt adjust frame because translatesAutoreszingMaskIntoConstraints = NO on stack views)
  120. }
  121. }];
  122. if(textColor==0) {
  123. KAIBatteryCell *cell = (KAIBatteryCell *)view;
  124. if(@available(iOS 12.0, *)) {
  125. if(self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark) {
  126. [cell.label setTextColor:[UIColor whiteColor]];
  127. [cell.percentLabel setTextColor:[UIColor whiteColor]];
  128. } else if(self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleLight) {
  129. [cell.label setTextColor:[UIColor blackColor]];
  130. [cell.percentLabel setTextColor:[UIColor blackColor]];
  131. }
  132. }
  133. }
  134. }
  135. -(void)removeArrangedSubview:(UIView *)view {
  136. [super removeArrangedSubview:view];
  137. self.number = [self.subviews count];
  138. if([self.superview.superview.superview respondsToSelector:@selector(fixComplicationsViewFrame)]) {
  139. [(NCNotificationListView *)(self.superview.superview.superview) fixComplicationsViewFrame];
  140. }
  141. [UIView animateWithDuration:0.3 animations:^{
  142. if(!self.heightConstraint) {
  143. self.heightConstraint.active = NO;
  144. self.heightConstraint = [self.heightAnchor constraintEqualToConstant:(self.number * (bannerHeight + spacing))];
  145. //set an initial constraint
  146. self.heightConstraint.active = YES;
  147. } else {
  148. int height = (self.number * (bannerHeight + spacing)); //big brain math
  149. //self.heightConstraint.active = NO; //deactivation
  150. self.heightConstraint.constant = height;
  151. //self.heightConstraint.active = YES; //forcing reactivation
  152. UIStackView *s = (UIStackView *)(self.superview);
  153. s.frame = CGRectMake(s.frame.origin.x, s.frame.origin.y, s.frame.size.width, (s.frame.size.height - 1));
  154. //literally does nothing but makes the stack view lay itself out (doesnt adjust frame because translatesAutoreszingMaskIntoConstraints = NO on stack views)
  155. }
  156. }];
  157. }
  158. -(void)refreshForPrefs {
  159. for( UIView *view in self.subviews ) {
  160. @try {
  161. [view removeFromSuperview];
  162. } @catch (NSException *exception) {
  163. //Panik
  164. }
  165. }
  166. BCBatteryDeviceController *bcb = [BCBatteryDeviceController sharedInstance];
  167. NSArray *devices = MSHookIvar<NSArray *>(bcb, "_sortedDevices");
  168. for(BCBatteryDevice *device in devices) {
  169. [device resetKaiCellForNewPrefs];
  170. }
  171. [self updateBattery];
  172. }
  173. -(void)dispatchQueue {
  174. self.isUpdating = NO;
  175. if(self.queued) {
  176. [self updateBattery];
  177. if([self.superview.superview.superview respondsToSelector:@selector(fixComplicationsViewFrame)]) {
  178. [(NCNotificationListView *)(self.superview.superview.superview) fixComplicationsViewFrame];
  179. }
  180. self.queued = NO;
  181. }
  182. [queueTimer invalidate];
  183. queueTimer = nil;
  184. }
  185. +(KAIBatteryStack *)sharedInstance {
  186. return instance;
  187. }
  188. @end