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);
    }
}