├── .gitignore ├── Makefile ├── README.md ├── SB-IconHeaders.h ├── Tweak.h ├── Tweak.xm ├── WGWeatherIconImageView.xm ├── WeatherGround.plist ├── WeatherGroundManager.h ├── WeatherGroundManager.xm ├── WeatherHeaders.h ├── control ├── packages ├── com.tr1fecta.weatherground_1.1_iphoneos-arm.deb ├── com.tr1fecta.weatherground_1.2_iphoneos-arm.deb ├── com.tr1fecta.weatherground_1.3_iphoneos-arm.deb └── com.tr1fecta.weatherground_1.4_iphoneos-arm.deb └── wgprefs ├── Makefile ├── Resources ├── Info.plist └── Root.plist ├── WGPRootListController.h ├── WGPRootListController.m └── entry.plist /.gitignore: -------------------------------------------------------------------------------- 1 | .theos 2 | .DS_Store -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | export TARGET = iphone:clang:13.3:11.0 2 | ARCHS = arm64 arm64e 3 | 4 | include $(THEOS)/makefiles/common.mk 5 | 6 | TWEAK_NAME = WeatherGround 7 | 8 | WeatherGround_FILES = $(wildcard *.xm) 9 | WeatherGround_CFLAGS = -fobjc-arc -Wno-unguarded-availability-new 10 | WeatherGround_PRIVATE_FRAMEWORKS = SpringBoardFoundation Weather WeatherUI 11 | WeatherGround_LDFLAGS = $(THEOS)/sdks/iPhoneOS13.3.sdk/System/Library/PrivateFrameworks/WeatherUI.framework/WeatherUI.tbd 12 | 13 | 14 | include $(THEOS_MAKE_PATH)/tweak.mk 15 | SUBPROJECTS += wgprefs 16 | include $(THEOS_MAKE_PATH)/aggregate.mk 17 | 18 | after-install:: 19 | install.exec "sbreload" 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WeatherGround 2 | 3 | ![image](https://github.com/Tr1Fecta-7/WeatherGround/assets/53660999/3671e4c3-9185-43a0-b9e2-31fa2bb0825d) 4 | ![image](https://github.com/Tr1Fecta-7/WeatherGround/assets/53660999/e19cb16e-bc7a-46ce-bebd-85d0ab48ea97) 5 | ![image](https://github.com/Tr1Fecta-7/WeatherGround/assets/53660999/305c4382-2bee-430d-b74a-258a75c5c49c) 6 | ![image](https://github.com/Tr1Fecta-7/WeatherGround/assets/53660999/97d3286e-6a50-454c-b321-250c59312759) 7 | 8 | WeatherGround is a tweak that brings weather to your fingertips! 9 | 10 | WeatherGround offers 3 (+ bonus) features currently: 11 | 12 | - Live weather background as wallpaper! 13 | - Live weather effects on top of your current wallpaper 14 | - Tapping on the time in status bar to see the current temperature! 15 | - (BONUS) If you have 2 different wallpapers, you can enable/disable the background or effect for the homescreen and lockscreen separately 16 | 17 | **The tweak only fully works on iPhones (X device recommended), iPads do not support the wallpaper features** 18 | **Supports iOS 13.0 to 14.6** 19 | 20 | 21 | Credits to @NSExceptional for the wallpaper idea and the info needed to make that feature possible. 22 | -------------------------------------------------------------------------------- /SB-IconHeaders.h: -------------------------------------------------------------------------------- 1 | #import "WeatherHeaders.h" 2 | 3 | @interface SBIcon : NSObject 4 | @end 5 | 6 | @interface SBLeafIcon : SBIcon 7 | @property (nonatomic,copy,readonly) NSString *applicationBundleID; 8 | @end 9 | 10 | @interface SBApplicationIcon : SBLeafIcon 11 | @end 12 | 13 | @interface SBIconView : UIView 14 | @property (nonatomic,retain) SBIcon *icon; 15 | @property (nonatomic, retain) WATodayAutoupdatingLocationModel *todayUpdateModel; 16 | @property (nonatomic, strong) WUIDynamicWeatherBackground *bgView; 17 | @property (nonatomic, strong) City *myCity; 18 | 19 | - (void)setupNewIconView; 20 | - (void)setupModelAndUpdate; 21 | - (void)setupDynamicWeatherBackgroundView; 22 | - (void)setupWeatherGradientLayer; 23 | - (void)setupWeatherIconImageView; 24 | @end 25 | 26 | 27 | @interface SBIconImageView : UIView 28 | @property (nonatomic,readonly) SBIcon * icon; 29 | @property (assign,nonatomic) SBIconView * iconView; 30 | 31 | // %new 32 | @property (nonatomic, retain) WATodayAutoupdatingLocationModel *todayUpdateModel; 33 | @property (nonatomic, strong) WUIDynamicWeatherBackground *bgView; 34 | @property (nonatomic, strong) City *myCity; 35 | @property (nonatomic, strong) UIImageView *weatherIconImageView; 36 | 37 | 38 | - (id)initWithFrame:(CGRect)arg1; 39 | - (void)updateImageAnimated:(BOOL)arg1; 40 | - (void)prepareForReuse; 41 | 42 | - (void)setupNewWeatherIconView; 43 | - (void)setupModelAndUpdate; 44 | - (void)setupDynamicWeatherBackgroundView; 45 | - (void)setupWeatherGradientLayer; 46 | - (void)setupWeatherIconImageView; 47 | @end 48 | -------------------------------------------------------------------------------- /Tweak.h: -------------------------------------------------------------------------------- 1 | #include "WeatherHeaders.h" 2 | #include "SB-IconHeaders.h" 3 | #include "WeatherGroundManager.h" 4 | #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) -------------------------------------------------------------------------------- /Tweak.xm: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Tweak.h" 4 | 5 | BOOL kTweakEnabled; 6 | BOOL kUseEntireWeatherView; 7 | BOOL kUseWeatherEffectsOnly; 8 | BOOL kEnableStatusBarTemperature; 9 | BOOL kLockscreenEnabled; 10 | BOOL kHomescreenEnabled; 11 | NSString *kTemperatureUnit; 12 | 13 | %group TimeStatusBar 14 | 15 | %hook _UIStatusBarStringView 16 | 17 | - (instancetype)initWithFrame:(CGRect)frame { 18 | if ((self = %orig)) { 19 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setTemperatureWithNotification:) name:@"wgSetTemperatureNotification" object:nil]; 20 | } 21 | return self; 22 | } 23 | 24 | - (void)didMoveToWindow { 25 | %orig; 26 | 27 | if ([[self _viewControllerForAncestor] isKindOfClass:%c(SBMainDisplaySceneLayoutViewController)] && kEnableStatusBarTemperature) { 28 | // Set the status string view for the status bar in apps 29 | [[WeatherGroundManager sharedManager] setStatusStringView:self]; 30 | } 31 | } 32 | 33 | %new 34 | - (void)setTemperatureWithNotification:(NSNotification *)notification { 35 | if ([notification.name isEqualToString:@"wgSetTemperatureNotification"]) { 36 | NSMutableAttributedString *temperatureAttrString = [[[WeatherGroundManager sharedManager] temperatureInfo:kTemperatureUnit] objectForKey:@"weatherString"]; 37 | [self changeLabelTextWithAttributedString:temperatureAttrString]; 38 | 39 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 40 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 41 | [formatter setLocale:[NSLocale currentLocale]]; 42 | [formatter setTimeStyle:NSDateFormatterShortStyle]; 43 | 44 | NSRange amRange = [[formatter stringFromDate:[NSDate now]] rangeOfString:[formatter AMSymbol]]; 45 | NSRange pmRange = [[formatter stringFromDate:[NSDate now]] rangeOfString:[formatter PMSymbol]]; 46 | 47 | BOOL is24h = (amRange.location == NSNotFound && pmRange.location == NSNotFound); 48 | 49 | [formatter setDateFormat:is24h ? @"HH:mm" : @"hh:mm"]; 50 | 51 | NSString *currentStatusTime = [formatter stringFromDate:[NSDate now]]; 52 | 53 | self.attributedText = nil; 54 | [self changeLabelText:currentStatusTime]; 55 | }); 56 | } 57 | } 58 | 59 | %new 60 | - (void)changeLabelTextWithAttributedString:(NSMutableAttributedString *)text { 61 | CATransition *animation = [CATransition animation]; 62 | animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 63 | animation.type = kCATransitionPush; 64 | animation.subtype = kCATransitionFromTop; 65 | animation.duration = 0.3; 66 | [self.layer addAnimation:animation forKey:@"kCATransitionPush"]; 67 | 68 | self.attributedText = text; 69 | } 70 | 71 | %new 72 | - (void)changeLabelText:(NSString *)text { 73 | CATransition *animation = [CATransition animation]; 74 | animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 75 | animation.type = kCATransitionPush; 76 | animation.subtype = kCATransitionFromTop; 77 | animation.duration = 0.3; 78 | [self.layer addAnimation:animation forKey:@"kCATransitionPush"]; 79 | 80 | self.text = text; 81 | } 82 | 83 | %end 84 | 85 | %hook _UIStatusBarForegroundView 86 | 87 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 88 | %orig; 89 | CGPoint location = [[[event allTouches] anyObject] locationInView:self]; 90 | if (location.x <= 105.0) { 91 | if (kEnableStatusBarTemperature) { 92 | // Handled in SpringBoard 93 | [[NSNotificationCenter defaultCenter] postNotificationName:@"wgSetTemperatureNotification" object:nil userInfo:nil]; 94 | } 95 | } 96 | } 97 | 98 | %end 99 | 100 | %hook SBMainDisplaySceneLayoutStatusBarView 101 | // Handled in applications 102 | -(void)_statusBarTapped:(UITapGestureRecognizer *)tapAction type:(long long)arg2 { 103 | %orig; 104 | 105 | _UIStatusBar *statusBar = [self safeValueForKey:@"_statusBarUnderlyingViewAccessor"]; 106 | 107 | if (statusBar && statusBar.foregroundView) { 108 | CGPoint location = [tapAction locationInView:statusBar.foregroundView]; 109 | if (location.x <= 105.0) { 110 | if (kEnableStatusBarTemperature) { 111 | [[NSNotificationCenter defaultCenter] postNotificationName:@"wgSetTemperatureNotification" object:nil userInfo:nil]; 112 | } 113 | } 114 | } 115 | 116 | } 117 | 118 | %end 119 | 120 | %end // End of TimeStatusBar 121 | 122 | %hook SBFWallpaperView 123 | 124 | -(void)didMoveToWindow { 125 | %orig; 126 | 127 | if (kUseEntireWeatherView && [[WeatherGroundManager sharedManager] sharedImage] != nil) { 128 | if ((kHomescreenEnabled && [self.variantCacheIdentifier isEqualToString:@"home"]) || (kLockscreenEnabled && [self.variantCacheIdentifier isEqualToString:@"lock"]) || (!kHomescreenEnabled && !kLockscreenEnabled)) { 129 | if ([((UIImageView *)self.contentView) respondsToSelector:@selector(setImage:)]) { 130 | ((UIImageView *)self.contentView).image = [[WeatherGroundManager sharedManager] sharedImage]; 131 | } 132 | } 133 | } 134 | } 135 | 136 | %end 137 | 138 | %hook LockScreenVC 139 | 140 | -(void)viewDidLoad { 141 | %orig; 142 | 143 | // Setup the dynamic views and effect layers 144 | [[WeatherGroundManager sharedManager] updateModel]; 145 | [[WeatherGroundManager sharedManager] setupDynamicWeatherBackgrounds]; 146 | [[WeatherGroundManager sharedManager] setupWeatherEffectLayers]; 147 | 148 | } 149 | 150 | %end 151 | 152 | %hook SpringBoard 153 | 154 | - (void)frontDisplayDidChange:(SBApplication *)application { 155 | %orig; 156 | 157 | if (kTweakEnabled) { 158 | // If the display changed to an app, pause the view and resume it when in SpringBoard 159 | if (application) { 160 | [[WeatherGroundManager sharedManager] pauseWG]; 161 | } else { 162 | [[WeatherGroundManager sharedManager] resumeWG]; 163 | } 164 | } 165 | 166 | } 167 | 168 | %end 169 | 170 | 171 | static void updateWGState(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { 172 | [[WeatherGroundManager sharedManager] updateModel]; 173 | 174 | BOOL screenOn = [[[%c(SBLockScreenManager) sharedInstance] safeValueForKey:@"_isScreenOn"] boolValue]; 175 | if (screenOn) { 176 | [[WeatherGroundManager sharedManager] resumeWG]; 177 | } else { 178 | [[WeatherGroundManager sharedManager] pauseWG]; 179 | } 180 | } 181 | 182 | 183 | %ctor { 184 | NSBundle *wUIBundle = [NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/WeatherUI.framework"]; 185 | NSBundle *wBundle = [NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/Weather.framework"]; 186 | if (!wUIBundle.loaded) { 187 | [wUIBundle load]; 188 | } 189 | if (!wBundle.loaded) { 190 | [wBundle load]; 191 | } 192 | 193 | NSDictionary *plistDict = [NSDictionary dictionaryWithContentsOfFile:@"/var/mobile/Library/Preferences/com.tr1fecta.wgprefs.plist"]; 194 | if (plistDict != nil) { 195 | kTweakEnabled = [plistDict objectForKey:@"kTweakEnabled"] ? [[plistDict objectForKey:@"kTweakEnabled"] boolValue] : NO; 196 | kUseEntireWeatherView = [plistDict objectForKey:@"kUseEntireWeatherView"] ? [[plistDict objectForKey:@"kUseEntireWeatherView"] boolValue] : NO; 197 | kUseWeatherEffectsOnly = [plistDict objectForKey:@"kUseWeatherEffectsOnly"] ? [[plistDict objectForKey:@"kUseWeatherEffectsOnly"] boolValue] : NO; 198 | 199 | kLockscreenEnabled = [plistDict objectForKey:@"kLockscreenEnabled"] ? [[plistDict objectForKey:@"kLockscreenEnabled"] boolValue] : NO; 200 | kHomescreenEnabled = [plistDict objectForKey:@"kHomescreenEnabled"] ? [[plistDict objectForKey:@"kHomescreenEnabled"] boolValue] : NO; 201 | 202 | kEnableStatusBarTemperature = [plistDict objectForKey:@"kEnableStatusBarTemperature"] ? [[plistDict objectForKey:@"kEnableStatusBarTemperature"] boolValue] : NO; 203 | kTemperatureUnit = [plistDict objectForKey:@"kTemperatureUnit"] ? [[plistDict objectForKey:@"kTemperatureUnit"] stringValue] : @"celsius"; 204 | 205 | if (kTweakEnabled) { 206 | if (kEnableStatusBarTemperature) { 207 | %init(TimeStatusBar); 208 | } 209 | 210 | Class LockScreenVCClass; 211 | if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"13.0")) { 212 | LockScreenVCClass = %c(CSCoverSheetViewController); 213 | } else { 214 | LockScreenVCClass = %c(SBDashBoardViewController); 215 | } 216 | %init(LockScreenVC=LockScreenVCClass); 217 | 218 | [WeatherGroundManager sharedManager]; 219 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, updateWGState, CFSTR("com.apple.springboard.screenchanged"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); 220 | } 221 | } 222 | } -------------------------------------------------------------------------------- /WGWeatherIconImageView.xm: -------------------------------------------------------------------------------- 1 | #import "Tweak.h" 2 | 3 | // Will come later 4 | /* 5 | %subclass WGWeatherIconImageView : SBIconImageView 6 | 7 | - (instancetype)initWithFrame:(CGRect)frame { 8 | if ((self = %orig)) { 9 | 10 | } 11 | return self; 12 | } 13 | 14 | 15 | %end*/ -------------------------------------------------------------------------------- /WeatherGround.plist: -------------------------------------------------------------------------------- 1 | { Filter = { Bundles = ( "com.apple.springboard"); }; } 2 | -------------------------------------------------------------------------------- /WeatherGroundManager.h: -------------------------------------------------------------------------------- 1 | #import "Tweak.h" 2 | 3 | @interface WeatherGroundManager : NSObject 4 | 5 | 6 | @property (nonatomic, strong) WUIDynamicWeatherBackground *lockScreenBgView; 7 | @property (nonatomic, strong) WUIDynamicWeatherBackground *homeScreenBgView; 8 | @property (nonatomic, strong) WUIDynamicWeatherBackground *sharedBgView; 9 | 10 | @property (nonatomic, strong) UIImage *sharedImage; 11 | @property (nonatomic, strong) NSDictionary *preferencesDictionary; 12 | 13 | @property (nonatomic, strong) WALockscreenWidgetViewController *widgetVC; 14 | @property (nonatomic, strong) City *myCity; 15 | @property (nonatomic, strong) NSTimer *autoUpdateTimer; 16 | 17 | @property (nonatomic, strong) _UIStatusBarStringView *statusStringView; // In Apps 18 | 19 | + (instancetype)sharedManager; 20 | 21 | 22 | - (void)setStatusBarTextToWeatherInfo:(NSDictionary *)infoDict; 23 | - (void)changeLabelTextWithAttributedString:(NSMutableAttributedString *)text; 24 | - (void)updateModel; 25 | - (void)setSharedImageWithView:(WUIDynamicWeatherBackground *)backgroundView; 26 | 27 | - (void)setupDynamicWeatherBackgrounds; 28 | - (void)setupWeatherEffectLayers; 29 | 30 | - (void)pauseWG; 31 | - (void)resumeWG; 32 | 33 | - (BOOL)boolForKey:(NSString *)key; 34 | - (int)intForKey:(NSString *)key; 35 | 36 | - (CALayer *)weatherEffectsLayerForWeatherView:(WUIDynamicWeatherBackground *)weatherView; 37 | - (void)updateCityForCity:(City *)city; 38 | - (NSDictionary *)temperatureInfo:(NSString *)unit; 39 | - (int)currentConditionCode; 40 | - (UIImage *)getImageForCondition:(NSInteger)conditionCode style:(int)style; 41 | - (NSMutableAttributedString *)stringForWeatherImage:(UIImage *)weatherImg withPrefix:(NSString *)prefixString; 42 | @end 43 | -------------------------------------------------------------------------------- /WeatherGroundManager.xm: -------------------------------------------------------------------------------- 1 | #import "WeatherGroundManager.h" 2 | #include 3 | 4 | @implementation WeatherGroundManager 5 | 6 | - (BOOL)boolForKey:(NSString *)key { 7 | id object = [self.preferencesDictionary objectForKey:key]; 8 | return object ? [object boolValue] : NO; 9 | } 10 | 11 | - (int)intForKey:(NSString *)key { 12 | id object = [self.preferencesDictionary objectForKey:key]; 13 | return object ? [object intValue] : 0; 14 | } 15 | 16 | + (instancetype)sharedManager { 17 | static dispatch_once_t onceToken = 0; 18 | __strong static WeatherGroundManager *sharedManager = nil; 19 | dispatch_once(&onceToken, ^{ 20 | sharedManager = [[self alloc] init]; 21 | }); 22 | return sharedManager; 23 | } 24 | 25 | - (instancetype)init { 26 | self = [super init]; 27 | if (self) { 28 | _preferencesDictionary = [NSDictionary dictionaryWithContentsOfFile:@"/var/mobile/Library/Preferences/com.tr1fecta.wgprefs.plist"]; 29 | 30 | // Convert to minutes from seconds 31 | double interval = (double)[self intForKey:@"kAutoUpdateInterval"] * 60; 32 | if (interval > 0) { 33 | _autoUpdateTimer = [NSTimer scheduledTimerWithTimeInterval:interval target:self selector:@selector(updateModel) userInfo:nil repeats:YES]; 34 | } 35 | 36 | } 37 | return self; 38 | } 39 | 40 | // In Apps 41 | - (void)setStatusBarTextToWeatherInfo:(NSDictionary *)infoDict { 42 | if (self.statusStringView != nil) { 43 | NSMutableAttributedString *temperatureAttrString = [[self temperatureInfo:infoDict[@"unit"]] objectForKey:@"weatherString"]; 44 | self.statusStringView.attributedText = temperatureAttrString; 45 | [self changeLabelTextWithAttributedString:temperatureAttrString]; 46 | 47 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 48 | NSDateFormatter *formatter = [NSDateFormatter new]; 49 | formatter.timeZone = [NSTimeZone localTimeZone]; 50 | formatter.dateFormat = @"HH:mm"; 51 | NSString *currentStatusTime = [formatter stringFromDate:[NSDate now]]; 52 | 53 | self.statusStringView.attributedText = nil; 54 | [self changeLabelText:currentStatusTime]; 55 | }); 56 | } 57 | } 58 | 59 | - (void)changeLabelTextWithAttributedString:(NSMutableAttributedString *)text { 60 | CATransition *animation = [CATransition animation]; 61 | animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 62 | animation.type = kCATransitionPush; 63 | animation.subtype = kCATransitionFromTop; 64 | animation.duration = 0.3; 65 | [self.statusStringView.layer addAnimation:animation forKey:@"kCATransitionPush"]; 66 | 67 | self.statusStringView.attributedText = text; 68 | } 69 | 70 | - (void)changeLabelText:(NSString *)text { 71 | CATransition *animation = [CATransition animation]; 72 | animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 73 | animation.type = kCATransitionPush; 74 | animation.subtype = kCATransitionFromTop; 75 | animation.duration = 0.3; 76 | [self.statusStringView.layer addAnimation:animation forKey:@"kCATransitionPush"]; 77 | 78 | self.statusStringView.text = text; 79 | } 80 | 81 | - (void)setupDynamicWeatherBackgrounds { 82 | SBWallpaperController *wallpaperController = [%c(SBWallpaperController) sharedInstance]; 83 | SBFWallpaperView *sharedWallpaperView; 84 | SBFWallpaperView *lockscreenWallpaperView; 85 | SBFWallpaperView *homescreenWallpaperView; 86 | 87 | if (%c(SBWallpaperViewController)) { 88 | SBWallpaperViewController *wallpaperViewController = [wallpaperController valueForKey:@"_wallpaperViewController"]; 89 | 90 | sharedWallpaperView = wallpaperViewController.sharedWallpaperView; 91 | 92 | lockscreenWallpaperView = wallpaperViewController.lockscreenWallpaperView; 93 | homescreenWallpaperView = wallpaperViewController.homescreenWallpaperView; 94 | } 95 | else { 96 | sharedWallpaperView = wallpaperController.sharedWallpaperView; 97 | 98 | lockscreenWallpaperView = wallpaperController.lockscreenWallpaperView; 99 | homescreenWallpaperView = wallpaperController.homescreenWallpaperView; 100 | } 101 | 102 | // Always create this instance for the weather effects layer, but only add if enabled 103 | self.sharedBgView = [[%c(WUIDynamicWeatherBackground) alloc] initWithFrame:UIScreen.mainScreen.bounds]; 104 | self.sharedBgView.city = [self myCity]; 105 | self.sharedBgView.condition.city = [self myCity]; 106 | if (sharedWallpaperView != nil && [self boolForKey:@"kUseEntireWeatherView"] && [self boolForKey:@"kUseWeatherEffectsOnly"] == NO) { 107 | [sharedWallpaperView addSubview:self.sharedBgView]; 108 | 109 | [self setSharedImageWithView:self.sharedBgView]; 110 | } 111 | 112 | // Check if the user is using 2 different wallpapers 113 | if (lockscreenWallpaperView != nil && homescreenWallpaperView != nil && sharedWallpaperView == nil) { 114 | if ([self boolForKey:@"kLockscreenEnabled"]) { 115 | self.lockScreenBgView = [[%c(WUIDynamicWeatherBackground) alloc] initWithFrame:UIScreen.mainScreen.bounds]; 116 | self.lockScreenBgView.city = [self myCity]; 117 | self.lockScreenBgView.condition.city = [self myCity]; 118 | 119 | if ([self boolForKey:@"kUseEntireWeatherView"]) { 120 | [lockscreenWallpaperView addSubview:self.lockScreenBgView]; 121 | 122 | [self setSharedImageWithView:self.lockScreenBgView]; 123 | } 124 | 125 | 126 | } 127 | if ([self boolForKey:@"kHomescreenEnabled"]) { 128 | self.homeScreenBgView = [[%c(WUIDynamicWeatherBackground) alloc] initWithFrame:UIScreen.mainScreen.bounds]; 129 | self.homeScreenBgView.city = [self myCity]; 130 | self.homeScreenBgView.condition.city = [self myCity]; 131 | 132 | if ([self boolForKey:@"kUseEntireWeatherView"]) { 133 | [homescreenWallpaperView addSubview:self.homeScreenBgView]; 134 | 135 | [self setSharedImageWithView:self.homeScreenBgView]; 136 | } 137 | } 138 | } 139 | } 140 | 141 | - (void)setupWeatherEffectLayers { 142 | if ([self boolForKey:@"kUseWeatherEffectsOnly"] && [self boolForKey:@"kUseEntireWeatherView"] == NO) { 143 | SBWallpaperController *wallpaperController = [%c(SBWallpaperController) sharedInstance]; 144 | SBFWallpaperView *sharedWallpaperView; 145 | SBFWallpaperView *lockscreenWallpaperView; 146 | SBFWallpaperView *homescreenWallpaperView; 147 | 148 | if (%c(SBWallpaperViewController)) { 149 | SBWallpaperViewController *wallpaperViewController = [wallpaperController valueForKey:@"_wallpaperViewController"]; 150 | 151 | sharedWallpaperView = wallpaperViewController.sharedWallpaperView; 152 | 153 | lockscreenWallpaperView = wallpaperViewController.lockscreenWallpaperView; 154 | homescreenWallpaperView = wallpaperViewController.homescreenWallpaperView; 155 | } 156 | else { 157 | sharedWallpaperView = wallpaperController.sharedWallpaperView; 158 | 159 | lockscreenWallpaperView = wallpaperController.lockscreenWallpaperView; 160 | homescreenWallpaperView = wallpaperController.homescreenWallpaperView; 161 | } 162 | 163 | if (sharedWallpaperView != nil && self.sharedBgView != nil) { 164 | CALayer *nLayer = [self weatherEffectsLayerForWeatherView:nil]; 165 | [sharedWallpaperView.layer addSublayer:nLayer]; 166 | } 167 | else if (lockscreenWallpaperView != nil && homescreenWallpaperView != nil && self.lockScreenBgView != nil && self.homeScreenBgView != nil && sharedWallpaperView == nil) { 168 | if ([self boolForKey:@"kLockscreenEnabled"]) { 169 | CALayer *nLayer = [self weatherEffectsLayerForWeatherView:self.lockScreenBgView]; 170 | [lockscreenWallpaperView.layer addSublayer:nLayer]; 171 | } 172 | if ([self boolForKey:@"kHomescreenEnabled"]) { 173 | CALayer *nLayer = [self weatherEffectsLayerForWeatherView:self.homeScreenBgView]; 174 | [homescreenWallpaperView.layer addSublayer:nLayer]; 175 | } 176 | } 177 | } 178 | } 179 | 180 | - (CALayer *)weatherEffectsLayerForWeatherView:(WUIDynamicWeatherBackground *)weatherView { 181 | CALayer *nLayer = weatherView != nil ? weatherView.condition.layer : self.sharedBgView.condition.layer; 182 | nLayer.bounds = UIScreen.mainScreen.nativeBounds; 183 | nLayer.allowsGroupOpacity = YES; 184 | nLayer.position = CGPointMake(0, UIScreen.mainScreen.bounds.size.height); 185 | nLayer.geometryFlipped = YES; 186 | 187 | return nLayer; 188 | } 189 | 190 | - (void)setSharedImageWithView:(WUIDynamicWeatherBackground *)backgroundView { 191 | if (backgroundView != nil) { 192 | // Take a screenshot of the current view, to use on SBFWallpaperView's contentView's image, otherwise the background when pulling up on Notification Center and Lockscreen will be see through 193 | UIGraphicsBeginImageContextWithOptions(backgroundView.bounds.size, NO, UIScreen.mainScreen.scale); 194 | [backgroundView drawViewHierarchyInRect:backgroundView.bounds afterScreenUpdates:YES]; 195 | self.sharedImage = UIGraphicsGetImageFromCurrentImageContext(); 196 | UIGraphicsEndImageContext(); 197 | } 198 | } 199 | 200 | - (void)updateModel { 201 | if (!self.widgetVC) { 202 | self.widgetVC = [[%c(WALockscreenWidgetViewController) alloc] init]; 203 | 204 | if ([self.widgetVC respondsToSelector:@selector(_setupWeatherModel)]) { 205 | [self.widgetVC _setupWeatherModel]; 206 | 207 | } 208 | } 209 | 210 | if (self.widgetVC) { 211 | if ([self.widgetVC.todayModel respondsToSelector:@selector(executeModelUpdateWithCompletion:)]) { 212 | 213 | if ([self.widgetVC.todayModel isKindOfClass:[WATodayAutoupdatingLocationModel class]]) { 214 | WATodayAutoupdatingLocationModel *autoUpdatingModel = (WATodayAutoupdatingLocationModel *)self.widgetVC.todayModel; 215 | 216 | if ([autoUpdatingModel respondsToSelector:@selector(updateLocationTrackingStatus)]) { 217 | [autoUpdatingModel updateLocationTrackingStatus]; 218 | } 219 | } 220 | 221 | 222 | [self.widgetVC.todayModel executeModelUpdateWithCompletion:nil]; 223 | } 224 | if ([self.widgetVC respondsToSelector:@selector(todayModelWantsUpdate:)] && self.widgetVC.todayModel) { 225 | [self.widgetVC todayModelWantsUpdate:self.widgetVC.todayModel]; 226 | } 227 | if ([self.widgetVC respondsToSelector:@selector(updateWeather)]) { 228 | [self.widgetVC updateWeather]; 229 | } 230 | if ([self.widgetVC respondsToSelector:@selector(_updateTodayView)]) { 231 | [self.widgetVC _updateTodayView]; 232 | } 233 | if ([self.widgetVC respondsToSelector:@selector(_updateWithReason:)]) { 234 | [self.widgetVC _updateWithReason:nil]; 235 | } 236 | 237 | /*if ([self.widgetVC respondsToSelector:@selector(_temperature)]) { 238 | self.currentTemperature = [self.widgetVC _temperature]; 239 | } 240 | 241 | if ([self.widgetVC respondsToSelector:@selector(_locationName)]) { 242 | self.myCity = [self.widgetVC _locationName]; 243 | }*/ 244 | } 245 | 246 | if (self.widgetVC.todayModel.forecastModel.city) { 247 | self.myCity = self.widgetVC.todayModel.forecastModel.city; 248 | 249 | if (self.sharedBgView != nil) { 250 | [self.sharedBgView setCity:[self myCity] animate:YES]; 251 | [self.sharedBgView.condition setCity:[self myCity] animationDuration:2]; 252 | 253 | /*if ([self boolForKey:@"kUseEntireWeatherView"]) { 254 | [self setSharedImageWithView:self.sharedBgView]; 255 | }*/ 256 | 257 | if ([self boolForKey:@"kUseWeatherEffectsOnly"]) { 258 | [self setupWeatherEffectLayers]; 259 | } 260 | } 261 | if (self.lockScreenBgView != nil) { 262 | [self.lockScreenBgView setCity:[self myCity] animate:YES]; 263 | [self.lockScreenBgView.condition setCity:[self myCity] animationDuration:2]; 264 | 265 | /*if ([self boolForKey:@"kUseEntireWeatherView"] && [self boolForKey:@"kLockscreenEnabled"]) { 266 | [self setSharedImageWithView: self.lockScreenBgView]; 267 | }*/ 268 | 269 | if ([self boolForKey: @ "kUseWeatherEffectsOnly"]) { 270 | [self setupWeatherEffectLayers]; 271 | } 272 | } 273 | if (self.homeScreenBgView != nil) { 274 | [self.homeScreenBgView setCity: [self myCity] animate: YES]; 275 | [self.homeScreenBgView.condition setCity: [self myCity] animationDuration: 2]; 276 | 277 | /*if ([self boolForKey:@"kUseEntireWeatherView"] && [self boolForKey:@"kHomescreenEnabled"]) { 278 | [self setSharedImageWithView: self.homeScreenBgView]; 279 | }*/ 280 | 281 | if ([self boolForKey: @ "kUseWeatherEffectsOnly"]) { 282 | [self setupWeatherEffectLayers]; 283 | } 284 | } 285 | } 286 | } 287 | 288 | - (void)pauseWG { 289 | if (self.sharedBgView != nil) { 290 | [self.sharedBgView.condition pause]; 291 | } 292 | if (self.lockScreenBgView != nil) { 293 | [self.lockScreenBgView.condition pause]; 294 | } 295 | if (self.homeScreenBgView != nil) { 296 | [self.homeScreenBgView.condition pause]; 297 | } 298 | } 299 | 300 | - (void)resumeWG { 301 | if (self.sharedBgView != nil) { 302 | [self.sharedBgView.condition resume]; 303 | } 304 | if (self.lockScreenBgView != nil) { 305 | [self.lockScreenBgView.condition resume]; 306 | 307 | } 308 | if (self.homeScreenBgView != nil) { 309 | [self.homeScreenBgView.condition resume]; 310 | } 311 | } 312 | 313 | - (void)updateCityForCity:(City *)city { 314 | city = self.myCity; 315 | } 316 | 317 | - (NSDictionary *)temperatureInfo:(NSString *)unit { 318 | [self updateModel]; 319 | 320 | int temperature = 0; 321 | 322 | if (self.widgetVC != nil && self.widgetVC.todayModel.forecastModel.currentConditions != nil) { 323 | if ([unit isEqualToString:@"celsius"]) { 324 | temperature = (int)self.widgetVC.todayModel.forecastModel.currentConditions.temperature.celsius; 325 | } 326 | else if ([unit isEqualToString:@"fahrenheit"]) { 327 | temperature = (int)ceil(self.widgetVC.todayModel.forecastModel.currentConditions.temperature.fahrenheit); 328 | } 329 | else if ([unit isEqualToString:@"kelvin"]) { 330 | temperature = (int)ceil(self.widgetVC.todayModel.forecastModel.currentConditions.temperature.kelvin); 331 | } 332 | } 333 | 334 | int conditionCode = [self currentConditionCode]; 335 | NSMutableAttributedString *weatherString = [self stringForWeatherImage:[self getImageForCondition:conditionCode style:1] withPrefix:[NSString stringWithFormat:@"%d°", temperature]]; 336 | NSDictionary *infoDict = @{@"weatherString": weatherString}; 337 | return infoDict; 338 | } 339 | 340 | 341 | - (int)currentConditionCode { 342 | if (self.widgetVC != nil && self.widgetVC.todayModel.forecastModel.currentConditions != nil) { 343 | int conditionCode = (int)self.widgetVC.todayModel.forecastModel.currentConditions.conditionCode; 344 | return conditionCode; 345 | } 346 | return 0; 347 | } 348 | 349 | - (UIImage *)getImageForCondition:(NSInteger)conditionCode style:(int)style { 350 | UIImage *image = [WeatherImageLoader conditionImageWithConditionIndex:conditionCode style:style]; 351 | return image; 352 | } 353 | 354 | - (NSMutableAttributedString *)stringForWeatherImage:(UIImage *)weatherImg withPrefix:(NSString *)prefixString{ 355 | // Make a new Mutable Attributed String 356 | NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@", prefixString]]; 357 | // Make a new NSTextAttachment variable and set the image 358 | NSTextAttachment *imgAttachment = [[NSTextAttachment alloc] init]; 359 | imgAttachment.bounds = CGRectMake(0,-12,35,35); 360 | imgAttachment.image = weatherImg; 361 | // Make a new attributed string with the NSTextAttachment 362 | NSAttributedString *attrStringWithWeatherImage = [NSAttributedString attributedStringWithAttachment:imgAttachment]; 363 | // Insert the attributed string containing our NSTextAttachment at the start of the string - example: {weatherIcon} 14° 364 | [attrString insertAttributedString:attrStringWithWeatherImage atIndex:0]; 365 | 366 | return attrString; 367 | } 368 | @end -------------------------------------------------------------------------------- /WeatherHeaders.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | 13 | @interface WUIWeatherCondition : NSObject 14 | @property (assign,nonatomic) City *city; 15 | @property (nonatomic,readonly) CALayer *layer; 16 | -(void)setCity:(id)arg1 animationDuration:(double)arg2 ; 17 | -(void)setAlpha:(double)arg1 animationDuration:(double)arg2; 18 | -(void)resume; 19 | -(void)pause; 20 | @end 21 | 22 | @interface WUIGradientLayer : CAGradientLayer { 23 | BOOL _allowsActions; 24 | } 25 | @property (assign,nonatomic) BOOL allowsActions; 26 | -(id)actionForKey:(id)arg1 ; 27 | -(BOOL)allowsActions; 28 | -(void)setAllowsActions:(BOOL)arg1 ; 29 | @end 30 | 31 | @interface WACurrentForecast 32 | @property (assign,nonatomic) long long conditionCode; 33 | @property (nonatomic, retain) WFTemperature *temperature; 34 | @end 35 | 36 | @interface WAForecastModel : NSObject 37 | @property (nonatomic,retain) City * city; 38 | @property (nonatomic,retain) WACurrentForecast *currentConditions; 39 | -(WFTemperature *)temperature; 40 | @end 41 | 42 | @interface WATodayModel : NSObject 43 | +(id)autoupdatingLocationModelWithPreferences:(id)arg1 effectiveBundleIdentifier:(id)arg2 ; 44 | -(BOOL)executeModelUpdateWithCompletion:(/*^block*/id)arg1 ; 45 | @property (nonatomic,retain) WAForecastModel * forecastModel; 46 | -(id)location; 47 | @end 48 | 49 | 50 | @interface WATodayAutoupdatingLocationModel : WATodayModel 51 | -(void)setIsLocationTrackingEnabled:(BOOL)arg1; 52 | -(void)setLocationServicesActive:(BOOL)arg1; 53 | -(BOOL)updateLocationTrackingStatus; 54 | @end 55 | 56 | @interface UIStatusBarTapAction : NSObject 57 | 58 | @property (nonatomic,readonly) long long type; 59 | @property (nonatomic,readonly) double xPosition; 60 | -(long long)type; 61 | -(id)keyDescriptionForSetting:(unsigned long long)arg1 ; 62 | -(long long)UIActionType; 63 | -(double)xPosition; 64 | -(id)initWithType:(long long)arg1 xPosition:(double)arg2 ; 65 | @end 66 | 67 | 68 | 69 | @interface WFTemperature : NSObject 70 | @property (assign,nonatomic) CGFloat celsius; 71 | @property (assign,nonatomic) CGFloat fahrenheit; 72 | @property (assign,nonatomic) CGFloat kelvin; 73 | -(CGFloat)temperatureForUnit:(int)arg1 ; 74 | @end 75 | 76 | 77 | @interface WUIDynamicWeatherBackground : UIView 78 | @property (nonatomic,retain) WUIWeatherCondition *condition; 79 | @property (nonatomic,retain) WUIGradientLayer *gradientLayer; 80 | 81 | - (id)initWithFrame:(CGRect)arg1 ; 82 | -(void)setCity:(id)arg1 animate:(BOOL)arg2 ; 83 | - (void)setCity:(id)arg1 ; 84 | -(void)setCity:(id)arg1 animationDuration:(double)arg2 ; 85 | -(CALayer *)rootLayer; 86 | @end 87 | 88 | 89 | @interface SBFStaticWallpaperView (WG) 90 | @property (nonatomic, strong) WUIDynamicWeatherBackground *bgView; 91 | @property (nonatomic, retain) WATodayAutoupdatingLocationModel *todayUpdateModel; 92 | @property (nonatomic, strong) City *myCity; 93 | 94 | - (void)updateModel; 95 | - (CALayer *)weatherEffectsLayer; 96 | - (int)currentConditionCode; 97 | - (UIImage *)getImageForCondition:(NSInteger)conditionCode style:(int)style; 98 | 99 | @end 100 | 101 | @interface UIView (Private) 102 | - (id)_viewControllerForAncestor; 103 | @end 104 | 105 | @interface _UIStatusBarForegroundView : UIView 106 | @property (strong, nonatomic) NSString *temperature; 107 | @end 108 | 109 | @interface _UIStatusBarStringView : UILabel 110 | @property (nonatomic,copy) NSString * originalText; 111 | - (void)changeLabelText:(NSString *)text; 112 | - (void)setTemperatureWithNotification:(NSNotification *)notification; 113 | - (void)changeLabelTextWithAttributedString:(NSMutableAttributedString *)text; 114 | @end 115 | 116 | @interface _UIStatusBarDataStringEntry : NSObject 117 | @property (nonatomic,copy) NSString * stringValue; 118 | @end 119 | 120 | @interface _UIStatusBarData : NSObject 121 | @property (nonatomic,copy) _UIStatusBarDataStringEntry * timeEntry; 122 | @end 123 | 124 | @interface _UIStatusBar : UIView 125 | @property (nonatomic,retain) UIView *foregroundView; 126 | @property (nonatomic,readonly) _UIStatusBarData * currentAggregatedData; 127 | @end 128 | 129 | @interface NSObject (WG) 130 | -(id)safeValueForKey:(id)arg1; 131 | @end 132 | 133 | @interface SBFWallpaperView (Private) 134 | @property (nonatomic,copy,readonly) NSString * variantCacheIdentifier; 135 | @property (nonatomic,retain) UIView * contentView; 136 | @end 137 | 138 | @interface SBWallpaperViewController : NSObject 139 | @property (nonatomic,retain) SBFWallpaperView *lockscreenWallpaperView; 140 | @property (nonatomic,retain) SBFWallpaperView *homescreenWallpaperView; 141 | @property (nonatomic,retain) SBFWallpaperView *sharedWallpaperView; 142 | - (SBFWallpaperView *)_activeWallpaperView; 143 | @end 144 | 145 | @interface SBWallpaperController : NSObject 146 | @property (nonatomic,retain) SBFWallpaperView * lockscreenWallpaperView; 147 | @property (nonatomic,retain) SBFWallpaperView * homescreenWallpaperView; 148 | @property (nonatomic,retain) SBFWallpaperView * sharedWallpaperView; 149 | +(id)sharedInstance; 150 | @end 151 | 152 | @interface WALockscreenWidgetViewController : UIViewController 153 | @property (nonatomic, strong) WATodayModel *todayModel; 154 | + (WALockscreenWidgetViewController *)sharedInstanceIfExists; 155 | - (id)_temperature; 156 | - (id)_locationName; 157 | - (void)updateWeather; 158 | - (void)_updateTodayView; 159 | - (void)_updateWithReason:(id)reason; 160 | - (void)_setupWeatherModel; 161 | - (void)todayModelWantsUpdate:(WATodayModel *)todayModel; 162 | 163 | @end 164 | 165 | 166 | @interface WAGreetingView : UIView { 167 | UIImageView * _conditionImageView; 168 | NSMutableArray * _constraints; 169 | bool _isViewCreated; 170 | UIColor * _labelColor; 171 | UILabel * _natualLanguageDescriptionLabel; 172 | UILabel * _temperatureLabel; 173 | WATodayAutoupdatingLocationModel * _todayModel; 174 | } 175 | 176 | @property (nonatomic, retain) UIImageView *conditionImageView; 177 | @property (nonatomic, retain) NSMutableArray *constraints; 178 | @property (nonatomic) bool isViewCreated; 179 | @property (nonatomic, retain) UIColor *labelColor; 180 | @property (nonatomic, retain) UILabel *natualLanguageDescriptionLabel; 181 | @property (nonatomic, retain) UILabel *temperatureLabel; 182 | @property (nonatomic, retain) WATodayAutoupdatingLocationModel *todayModel; 183 | 184 | - (id)_conditionsImage; 185 | - (id)_temperature; 186 | - (id)conditionImageView; 187 | - (id)constraints; 188 | - (void)createViews; 189 | - (void)dealloc; 190 | - (id)init; 191 | - (id)initWithColor:(id)arg1; 192 | - (bool)isViewCreated; 193 | - (id)labelColor; 194 | - (id)natualLanguageDescriptionLabel; 195 | - (void)setConditionImageView:(UIImageView *)arg1; 196 | - (void)setConstraints:(NSMutableArray *)arg1; 197 | - (void)setIsViewCreated:(bool)arg1; 198 | - (void)setLabelColor:(UIColor *)arg1; 199 | - (void)setNatualLanguageDescriptionLabel:(UILabel *)arg1; 200 | - (void)setTemperatureLabel:(UILabel *)arg1; 201 | - (void)setTodayModel:(WATodayAutoupdatingLocationModel *)arg1; 202 | - (void)setupConstraints; 203 | - (void)startService; 204 | - (id)temperatureLabel; 205 | - (id)todayModel; 206 | - (void)updateConstraints; 207 | - (void)updateLabelColors; 208 | - (void)updateView; 209 | 210 | @end 211 | 212 | 213 | @interface SBMainDisplaySceneLayoutStatusBarView : UIView { 214 | _UIStatusBar *_statusBarUnderlyingViewAccessor; 215 | } 216 | @end -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: com.tr1fecta.weatherground 2 | Name: WeatherGround 3 | Depends: mobilesubstrate 4 | Version: 1.4 5 | Architecture: iphoneos-arm 6 | Description: Weather right at your fingertips! 7 | Maintainer: Tr1Fecta 8 | Author: Tr1Fecta 9 | Section: Tweaks 10 | -------------------------------------------------------------------------------- /packages/com.tr1fecta.weatherground_1.1_iphoneos-arm.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tr1Fecta-7/WeatherGround/5ca15924323436cdc365a9283d57268acdd76d51/packages/com.tr1fecta.weatherground_1.1_iphoneos-arm.deb -------------------------------------------------------------------------------- /packages/com.tr1fecta.weatherground_1.2_iphoneos-arm.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tr1Fecta-7/WeatherGround/5ca15924323436cdc365a9283d57268acdd76d51/packages/com.tr1fecta.weatherground_1.2_iphoneos-arm.deb -------------------------------------------------------------------------------- /packages/com.tr1fecta.weatherground_1.3_iphoneos-arm.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tr1Fecta-7/WeatherGround/5ca15924323436cdc365a9283d57268acdd76d51/packages/com.tr1fecta.weatherground_1.3_iphoneos-arm.deb -------------------------------------------------------------------------------- /packages/com.tr1fecta.weatherground_1.4_iphoneos-arm.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Tr1Fecta-7/WeatherGround/5ca15924323436cdc365a9283d57268acdd76d51/packages/com.tr1fecta.weatherground_1.4_iphoneos-arm.deb -------------------------------------------------------------------------------- /wgprefs/Makefile: -------------------------------------------------------------------------------- 1 | include $(THEOS)/makefiles/common.mk 2 | 3 | ARCHS = arm64 arm64e 4 | 5 | BUNDLE_NAME = wgprefs 6 | 7 | wgprefs_FILES = WGPRootListController.m 8 | wgprefs_INSTALL_PATH = /Library/PreferenceBundles 9 | wgprefs_FRAMEWORKS = UIKit 10 | wgprefs_PRIVATE_FRAMEWORKS = Preferences 11 | wgprefs_CFLAGS = -fobjc-arc 12 | 13 | include $(THEOS_MAKE_PATH)/bundle.mk 14 | 15 | internal-stage:: 16 | $(ECHO_NOTHING)mkdir -p $(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences$(ECHO_END) 17 | $(ECHO_NOTHING)cp entry.plist $(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences/wgprefs.plist$(ECHO_END) 18 | -------------------------------------------------------------------------------- /wgprefs/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | wgprefs 9 | CFBundleIdentifier 10 | com.tr1fecta.wgprefs 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1.0 21 | NSPrincipalClass 22 | WGPRootListController 23 | 24 | 25 | -------------------------------------------------------------------------------- /wgprefs/Resources/Root.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | cell 9 | PSGroupCell 10 | label 11 | Tweak Options 12 | 13 | 14 | cell 15 | PSSwitchCell 16 | default 17 | 18 | defaults 19 | com.tr1fecta.wgprefs 20 | key 21 | kTweakEnabled 22 | label 23 | Tweak Enabled 24 | 25 | 26 | cell 27 | PSGroupCell 28 | label 29 | Style Options 30 | 31 | 32 | cell 33 | PSSwitchCell 34 | default 35 | 36 | defaults 37 | com.tr1fecta.wgprefs 38 | key 39 | kUseEntireWeatherView 40 | label 41 | Use Full Weather View 42 | 43 | 44 | cell 45 | PSSwitchCell 46 | default 47 | 48 | defaults 49 | com.tr1fecta.wgprefs 50 | key 51 | kUseWeatherEffectsOnly 52 | label 53 | Use Weather Effects only 54 | 55 | 56 | cell 57 | PSGroupCell 58 | label 59 | Status Bar Options 60 | 61 | 62 | cell 63 | PSSwitchCell 64 | default 65 | 66 | defaults 67 | com.tr1fecta.wgprefs 68 | key 69 | kEnableStatusBarTemperature 70 | label 71 | Tap on time for temperature 72 | 73 | 74 | cell 75 | PSSegmentCell 76 | defaults 77 | com.tr1fecta.wgprefs 78 | label 79 | Temperature Unit 80 | key 81 | kTemperatureUnit 82 | validTitles 83 | 84 | Celsius 85 | Fahrenheit 86 | Kelvin 87 | 88 | validValues 89 | 90 | celsius 91 | fahrenheit 92 | kelvin 93 | 94 | 95 | 96 | cell 97 | PSGroupCell 98 | label 99 | Auto Update Interval (in minutes) 100 | 101 | 102 | cell 103 | PSSliderCell 104 | defaults 105 | com.tr1fecta.wgprefs 106 | label 107 | Interval 108 | key 109 | kAutoUpdateInterval 110 | isSegmented 111 | 112 | min 113 | 0 114 | max 115 | 60 116 | segmentCount 117 | 12 118 | showValue 119 | 120 | 121 | 122 | cell 123 | PSGroupCell 124 | label 125 | Appearance Options (Only works if you have 2 different wallpapers for LS and HS) 126 | 127 | 128 | cell 129 | PSSwitchCell 130 | default 131 | 132 | defaults 133 | com.tr1fecta.wgprefs 134 | key 135 | kLockscreenEnabled 136 | label 137 | Use on Lockscreen 138 | 139 | 140 | cell 141 | PSSwitchCell 142 | default 143 | 144 | defaults 145 | com.tr1fecta.wgprefs 146 | key 147 | kHomescreenEnabled 148 | label 149 | Use on Homescreen 150 | 151 | 152 | title 153 | WeatherGround 154 | 155 | 156 | -------------------------------------------------------------------------------- /wgprefs/WGPRootListController.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface WGPRootListController : PSListController 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /wgprefs/WGPRootListController.m: -------------------------------------------------------------------------------- 1 | #include "WGPRootListController.h" 2 | #include 3 | 4 | @implementation WGPRootListController 5 | 6 | - (NSArray *)specifiers { 7 | if (!_specifiers) { 8 | _specifiers = [self loadSpecifiersFromPlistName:@"Root" target:self]; 9 | } 10 | 11 | return _specifiers; 12 | } 13 | 14 | - (void)viewDidLoad { 15 | [super viewDidLoad]; 16 | UIBarButtonItem *applyButton = [[UIBarButtonItem alloc] initWithTitle:@"Apply" style:UIBarButtonItemStylePlain target:self action:@selector(respring)]; 17 | self.navigationItem.rightBarButtonItem = applyButton; 18 | } 19 | 20 | - (void)respring { 21 | UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Apply Settings" 22 | message:@"Are you sure you want to respring?" 23 | preferredStyle:UIAlertControllerStyleAlert]; 24 | 25 | UIAlertAction* respringAction = [UIAlertAction actionWithTitle:@"Respring" style:UIAlertActionStyleDestructive 26 | handler:^(UIAlertAction * action) { 27 | pid_t pid; 28 | int status; 29 | 30 | const char *args[] = {"sbreload", NULL, NULL, NULL}; 31 | posix_spawn(&pid, "usr/bin/sbreload", NULL, NULL, (char *const *)args, NULL); 32 | waitpid(pid, &status, WEXITED); 33 | }]; 34 | UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel 35 | handler:^(UIAlertAction * action) {}]; 36 | 37 | [alert addAction:respringAction]; 38 | [alert addAction:cancelAction]; 39 | 40 | [self presentViewController:alert animated:YES completion:nil]; 41 | } 42 | 43 | - (id)readPreferenceValue:(PSSpecifier*)specifier { 44 | id result; 45 | 46 | NSDictionary *weatherGroundSettingsDict = [NSDictionary dictionaryWithContentsOfFile:@"/var/mobile/Library/Preferences/com.tr1fecta.wgprefs.plist"]; 47 | 48 | if (!weatherGroundSettingsDict[specifier.properties[@"key"]]) { 49 | // Preference doesn't have a value (unset), so fetch the default. 50 | result = specifier.properties[@"default"]; 51 | } 52 | else { 53 | // Fetch the preference value 54 | result = weatherGroundSettingsDict[specifier.properties[@"key"]]; 55 | } 56 | return result; 57 | } 58 | 59 | - (void)setPreferenceValue:(id)value specifier:(PSSpecifier*)specifier { 60 | NSMutableDictionary *defaults = [NSMutableDictionary dictionary]; 61 | NSString *nsPreferencesPath = @"/var/mobile/Library/Preferences/com.tr1fecta.wgprefs.plist"; 62 | 63 | [defaults addEntriesFromDictionary:[NSDictionary dictionaryWithContentsOfFile:nsPreferencesPath]]; 64 | [defaults setObject:value forKey:specifier.properties[@"key"]]; 65 | [defaults writeToFile:nsPreferencesPath atomically:YES]; 66 | 67 | /*// Send Notification (via Darwin) if one is specified for the preference value. 68 | // This will notify the Tweak (.xm) that the preference value changed. 69 | CFStringRef toPost = (__bridge CFStringRef)specifier.properties[@"PostNotification"]; 70 | if (toPost) { 71 | CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), toPost, NULL, NULL, YES); 72 | }*/ 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /wgprefs/entry.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | entry 6 | 7 | bundle 8 | wgprefs 9 | cell 10 | PSLinkCell 11 | detail 12 | WGPRootListController 13 | icon 14 | icon.png 15 | isController 16 | 17 | label 18 | WeatherGround 19 | 20 | 21 | 22 | --------------------------------------------------------------------------------