├── Makefile ├── ntspeedhooks ├── Makefile └── Tweak.xm └── ntspeedsettings ├── Makefile └── NtSpeedSettingsController.mm /Makefile: -------------------------------------------------------------------------------- 1 | include $(THEOS)/makefiles/common.mk 2 | 3 | SUBPROJECTS += ntspeedhooks 4 | SUBPROJECTS += ntspeedsettings 5 | 6 | include $(THEOS_MAKE_PATH)/aggregate.mk 7 | 8 | all:: 9 | 10 | -------------------------------------------------------------------------------- /ntspeedhooks/Makefile: -------------------------------------------------------------------------------- 1 | include $(THEOS)/makefiles/common.mk 2 | 3 | TWEAK_NAME = NtSpeed 4 | $(TWEAK_NAME)_FILES = /mnt/d/codes/ntspeed/ntspeedhooks/Tweak.xm 5 | $(TWEAK_NAME)_FRAMEWORKS = CydiaSubstrate Foundation UIKit CoreGraphics 6 | #$(TWEAK_NAME)_CFLAGS = -fobjc-arc 7 | $(TWEAK_NAME)_LDFLAGS = -Wl,-segalign,4000 8 | 9 | $(TWEAK_NAME)_ARCHS = armv7 armv7s arm64 arm64e 10 | export ARCHS = armv7 armv7s arm64 arm64e 11 | 12 | include $(THEOS_MAKE_PATH)/tweak.mk 13 | -------------------------------------------------------------------------------- /ntspeedsettings/Makefile: -------------------------------------------------------------------------------- 1 | include $(THEOS)/makefiles/common.mk 2 | 3 | BUNDLE_NAME = NtSpeedSettings 4 | 5 | $(BUNDLE_NAME)_FILES = /mnt/d/codes/ntspeed/ntspeedsettings/NtSpeedSettingsController.mm 6 | 7 | $(BUNDLE_NAME)_INSTALL_PATH = /Library/PreferenceBundles 8 | $(BUNDLE_NAME)_FRAMEWORKS = UIKit QuartzCore CoreGraphics MessageUI Social Twitter 9 | $(BUNDLE_NAME)_PRIVATE_FRAMEWORKS = Preferences 10 | $(BUNDLE_NAME)_CFLAGS = -fobjc-arc 11 | $(BUNDLE_NAME)_LDFLAGS = -Wl,-segalign,4000 12 | 13 | $(BUNDLE_NAME)_ARCHS = armv7 armv7s arm64 arm64e 14 | export ARCHS = armv7 armv7s arm64 arm64e 15 | 16 | include $(THEOS_MAKE_PATH)/bundle.mk 17 | -------------------------------------------------------------------------------- /ntspeedhooks/Tweak.xm: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | #import 5 | #import 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define NSLog(...) 13 | 14 | #define PLIST_PATH_Settings "/var/mobile/Library/Preferences/com.julioverne.ntspeed.plist" 15 | 16 | static BOOL Enabled; 17 | 18 | static BOOL alwaysVisible; 19 | static BOOL isBlackScreen; 20 | 21 | static int textColor; 22 | 23 | static int kWidth = 40; 24 | static int kHeight = 15; 25 | 26 | static int kLocX = 5; 27 | static int kLocY = 20; 28 | 29 | static float kAlpha = 0.5f; 30 | static float kAlphaText = 0.9f; 31 | static float kRadius = 6; 32 | 33 | static BOOL forceNewLocation; 34 | 35 | static float kScreenW; 36 | static float kScreenH; 37 | 38 | static __strong NSString* kBs = [[@"%ldB/s" copy] retain]; 39 | static __strong NSString* kKs = [[@"%.1fK/s" copy] retain]; 40 | static __strong NSString* kMs = [[@"%.2fM/s" copy] retain]; 41 | static __strong NSString* kGs = [[@"%.3fG/s" copy] retain]; 42 | 43 | 44 | static __unused NSString *bytesFormat(long long bytes) 45 | { 46 | //@autoreleasepool { 47 | if(bytes < 1024) { 48 | return [NSString stringWithFormat:kBs, bytes]; 49 | } else if(bytes >= 1024 && bytes < 1024 * 1024) { 50 | return [NSString stringWithFormat:kKs, (double)bytes / 1024]; 51 | } else if(bytes >= 1024 * 1024 && bytes < 1024 * 1024 * 1024) { 52 | return [NSString stringWithFormat:kMs, (double)bytes / (1024 * 1024)]; 53 | } else { 54 | return [NSString stringWithFormat:kGs, (double)bytes / (1024 * 1024 * 1024)]; 55 | } 56 | //} 57 | } 58 | 59 | static long long getBytesTotal() 60 | { 61 | @autoreleasepool { 62 | long long iBytes = 0; 63 | long long oBytes = 0; 64 | struct ifaddrs *ifa_list = NULL, *ifa; 65 | if ((getifaddrs(&ifa_list) < 0) || !ifa_list || ifa_list==0) { 66 | return 0; 67 | } 68 | for (ifa = ifa_list; ifa; ifa = ifa->ifa_next) { 69 | if (ifa->ifa_addr == NULL) { 70 | continue; 71 | } 72 | if (AF_LINK != ifa->ifa_addr->sa_family) { 73 | continue; 74 | } 75 | if (!(ifa->ifa_flags & IFF_UP) && !(ifa->ifa_flags & IFF_RUNNING)) { 76 | continue; 77 | } 78 | if (ifa->ifa_data == NULL || ifa->ifa_data == 0) { 79 | continue; 80 | } 81 | struct if_data *if_data = (struct if_data *)ifa->ifa_data; 82 | iBytes += if_data->ifi_ibytes; 83 | oBytes += if_data->ifi_obytes; 84 | } 85 | if(ifa_list) { 86 | freeifaddrs(ifa_list); 87 | } 88 | return iBytes + oBytes; 89 | } 90 | } 91 | 92 | @interface UIWindow () 93 | - (void)_setSecure:(BOOL)arg1; 94 | @end 95 | @interface UIApplication () 96 | - (UIDeviceOrientation)_frontMostAppOrientation; 97 | @end 98 | 99 | @interface NtSpeedWindow : UIWindow 100 | @end 101 | @implementation NtSpeedWindow 102 | - (BOOL)_ignoresHitTest 103 | { 104 | return YES; 105 | } 106 | + (BOOL)_isSecure 107 | { 108 | return YES; 109 | } 110 | - (void)dalloc 111 | { 112 | return; 113 | } 114 | - (oneway void)release 115 | { 116 | return; 117 | } 118 | @end 119 | 120 | @interface NtSpeed : NSObject 121 | { 122 | UIWindow* springboardWindow; 123 | UILabel *label; 124 | UIView *backView; 125 | UIView *content; 126 | } 127 | @property (nonatomic, strong) UIWindow* springboardWindow; 128 | @property (nonatomic, strong) UILabel *label; 129 | @property (nonatomic, strong) UIView *backView; 130 | @property (nonatomic, strong) UIView *content; 131 | + (id)sharedInstance; 132 | + (BOOL)sharedInstanceExist; 133 | + (void)notifyOrientationChange; 134 | - (void)firstload; 135 | - (void)orientationChanged; 136 | - (void)updateFrame; 137 | @end 138 | 139 | static void orientationChanged() 140 | { 141 | [NtSpeed notifyOrientationChange]; 142 | } 143 | 144 | static long long oldSpeed = 0; 145 | static UIDeviceOrientation orientationOld; 146 | 147 | @implementation NtSpeed 148 | @synthesize springboardWindow, label, backView, content; 149 | __strong static id _sharedObject; 150 | + (id)sharedInstance 151 | { 152 | if (!_sharedObject) { 153 | _sharedObject = [[[self alloc] init] retain]; 154 | [NSTimer scheduledTimerWithTimeInterval:1 target:_sharedObject selector:@selector(update) userInfo:nil repeats:YES]; 155 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)&orientationChanged, CFSTR("com.apple.springboard.screenchanged"), NULL, (CFNotificationSuspensionBehavior)0); 156 | CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(), NULL, (CFNotificationCallback)&orientationChanged, CFSTR("UIWindowDidRotateNotification"), NULL, CFNotificationSuspensionBehaviorCoalesce); 157 | } 158 | return [_sharedObject retain]; 159 | } 160 | + (BOOL)sharedInstanceExist 161 | { 162 | if (_sharedObject) { 163 | return YES; 164 | } 165 | return NO; 166 | } 167 | + (void)notifyOrientationChange 168 | { 169 | @try { 170 | if([NtSpeed sharedInstanceExist]) { 171 | if (NtSpeed* NTShared = [[NtSpeed sharedInstance] retain]) { 172 | [NTShared orientationChanged]; 173 | } 174 | } 175 | } @catch (NSException * e) { 176 | } 177 | } 178 | - (void)firstload 179 | { 180 | return; 181 | } 182 | - (void)updateLabelColor 183 | { 184 | if(label) { 185 | label.textColor = textColor==0?[UIColor whiteColor]:textColor==1?[UIColor blackColor]:textColor==2?[UIColor redColor]:textColor==3?[UIColor greenColor]:textColor==4?[UIColor blueColor]:[UIColor grayColor]; 186 | } 187 | } 188 | -(id)init 189 | { 190 | self = [super init]; 191 | if(self != nil) { 192 | @try { 193 | kScreenW = [[UIScreen mainScreen] bounds].size.width; 194 | kScreenH = [[UIScreen mainScreen] bounds].size.height; 195 | 196 | springboardWindow = [[[NtSpeedWindow alloc] initWithFrame:CGRectZero] retain]; 197 | springboardWindow.windowLevel = 9999999; 198 | [springboardWindow setHidden:NO]; 199 | springboardWindow.alpha = 1; 200 | [springboardWindow _setSecure:YES]; 201 | [springboardWindow setUserInteractionEnabled:NO]; 202 | springboardWindow.layer.cornerRadius = kRadius; 203 | springboardWindow.layer.masksToBounds = YES; 204 | springboardWindow.layer.shouldRasterize = NO; 205 | 206 | backView = [UIView new]; 207 | backView.backgroundColor = [UIColor colorWithWhite: 0.50 alpha:1]; 208 | [(UIView *)springboardWindow addSubview:backView]; 209 | 210 | content = [UIView new]; 211 | label = [[UILabel alloc]initWithFrame:CGRectZero]; 212 | [self update]; 213 | label.numberOfLines = 1; 214 | [self updateLabelColor]; 215 | label.baselineAdjustment = (UIBaselineAdjustment)YES; 216 | label.adjustsFontSizeToFitWidth = YES; 217 | label.adjustsLetterSpacingToFitWidth = YES; 218 | label.textAlignment = NSTextAlignmentCenter; 219 | [content addSubview:label]; 220 | [(UIView *)springboardWindow addSubview:content]; 221 | 222 | [self updateFrame]; 223 | 224 | } @catch (NSException * e) { 225 | } 226 | } 227 | return self; 228 | } 229 | - (void)updateFrame 230 | { 231 | [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_updateFrame) object:nil]; 232 | [self performSelector:@selector(_updateFrame) withObject:nil afterDelay:0.3]; 233 | } 234 | - (void)_updateFrame 235 | { 236 | @try { 237 | backView.alpha = kAlpha; 238 | content.alpha = kAlphaText; 239 | [self updateLabelColor]; 240 | springboardWindow.layer.cornerRadius = kRadius; 241 | springboardWindow.frame = CGRectMake(0, 0, kWidth, kHeight); 242 | backView.frame = CGRectMake(0, 0, springboardWindow.frame.size.width, springboardWindow.frame.size.height); 243 | content.frame = CGRectMake(4, 0, springboardWindow.frame.size.width-8, springboardWindow.frame.size.height); 244 | label.frame = CGRectMake(0, 0, content.frame.size.width, content.frame.size.height); 245 | forceNewLocation = YES; 246 | [springboardWindow setHidden:NO]; 247 | [self orientationChanged]; 248 | } @catch (NSException * e) { 249 | } 250 | } 251 | - (void)update 252 | { 253 | @try { 254 | @autoreleasepool { 255 | if(!Enabled || isBlackScreen) { 256 | if(springboardWindow && !springboardWindow.hidden) { 257 | [springboardWindow setHidden:YES]; 258 | } 259 | return; 260 | } 261 | long long nowData = getBytesTotal(); 262 | if(!oldSpeed) { 263 | oldSpeed = nowData; 264 | } 265 | if(label&&springboardWindow) { 266 | long long speed = nowData-oldSpeed; 267 | if(speed < 0) { 268 | speed = 0; 269 | } 270 | [springboardWindow setHidden:(!alwaysVisible && speed==0)?YES:NO]; 271 | label.text = bytesFormat(speed); 272 | } 273 | oldSpeed = nowData; 274 | } 275 | } @catch (NSException * e) { 276 | } 277 | } 278 | - (void)orientationChanged 279 | { 280 | @try { 281 | UIDeviceOrientation orientation = [[UIApplication sharedApplication] _frontMostAppOrientation]; 282 | if(orientation == orientationOld && !forceNewLocation) { 283 | return; 284 | } 285 | forceNewLocation = NO; 286 | BOOL isLandscape; 287 | __block CGAffineTransform newTransform; 288 | __block int xLoc; 289 | __block int yLoc; 290 | #define DegreesToRadians(degrees) (degrees * M_PI / 180) 291 | switch (orientation) { 292 | case UIDeviceOrientationLandscapeRight: { 293 | isLandscape = YES; 294 | yLoc = kLocX; 295 | xLoc = kLocY; 296 | newTransform = CGAffineTransformMakeRotation(-DegreesToRadians(90)); 297 | break; 298 | } 299 | case UIDeviceOrientationLandscapeLeft: { 300 | isLandscape = YES; 301 | yLoc = (kScreenH-kWidth-kLocX); 302 | xLoc = (kScreenW-kHeight-kLocY); 303 | newTransform = CGAffineTransformMakeRotation(DegreesToRadians(90)); 304 | break; 305 | } 306 | case UIDeviceOrientationPortraitUpsideDown: { 307 | isLandscape = NO; 308 | yLoc = (kScreenH-kHeight-kLocY); 309 | xLoc = kLocX; 310 | newTransform = CGAffineTransformMakeRotation(DegreesToRadians(180)); 311 | break; 312 | } 313 | case UIDeviceOrientationPortrait: 314 | default: { 315 | isLandscape = NO; 316 | yLoc = kLocY; 317 | xLoc = (kScreenW-kWidth-kLocX); 318 | newTransform = CGAffineTransformMakeRotation(DegreesToRadians(0)); 319 | break; 320 | } 321 | } 322 | [UIView animateWithDuration:0.3f animations:^{ 323 | [springboardWindow setTransform:newTransform]; 324 | CGRect frame = springboardWindow.frame; 325 | frame.origin.y = yLoc; 326 | frame.origin.x = xLoc; 327 | springboardWindow.frame = frame; 328 | orientationOld = orientation; 329 | } completion:nil]; 330 | 331 | } @catch (NSException * e) { 332 | } 333 | } 334 | - (void)dalloc 335 | { 336 | return; 337 | } 338 | - (oneway void)release 339 | { 340 | return; 341 | } 342 | @end 343 | 344 | %hook SpringBoard 345 | - (void)applicationDidFinishLaunching:(id)application 346 | { 347 | %orig; 348 | [[[NtSpeed sharedInstance] retain] firstload]; 349 | } 350 | %end 351 | 352 | static void screenDisplayStatus(CFNotificationCenterRef center, void* observer, CFStringRef name, const void* object, CFDictionaryRef userInfo) 353 | { 354 | uint64_t state; 355 | int token; 356 | notify_register_check("com.apple.iokit.hid.displayStatus", &token); 357 | notify_get_state(token, &state); 358 | notify_cancel(token); 359 | if(!state) { 360 | isBlackScreen = YES; 361 | oldSpeed = 0; 362 | } else { 363 | isBlackScreen = NO; 364 | } 365 | } 366 | 367 | static void settingsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) 368 | { 369 | @autoreleasepool { 370 | NSDictionary *TweakPrefs = [[[NSDictionary alloc] initWithContentsOfFile:@PLIST_PATH_Settings]?:[NSDictionary dictionary] copy]; 371 | Enabled = (BOOL)[[TweakPrefs objectForKey:@"Enabled"]?:@YES boolValue]; 372 | alwaysVisible = (BOOL)[[TweakPrefs objectForKey:@"alwaysVisible"]?:@NO boolValue]; 373 | int newtextColor = (int)[[TweakPrefs objectForKey:@"textColor"]?:@(0) intValue]; 374 | int newkLocX = (int)[[TweakPrefs objectForKey:@"kLocX"]?:@(5) intValue]; 375 | int newkLocY = (int)[[TweakPrefs objectForKey:@"kLocY"]?:@(20) intValue]; 376 | int newkWidth = (int)[[TweakPrefs objectForKey:@"kWidth"]?:@(40) intValue]; 377 | int newkHeight = (int)[[TweakPrefs objectForKey:@"kHeight"]?:@(15) intValue]; 378 | float newkAlpha = (float)[[TweakPrefs objectForKey:@"kAlpha"]?:@(0.5) floatValue]; 379 | float newkAlphaText = (float)[[TweakPrefs objectForKey:@"kAlphaText"]?:@(0.9) floatValue]; 380 | float newkRadius = (float)[[TweakPrefs objectForKey:@"kRadius"]?:@(6) floatValue]; 381 | 382 | BOOL needUpdateUI = NO; 383 | if(newkLocX!=kLocX || newkLocY!=kLocY || newkWidth!=kWidth || newkHeight!=kHeight || newkAlpha!=kAlpha || newkRadius!=kRadius || newtextColor!=textColor || newkAlphaText!=kAlphaText) { 384 | needUpdateUI = YES; 385 | } 386 | kLocX = newkLocX; 387 | kLocY = newkLocY; 388 | kWidth = newkWidth; 389 | kHeight = newkHeight; 390 | kAlpha = newkAlpha; 391 | kRadius = newkRadius; 392 | textColor = newtextColor; 393 | kAlphaText = newkAlphaText; 394 | if(needUpdateUI && [NtSpeed sharedInstanceExist]) { 395 | if (NtSpeed* NTShared = [NtSpeed sharedInstance]) { 396 | [NTShared updateFrame]; 397 | } 398 | } 399 | } 400 | } 401 | 402 | %ctor 403 | { 404 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, screenDisplayStatus, CFSTR("com.apple.iokit.hid.displayStatus"), NULL, (CFNotificationSuspensionBehavior)0); 405 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, settingsChanged, CFSTR("com.julioverne.ntspeed/Settings"), NULL, CFNotificationSuspensionBehaviorCoalesce); 406 | settingsChanged(NULL, NULL, NULL, NULL, NULL); 407 | %init; 408 | } -------------------------------------------------------------------------------- /ntspeedsettings/NtSpeedSettingsController.mm: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | #define PLIST_PATH_Settings "/var/mobile/Library/Preferences/com.julioverne.ntspeed.plist" 6 | 7 | @interface NtSpeedSettingsController : PSListController { 8 | UILabel* _label; 9 | UILabel* underLabel; 10 | } 11 | - (void)HeaderCell; 12 | @end 13 | 14 | 15 | 16 | @implementation NtSpeedSettingsController 17 | - (id)specifiers { 18 | if (!_specifiers) { 19 | NSMutableArray* specifiers = [NSMutableArray array]; 20 | PSSpecifier* spec; 21 | spec = [PSSpecifier preferenceSpecifierNamed:@"Enabled" 22 | target:self 23 | set:@selector(setPreferenceValue:specifier:) 24 | get:@selector(readPreferenceValue:) 25 | detail:Nil 26 | cell:PSSwitchCell 27 | edit:Nil]; 28 | [spec setProperty:@"Enabled" forKey:@"key"]; 29 | [spec setProperty:@YES forKey:@"default"]; 30 | [specifiers addObject:spec]; 31 | spec = [PSSpecifier emptyGroupSpecifier]; 32 | [specifiers addObject:spec]; 33 | 34 | 35 | spec = [PSSpecifier preferenceSpecifierNamed:@"Always Visible" 36 | target:self 37 | set:@selector(setPreferenceValue:specifier:) 38 | get:@selector(readPreferenceValue:) 39 | detail:Nil 40 | cell:PSSwitchCell 41 | edit:Nil]; 42 | [spec setProperty:@"alwaysVisible" forKey:@"key"]; 43 | [spec setProperty:@NO forKey:@"default"]; 44 | [specifiers addObject:spec]; 45 | 46 | spec = [PSSpecifier preferenceSpecifierNamed:@"Text Color" 47 | target:self 48 | set:@selector(setPreferenceValue:specifier:) 49 | get:@selector(readPreferenceValue:) 50 | detail:PSListItemsController.class 51 | cell:PSLinkListCell 52 | edit:Nil]; 53 | [spec setProperty:@"textColor" forKey:@"key"]; 54 | [spec setProperty:@0 forKey:@"default"]; 55 | [spec setValues:@[@0, @1, @2, @3, @4, @5] titles:@[@"White", @"Black", @"Red", @"Green", @"Blue", @"Gray"]]; 56 | [specifiers addObject:spec]; 57 | 58 | spec = [PSSpecifier preferenceSpecifierNamed:@"Width" 59 | target:self 60 | set:Nil 61 | get:Nil 62 | detail:Nil 63 | cell:PSGroupCell 64 | edit:Nil]; 65 | [spec setProperty:@"Width" forKey:@"label"]; 66 | [specifiers addObject:spec]; 67 | spec = [PSSpecifier preferenceSpecifierNamed:@"Width" 68 | target:self 69 | set:@selector(setPreferenceValue:specifier:) 70 | get:@selector(readPreferenceValue:) 71 | detail:Nil 72 | cell:PSSliderCell 73 | edit:Nil]; 74 | [spec setProperty:@"kWidth" forKey:@"key"]; 75 | [spec setProperty:@(40) forKey:@"default"]; 76 | [spec setProperty:@0 forKey:@"min"]; 77 | [spec setProperty:@([[UIScreen mainScreen] bounds].size.width) forKey:@"max"]; 78 | [spec setProperty:@NO forKey:@"isContinuous"]; 79 | [spec setProperty:@YES forKey:@"showValue"]; 80 | [specifiers addObject:spec]; 81 | spec = [PSSpecifier preferenceSpecifierNamed:nil 82 | target:self 83 | set:@selector(setPreferenceValue:specifier:) 84 | get:@selector(readPreferenceValue:) 85 | detail:Nil 86 | cell:PSEditTextCell 87 | edit:Nil]; 88 | [spec setProperty:@"kWidth" forKey:@"key"]; 89 | [spec setProperty:@(40) forKey:@"default"]; 90 | [specifiers addObject:spec]; 91 | 92 | spec = [PSSpecifier preferenceSpecifierNamed:@"Height" 93 | target:self 94 | set:Nil 95 | get:Nil 96 | detail:Nil 97 | cell:PSGroupCell 98 | edit:Nil]; 99 | [spec setProperty:@"Height" forKey:@"label"]; 100 | [specifiers addObject:spec]; 101 | spec = [PSSpecifier preferenceSpecifierNamed:@"Height" 102 | target:self 103 | set:@selector(setPreferenceValue:specifier:) 104 | get:@selector(readPreferenceValue:) 105 | detail:Nil 106 | cell:PSSliderCell 107 | edit:Nil]; 108 | [spec setProperty:@"kHeight" forKey:@"key"]; 109 | [spec setProperty:@(15) forKey:@"default"]; 110 | [spec setProperty:@0 forKey:@"min"]; 111 | [spec setProperty:@([[UIScreen mainScreen] bounds].size.height) forKey:@"max"]; 112 | [spec setProperty:@NO forKey:@"isContinuous"]; 113 | [spec setProperty:@YES forKey:@"showValue"]; 114 | [specifiers addObject:spec]; 115 | spec = [PSSpecifier preferenceSpecifierNamed:nil 116 | target:self 117 | set:@selector(setPreferenceValue:specifier:) 118 | get:@selector(readPreferenceValue:) 119 | detail:Nil 120 | cell:PSEditTextCell 121 | edit:Nil]; 122 | [spec setProperty:@"kHeight" forKey:@"key"]; 123 | [spec setProperty:@(15) forKey:@"default"]; 124 | [specifiers addObject:spec]; 125 | 126 | spec = [PSSpecifier preferenceSpecifierNamed:@"Location X" 127 | target:self 128 | set:Nil 129 | get:Nil 130 | detail:Nil 131 | cell:PSGroupCell 132 | edit:Nil]; 133 | [spec setProperty:@"Location X" forKey:@"label"]; 134 | [specifiers addObject:spec]; 135 | spec = [PSSpecifier preferenceSpecifierNamed:@"Location X" 136 | target:self 137 | set:@selector(setPreferenceValue:specifier:) 138 | get:@selector(readPreferenceValue:) 139 | detail:Nil 140 | cell:PSSliderCell 141 | edit:Nil]; 142 | [spec setProperty:@"kLocX" forKey:@"key"]; 143 | [spec setProperty:@(5) forKey:@"default"]; 144 | [spec setProperty:@0 forKey:@"min"]; 145 | [spec setProperty:@([[UIScreen mainScreen] bounds].size.width) forKey:@"max"]; 146 | [spec setProperty:@NO forKey:@"isContinuous"]; 147 | [spec setProperty:@YES forKey:@"showValue"]; 148 | [specifiers addObject:spec]; 149 | spec = [PSSpecifier preferenceSpecifierNamed:nil 150 | target:self 151 | set:@selector(setPreferenceValue:specifier:) 152 | get:@selector(readPreferenceValue:) 153 | detail:Nil 154 | cell:PSEditTextCell 155 | edit:Nil]; 156 | [spec setProperty:@"kLocX" forKey:@"key"]; 157 | [spec setProperty:@(5) forKey:@"default"]; 158 | [specifiers addObject:spec]; 159 | 160 | spec = [PSSpecifier preferenceSpecifierNamed:@"Location Y" 161 | target:self 162 | set:Nil 163 | get:Nil 164 | detail:Nil 165 | cell:PSGroupCell 166 | edit:Nil]; 167 | [spec setProperty:@"Location Y" forKey:@"label"]; 168 | [specifiers addObject:spec]; 169 | spec = [PSSpecifier preferenceSpecifierNamed:@"Location Y" 170 | target:self 171 | set:@selector(setPreferenceValue:specifier:) 172 | get:@selector(readPreferenceValue:) 173 | detail:Nil 174 | cell:PSSliderCell 175 | edit:Nil]; 176 | [spec setProperty:@"kLocY" forKey:@"key"]; 177 | [spec setProperty:@(20) forKey:@"default"]; 178 | [spec setProperty:@0 forKey:@"min"]; 179 | [spec setProperty:@([[UIScreen mainScreen] bounds].size.height) forKey:@"max"]; 180 | [spec setProperty:@NO forKey:@"isContinuous"]; 181 | [spec setProperty:@YES forKey:@"showValue"]; 182 | [specifiers addObject:spec]; 183 | spec = [PSSpecifier preferenceSpecifierNamed:nil 184 | target:self 185 | set:@selector(setPreferenceValue:specifier:) 186 | get:@selector(readPreferenceValue:) 187 | detail:Nil 188 | cell:PSEditTextCell 189 | edit:Nil]; 190 | [spec setProperty:@"kLocY" forKey:@"key"]; 191 | [spec setProperty:@(20) forKey:@"default"]; 192 | [specifiers addObject:spec]; 193 | 194 | spec = [PSSpecifier preferenceSpecifierNamed:@"Radius" 195 | target:self 196 | set:Nil 197 | get:Nil 198 | detail:Nil 199 | cell:PSGroupCell 200 | edit:Nil]; 201 | [spec setProperty:@"Radius" forKey:@"label"]; 202 | [specifiers addObject:spec]; 203 | spec = [PSSpecifier preferenceSpecifierNamed:@"Radius" 204 | target:self 205 | set:@selector(setPreferenceValue:specifier:) 206 | get:@selector(readPreferenceValue:) 207 | detail:Nil 208 | cell:PSSliderCell 209 | edit:Nil]; 210 | [spec setProperty:@"kRadius" forKey:@"key"]; 211 | [spec setProperty:@6 forKey:@"default"]; 212 | [spec setProperty:@0 forKey:@"min"]; 213 | [spec setProperty:@50 forKey:@"max"]; 214 | [spec setProperty:@YES forKey:@"isContinuous"]; 215 | [spec setProperty:@YES forKey:@"showValue"]; 216 | [specifiers addObject:spec]; 217 | spec = [PSSpecifier preferenceSpecifierNamed:nil 218 | target:self 219 | set:@selector(setPreferenceValue:specifier:) 220 | get:@selector(readPreferenceValue:) 221 | detail:Nil 222 | cell:PSEditTextCell 223 | edit:Nil]; 224 | [spec setProperty:@"kRadius" forKey:@"key"]; 225 | [spec setProperty:@6 forKey:@"default"]; 226 | [specifiers addObject:spec]; 227 | 228 | spec = [PSSpecifier preferenceSpecifierNamed:@"Alpha Background" 229 | target:self 230 | set:Nil 231 | get:Nil 232 | detail:Nil 233 | cell:PSGroupCell 234 | edit:Nil]; 235 | [spec setProperty:@"Alpha Background" forKey:@"label"]; 236 | [specifiers addObject:spec]; 237 | spec = [PSSpecifier preferenceSpecifierNamed:@"Alpha Background" 238 | target:self 239 | set:@selector(setPreferenceValue:specifier:) 240 | get:@selector(readPreferenceValue:) 241 | detail:Nil 242 | cell:PSSliderCell 243 | edit:Nil]; 244 | [spec setProperty:@"kAlpha" forKey:@"key"]; 245 | [spec setProperty:@(0.5) forKey:@"default"]; 246 | [spec setProperty:@(0.0) forKey:@"min"]; 247 | [spec setProperty:@(1.0) forKey:@"max"]; 248 | [spec setProperty:@YES forKey:@"isContinuous"]; 249 | [spec setProperty:@YES forKey:@"showValue"]; 250 | [specifiers addObject:spec]; 251 | spec = [PSSpecifier preferenceSpecifierNamed:nil 252 | target:self 253 | set:@selector(setPreferenceValue:specifier:) 254 | get:@selector(readPreferenceValue:) 255 | detail:Nil 256 | cell:PSEditTextCell 257 | edit:Nil]; 258 | [spec setProperty:@"kAlpha" forKey:@"key"]; 259 | [spec setProperty:@(0.5) forKey:@"default"]; 260 | [specifiers addObject:spec]; 261 | 262 | spec = [PSSpecifier preferenceSpecifierNamed:@"Alpha Text" 263 | target:self 264 | set:Nil 265 | get:Nil 266 | detail:Nil 267 | cell:PSGroupCell 268 | edit:Nil]; 269 | [spec setProperty:@"Alpha Text" forKey:@"label"]; 270 | [specifiers addObject:spec]; 271 | spec = [PSSpecifier preferenceSpecifierNamed:@"Alpha Text" 272 | target:self 273 | set:@selector(setPreferenceValue:specifier:) 274 | get:@selector(readPreferenceValue:) 275 | detail:Nil 276 | cell:PSSliderCell 277 | edit:Nil]; 278 | [spec setProperty:@"kAlphaText" forKey:@"key"]; 279 | [spec setProperty:@(0.9) forKey:@"default"]; 280 | [spec setProperty:@(0.0) forKey:@"min"]; 281 | [spec setProperty:@(1.0) forKey:@"max"]; 282 | [spec setProperty:@YES forKey:@"isContinuous"]; 283 | [spec setProperty:@YES forKey:@"showValue"]; 284 | [specifiers addObject:spec]; 285 | spec = [PSSpecifier preferenceSpecifierNamed:nil 286 | target:self 287 | set:@selector(setPreferenceValue:specifier:) 288 | get:@selector(readPreferenceValue:) 289 | detail:Nil 290 | cell:PSEditTextCell 291 | edit:Nil]; 292 | [spec setProperty:@"kAlphaText" forKey:@"key"]; 293 | [spec setProperty:@(0.9) forKey:@"default"]; 294 | [specifiers addObject:spec]; 295 | 296 | 297 | spec = [PSSpecifier emptyGroupSpecifier]; 298 | [specifiers addObject:spec]; 299 | spec = [PSSpecifier preferenceSpecifierNamed:@"Reset Settings" 300 | target:self 301 | set:NULL 302 | get:NULL 303 | detail:Nil 304 | cell:PSLinkCell 305 | edit:Nil]; 306 | spec->action = @selector(reset); 307 | [specifiers addObject:spec]; 308 | spec = [PSSpecifier preferenceSpecifierNamed:@"Developer" 309 | target:self 310 | set:Nil 311 | get:Nil 312 | detail:Nil 313 | cell:PSGroupCell 314 | edit:Nil]; 315 | [spec setProperty:@"Developer" forKey:@"label"]; 316 | [specifiers addObject:spec]; 317 | spec = [PSSpecifier preferenceSpecifierNamed:@"Follow julioverne" 318 | target:self 319 | set:NULL 320 | get:NULL 321 | detail:Nil 322 | cell:PSLinkCell 323 | edit:Nil]; 324 | spec->action = @selector(twitter); 325 | [spec setProperty:[NSNumber numberWithBool:TRUE] forKey:@"hasIcon"]; 326 | [spec setProperty:[UIImage imageWithContentsOfFile:[[self bundle] pathForResource:@"twitter" ofType:@"png"]] forKey:@"iconImage"]; 327 | [specifiers addObject:spec]; 328 | spec = [PSSpecifier emptyGroupSpecifier]; 329 | [spec setProperty:@"NtSpeed © 2021" forKey:@"footerText"]; 330 | [specifiers addObject:spec]; 331 | _specifiers = [specifiers copy]; 332 | } 333 | return _specifiers; 334 | } 335 | - (void)twitter 336 | { 337 | UIApplication *app = [UIApplication sharedApplication]; 338 | if ([app canOpenURL:[NSURL URLWithString:@"twitter://user?screen_name=ijulioverne"]]) { 339 | [app openURL:[NSURL URLWithString:@"twitter://user?screen_name=ijulioverne"]]; 340 | } else if ([app canOpenURL:[NSURL URLWithString:@"tweetbot:///user_profile/ijulioverne"]]) { 341 | [app openURL:[NSURL URLWithString:@"tweetbot:///user_profile/ijulioverne"]]; 342 | } else { 343 | [app openURL:[NSURL URLWithString:@"https://mobile.twitter.com/ijulioverne"]]; 344 | } 345 | } 346 | - (void)love 347 | { 348 | SLComposeViewController *twitter = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter]; 349 | [twitter setInitialText:@"#NtSpeed by @ijulioverne is cool!"]; 350 | if (twitter != nil) { 351 | [[self navigationController] presentViewController:twitter animated:YES completion:nil]; 352 | } 353 | } 354 | - (void)reset 355 | { 356 | [@{} writeToFile:@PLIST_PATH_Settings atomically:YES]; 357 | [self reloadSpecifiers]; 358 | [self showPrompt]; 359 | notify_post("com.julioverne.ntspeed/Settings"); 360 | } 361 | 362 | - (void)showPrompt 363 | { 364 | if(objc_getClass("UIAlertController")!=nil) { 365 | UIAlertController* alert = [objc_getClass("UIAlertController") alertControllerWithTitle:self.title message:@"An Respring is Requerid for this option." preferredStyle:UIAlertControllerStyleAlert]; 366 | UIAlertAction* defaultAction = [objc_getClass("UIAlertAction") actionWithTitle:@"Respring" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { 367 | system("killall backboardd SpringBoard"); 368 | }]; 369 | [alert addAction:defaultAction]; 370 | UIAlertAction* defaultActionCancel = [objc_getClass("UIAlertAction") actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:nil]; 371 | [alert addAction:defaultActionCancel]; 372 | [self presentViewController:alert animated:YES completion:nil]; 373 | } else { 374 | UIAlertView *alert = [[objc_getClass("UIAlertView") alloc] initWithTitle:self.title message:@"An Respring is Requerid for this option." delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Respring", nil]; 375 | alert.tag = 55; 376 | [alert show]; 377 | } 378 | } 379 | 380 | - (void)reloadSpec 381 | { 382 | [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_reloadSpec) object:nil]; 383 | [self performSelector:@selector(_reloadSpec) withObject:nil afterDelay:0.5f]; 384 | } 385 | 386 | - (void)_reloadSpec 387 | { 388 | [self reloadSpecifiers]; 389 | } 390 | 391 | - (void)setPreferenceValue:(id)value specifier:(PSSpecifier *)specifier 392 | { 393 | @autoreleasepool { 394 | NSMutableDictionary *CydiaEnablePrefsCheck = [[NSMutableDictionary alloc] initWithContentsOfFile:@PLIST_PATH_Settings]?:[NSMutableDictionary dictionary]; 395 | 396 | NSString* keyVal = [specifier identifier]; 397 | id val = value; 398 | 399 | if([keyVal hasSuffix:@".0"]) { 400 | keyVal = [keyVal substringToIndex:[keyVal length]-2]; 401 | val = @([(NSString*)val doubleValue]); 402 | } 403 | 404 | [CydiaEnablePrefsCheck setObject:val forKey:keyVal]; 405 | [CydiaEnablePrefsCheck writeToFile:@PLIST_PATH_Settings atomically:YES]; 406 | notify_post("com.julioverne.ntspeed/Settings"); 407 | if ([[specifier properties] objectForKey:@"PromptRespring"]) { 408 | [self showPrompt]; 409 | } 410 | 411 | [self reloadSpec]; 412 | } 413 | } 414 | - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex 415 | { 416 | if (alertView.tag == 55 && buttonIndex == 1) { 417 | system("killall backboardd SpringBoard"); 418 | } 419 | } 420 | - (id)readPreferenceValue:(PSSpecifier*)specifier 421 | { 422 | @autoreleasepool { 423 | 424 | NSString* keyVal = [specifier identifier]; 425 | 426 | if([keyVal hasSuffix:@".0"]) { 427 | keyVal = [keyVal substringToIndex:[keyVal length]-2]; 428 | } 429 | 430 | NSDictionary *CydiaEnablePrefsCheck = [[NSDictionary alloc] initWithContentsOfFile:@PLIST_PATH_Settings]; 431 | return CydiaEnablePrefsCheck[keyVal]?:[[specifier properties] objectForKey:@"default"]; 432 | } 433 | } 434 | - (void)_returnKeyPressed:(id)arg1 435 | { 436 | [super _returnKeyPressed:arg1]; 437 | [self.view endEditing:YES]; 438 | } 439 | 440 | - (void)HeaderCell 441 | { 442 | @autoreleasepool { 443 | UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 120)]; 444 | int width = [[UIScreen mainScreen] bounds].size.width; 445 | CGRect frame = CGRectMake(0, 20, width, 60); 446 | CGRect botFrame = CGRectMake(0, 55, width, 60); 447 | 448 | _label = [[UILabel alloc] initWithFrame:frame]; 449 | [_label setNumberOfLines:1]; 450 | _label.font = [UIFont fontWithName:@"HelveticaNeue-UltraLight" size:48]; 451 | [_label setText:self.title]; 452 | [_label setBackgroundColor:[UIColor clearColor]]; 453 | //_label.textColor = [UIColor blackColor]; 454 | _label.textAlignment = NSTextAlignmentCenter; 455 | _label.alpha = 0; 456 | 457 | underLabel = [[UILabel alloc] initWithFrame:botFrame]; 458 | [underLabel setNumberOfLines:1]; 459 | underLabel.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:14]; 460 | [underLabel setText:@"See Active Network Speed"]; 461 | [underLabel setBackgroundColor:[UIColor clearColor]]; 462 | underLabel.textColor = [UIColor grayColor]; 463 | underLabel.textAlignment = NSTextAlignmentCenter; 464 | underLabel.alpha = 0; 465 | 466 | [headerView addSubview:_label]; 467 | [headerView addSubview:underLabel]; 468 | 469 | [_table setTableHeaderView:headerView]; 470 | 471 | [NSTimer scheduledTimerWithTimeInterval:0.5 472 | target:self 473 | selector:@selector(increaseAlpha) 474 | userInfo:nil 475 | repeats:NO]; 476 | 477 | } 478 | } 479 | - (void) loadView 480 | { 481 | [super loadView]; 482 | self.title = @"NtSpeed"; 483 | [UISwitch appearanceWhenContainedIn:self.class, nil].onTintColor = [UIColor colorWithRed:0.09 green:0.99 blue:0.99 alpha:1.0]; 484 | UIButton *heart = [[UIButton alloc] initWithFrame:CGRectZero]; 485 | [heart setImage:[[UIImage alloc] initWithContentsOfFile:[[self bundle] pathForResource:@"Heart" ofType:@"png"]] forState:UIControlStateNormal]; 486 | [heart sizeToFit]; 487 | [heart addTarget:self action:@selector(love) forControlEvents:UIControlEventTouchUpInside]; 488 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:heart]; 489 | [self HeaderCell]; 490 | } 491 | - (void)increaseAlpha 492 | { 493 | [UIView animateWithDuration:0.5 animations:^{ 494 | _label.alpha = 1; 495 | }completion:^(BOOL finished) { 496 | [UIView animateWithDuration:0.5 animations:^{ 497 | underLabel.alpha = 1; 498 | }completion:nil]; 499 | }]; 500 | } 501 | @end --------------------------------------------------------------------------------