Back to article
watchbuddy.xm
Full source file from the original WatchBuddy implementation.
#import <substrate.h>
#import "watchbuddy.h"
#define enabletweak @"enabletweak"
#define enablePercent @"enablepercent"
#define disablebackground @"disablebackground"
#define devicename @"devicename"
#define hidedevicenotfound @"hidedevicenotfound"
static BOOL tweakEnabled;
static BOOL percentEnabled;
static BOOL disableBackground;
static BOOL hideDeviceNotFound;
static bool isWatchDevice = FALSE;
NSString* deviceIdentifier;
%group tweakCode
%hook CSNotificationAdjunctListViewController
-(void)viewDidLoad{
%orig;
CGRect screenRect = [[UIScreen mainScreen] bounds];
if(!stackView){
stackView = [self valueForKey:@"_stackView"];
}
if(!watchbuddy){
watchbuddy = [[UIView alloc] initWithFrame:CGRectMake(0, 0, screenRect.size.width, 50)];
}
if(!spacerView){
spacerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, screenRect.size.width, 10)];
}
if(disableBackground == FALSE){
if(!blurEffect){
blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleSystemUltraThinMaterial];
}
}
if(!beView){
beView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
}
if(!watchString){
watchString = [[UILabel alloc]initWithFrame:CGRectMake(35, watchbuddy.frame.origin.y + 15, screenRect.size.width, 20)];
}
if(!batteryview){
batteryview = [[_UIBatteryView alloc] initWithFrame:CGRectMake(screenRect.size.width - 100, watchbuddy.frame.origin.y + 20, 0, 11.5)];
}
watchbuddy.layer.backgroundColor = [UIColor clearColor].CGColor;
watchbuddy.layer.cornerRadius = 15.0;
[stackView addArrangedSubview: watchbuddy];
[stackView addArrangedSubview: spacerView];
stackView.spacing = 10.0;
watchbuddy.translatesAutoresizingMaskIntoConstraints = NO;
[watchbuddy.centerXAnchor constraintEqualToAnchor:stackView.centerXAnchor].active = true;
[watchbuddy.leadingAnchor constraintEqualToAnchor:stackView.leadingAnchor constant:10].active = true;
[watchbuddy.trailingAnchor constraintEqualToAnchor:stackView.trailingAnchor constant:-10].active = true;
[watchbuddy.topAnchor constraintEqualToAnchor:stackView.topAnchor constant: 10].active = true;
[watchbuddy.heightAnchor constraintEqualToConstant:50].active = true;
beView.frame = watchbuddy.frame;
watchbuddy.clipsToBounds = YES;
beView.clipsToBounds = YES;
watchbuddy.autoresizingMask = UIViewAutoresizingFlexibleWidth;
if(disableBackground == FALSE){
[watchbuddy insertSubview:beView atIndex:0];
}
watchString.text = @"Loading Data";
watchString.numberOfLines = 1;
watchString.clipsToBounds = YES;
watchString.backgroundColor = [UIColor clearColor];
watchString.textColor = [UIColor labelColor];
[watchString setFont:[UIFont systemFontOfSize:12]];
[watchbuddy addSubview: watchString];
[batteryview _commonInit];
batteryview.lowBatteryChargePercentThreshold = 0.20; // The val till it changes color
batteryview.chargingState = 0;
if(percentEnabled){
batteryview.showsPercentage = YES;
}
[watchbuddy addSubview: batteryview];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(percentUpdate:) name:@"percentUpdate" object:nil];
[NSTimer scheduledTimerWithTimeInterval:0.3 target:self selector:@selector(MethodB:) userInfo:nil repeats:NO];
}
%new
-(void)updateBatteryData{
NSLog(@"Received Notification - percentUpdate, refreshing view");
BCBatteryDeviceController *bcb = [%c(BCBatteryDeviceController) sharedInstance];
NSArray *devices = [bcb valueForKey:@"_sortedDevices"];
for (BCBatteryDevice *device in devices) {
NSString *deviceName = [device valueForKey:@"_name"];
NSString *deviceCharge = [NSString stringWithFormat:@"%@", [device valueForKey:@"_percentCharge"]];
NSLog(@"Checking if %@ contains %@", deviceName, deviceIdentifier);
if ([[deviceName lowercaseString] containsString:[deviceIdentifier lowercaseString]]) {
long long ChargePercentInt = [deviceCharge intValue];
NSLog(@"CHARGED : %lld\n", ChargePercentInt / 10);
NSTextAttachment *imageAttachment = [[NSTextAttachment alloc] init];
imageAttachment.image = [device glyph];
CGFloat imageOffsetY = -5.0;
imageAttachment.bounds = CGRectMake(0, imageOffsetY, imageAttachment.image.size.width, imageAttachment.image.size.height);
NSAttributedString *attachmentString = [NSAttributedString attributedStringWithAttachment:imageAttachment];
NSMutableAttributedString *completeText= [[NSMutableAttributedString alloc] initWithString:@""];
[completeText appendAttributedString:attachmentString];
NSMutableAttributedString *textAfterIcon= [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@" %@", deviceName]];
[completeText appendAttributedString:textAfterIcon];
isWatchDevice = TRUE;
dispatch_async(dispatch_get_main_queue(), ^{
watchString.attributedText = completeText;
batteryview.chargePercent = ChargePercentInt / 100.0;
});
}
else
{
if(isWatchDevice == FALSE){
dispatch_async(dispatch_get_main_queue(), ^{
watchString.text = @"Device not found";
});
}
}
}
}
%new
-(void)MethodB:(NSTimer*)timer {
[self updateBatteryData];
}
%new
-(void)percentUpdate:(NSNotification *)note {
[self updateBatteryData];
}
%end
%hook BCBatteryDevice
-(void)setPercentCharge:(long long)arg1{
%orig;
NSLog(@"Battery charged, updating watchbuddy\n");
[[NSNotificationCenter defaultCenter] postNotificationName:@"percentUpdate" object:nil];
}
%end
%end
void reloadPrefs() {
static NSUserDefaults *prefs = [[NSUserDefaults alloc] initWithSuiteName:@"com.paddycodes.watchbuddy"];
if (prefs)
tweakEnabled = [prefs objectForKey:enabletweak ] ? ((NSNumber *)[prefs objectForKey:enabletweak]).boolValue : YES;
percentEnabled = [prefs objectForKey:enablePercent ] ? ((NSNumber *)[prefs objectForKey:enablePercent]).boolValue : YES;
disableBackground = [prefs objectForKey:disablebackground ] ? ((NSNumber *)[prefs objectForKey:disablebackground]).boolValue : YES;
deviceIdentifier = [prefs objectForKey:devicename];
hideDeviceNotFound = [prefs objectForKey:hidedevicenotfound ] ? ((NSNumber *)[prefs objectForKey:hidedevicenotfound]).boolValue : YES;
}
%ctor {
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)reloadPrefs, CFSTR("com.paddycodes.watchbuddy/ReloadPreferences"), NULL, kNilOptions);
reloadPrefs();
if(tweakEnabled){
%init(tweakCode);
}
}