├── theos ├── colorbannersprefs ├── theos ├── Resources │ ├── CBRPrefsIcon.png │ ├── CBRPrefsIcon@2x.png │ ├── CBRPrefsIcon@3x.png │ ├── Info.plist │ ├── ColorBannersPrefs.plist │ ├── NotificationCenter.plist │ ├── LockScreen.plist │ └── Banners.plist ├── entry.plist ├── PreferenceHeaders.h ├── Makefile ├── PSControlTableCell.h ├── ColorBannersPrefs.h ├── PSSwitchTableCell.h ├── PSViewController.h ├── ColorBannersCells.m ├── PSTableCell.h ├── PSSpecifier.h ├── PSListController.h └── ColorBannersPrefs.mm ├── .gitignore ├── ColorBanners.plist ├── CBRAppList.h ├── CBRGradientView.h ├── CBRColorCache.h ├── control ├── CBRReadabilityManager.h ├── UIColor+ColorBanners.h ├── README.md ├── Makefile ├── Defines.h ├── CBRGradientView.m ├── NSDistributedNotificationCenter.h ├── ColorBadges.h ├── CBRPrefsManager.h ├── CBRColorCache.m ├── CBRAppList.m ├── CBRReadabilityManager.m ├── UIColor+ColorBanners.m ├── CBRPrefsManager.m ├── PrivateHeaders.h └── Tweak.xm /theos: -------------------------------------------------------------------------------- 1 | /opt/theos -------------------------------------------------------------------------------- /colorbannersprefs/theos: -------------------------------------------------------------------------------- 1 | /opt/theos -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | 3 | obj/ 4 | 5 | .theos/ 6 | 7 | _/ 8 | 9 | private/ 10 | 11 | /*.deb 12 | -------------------------------------------------------------------------------- /ColorBanners.plist: -------------------------------------------------------------------------------- 1 | { Filter = { Bundles = ( "com.apple.springboard", "com.apple.mobilesms.notification" ); }; } 2 | -------------------------------------------------------------------------------- /colorbannersprefs/Resources/CBRPrefsIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidGoldman/ColorBanners/HEAD/colorbannersprefs/Resources/CBRPrefsIcon.png -------------------------------------------------------------------------------- /colorbannersprefs/Resources/CBRPrefsIcon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidGoldman/ColorBanners/HEAD/colorbannersprefs/Resources/CBRPrefsIcon@2x.png -------------------------------------------------------------------------------- /colorbannersprefs/Resources/CBRPrefsIcon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavidGoldman/ColorBanners/HEAD/colorbannersprefs/Resources/CBRPrefsIcon@3x.png -------------------------------------------------------------------------------- /CBRAppList.h: -------------------------------------------------------------------------------- 1 | @interface CBRAppList : NSObject { 2 | 3 | } 4 | + (NSArray *)allAppIdentifiers; 5 | + (NSString *)randomAppIdentifier; 6 | + (NSSet *)hiddenIdentifiers; 7 | @end 8 | -------------------------------------------------------------------------------- /colorbannersprefs/entry.plist: -------------------------------------------------------------------------------- 1 | { 2 | entry = { 3 | bundle = ColorBannersPrefs; 4 | cell = PSLinkCell; 5 | detail = ColorBannersPrefsListController; 6 | icon = CBRPrefsIcon.png; 7 | isController = 1; 8 | label = ColorBanners; 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /CBRGradientView.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface CBRGradientView : UIView { 4 | NSArray *_colors; 5 | } 6 | 7 | - (instancetype)initWithFrame:(CGRect)frame; 8 | - (void)setColors:(NSArray *)colors; 9 | - (void)setSolidColor:(UIColor *)color; 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /CBRColorCache.h: -------------------------------------------------------------------------------- 1 | @interface CBRColorCache : NSObject { 2 | NSCache *_cache; 3 | } 4 | 5 | + (instancetype)sharedInstance; 6 | + (BOOL)isDarkColor:(int)color; 7 | 8 | - (int)colorForIdentifier:(NSString *)identifier image:(UIImage *)image; 9 | - (int)colorForImage:(UIImage *)image; 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /colorbannersprefs/PreferenceHeaders.h: -------------------------------------------------------------------------------- 1 | #import "PSControlTableCell.h" 2 | #import "PSListController.h" 3 | #import "PSSpecifier.h" 4 | #import "PSSwitchTableCell.h" 5 | #import "PSTableCell.h" 6 | #import "PSViewController.h" 7 | 8 | @interface NSArray(Private) 9 | - (id)specifierForID:(id)id; 10 | @end 11 | -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: com.golddavid.colorbanners 2 | Name: ColorBanners 3 | Depends: firmware (>= 8.0), mobilesubstrate (>= 0.9.5.000), org.thebigboss.libcolorpicker (>= 1.1) 4 | Version: 1.0.5 5 | Architecture: iphoneos-arm 6 | Description: Color your notifications 7 | Depiction: http://apt.golddavid.com/depictions/ColorBanners.html 8 | Maintainer: David Goldman 9 | Author: David Goldman 10 | Section: Tweaks 11 | Icon: file:///Library/PreferenceBundles/ColorBannersPrefs.bundle/CBRPrefsIcon@3x.png 12 | -------------------------------------------------------------------------------- /CBRReadabilityManager.h: -------------------------------------------------------------------------------- 1 | @class CBRReadabilityManager; 2 | 3 | @protocol CBRReadabilityManagerDelegate 4 | @required 5 | - (void)managersReadabilityStateDidChange:(CBRReadabilityManager *)manager; 6 | @end 7 | 8 | @interface CBRReadabilityManager : NSObject { 9 | 10 | } 11 | 12 | @property(nonatomic, assign) BOOL shouldUseDarkText; 13 | @property(nonatomic, assign) id delegate; 14 | 15 | + (instancetype)sharedInstance; 16 | 17 | - (void)refresh; 18 | - (void)setShouldUseDarkTextAndSynchronize:(BOOL)useDarkText; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /UIColor+ColorBanners.h: -------------------------------------------------------------------------------- 1 | // Adapted from https://github.com/thisandagain/color. 2 | 3 | #import 4 | 5 | @interface UIColor(ColorBanners) 6 | 7 | + (UIColor *)cbr_colorWithHue:(CGFloat)hue saturation:(CGFloat)saturation lightness:(CGFloat)lightness alpha:(CGFloat)alpha; 8 | - (void)cbr_getHue:(CGFloat *)hue saturation:(CGFloat *)saturation lightness:(CGFloat *)lightness alpha:(CGFloat *)alpha; 9 | - (UIColor *)cbr_offsetWithHue:(CGFloat)h saturation:(CGFloat)s lightness:(CGFloat)l alpha:(CGFloat)alpha; 10 | - (UIColor *)cbr_lighten:(CGFloat)amount; 11 | - (UIColor *)cbr_darken:(CGFloat)amount; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ColorBanners 2 | ====== 3 | 4 | *Colorize your banners and lockscreen notifications.* 5 | 6 | This tweak allows you to improve the look of your notifications by coloring them to match the app icon. 7 | Also included is an option to just use a constant color (thanks to [libcolorpicker](https://bitbucket.org/pixelfiredev/libcolorpicker/)). 8 | 9 | Note that this version of the tweak does require ColorBadges. 10 | 11 | This tweak was built with help from: 12 | * [PriorityHub](https://github.com/thomasfinch/Priority-Hub) 13 | * [TinyBar](https://github.com/alexzielenski/TinyBar) 14 | * [InspectiveC](https://github.com/DavidGoldman/InspectiveC) 15 | -------------------------------------------------------------------------------- /colorbannersprefs/Makefile: -------------------------------------------------------------------------------- 1 | include $(THEOS)/makefiles/common.mk 2 | 3 | BUNDLE_NAME = ColorBannersPrefs 4 | ColorBannersPrefs_FILES = ColorBannersPrefs.mm ColorBannersCells.m 5 | ColorBannersPrefs_INSTALL_PATH = /Library/PreferenceBundles 6 | ColorBannersPrefs_LIBRARIES = colorpicker 7 | ColorBannersPrefs_FRAMEWORKS = UIKit 8 | ColorBannersPrefs_PRIVATE_FRAMEWORKS = Preferences 9 | ColorBannersPrefs_LDFLAGS += -Wl,-segalign,4000 10 | 11 | include $(THEOS_MAKE_PATH)/bundle.mk 12 | 13 | internal-stage:: 14 | $(ECHO_NOTHING)mkdir -p $(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences$(ECHO_END) 15 | $(ECHO_NOTHING)cp entry.plist $(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences/ColorBannersPrefs.plist$(ECHO_END) 16 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | export ARCHS = armv7 arm64 2 | export TARGET = iphone:9.2:9.2 3 | export THEOS_PACKAGE_DIR_NAME = debs 4 | # PACKAGE_VERSION = $(THEOS_PACKAGE_BASE_VERSION)~beta$(VERSION.INC_BUILD_NUMBER) 5 | include $(THEOS)/makefiles/common.mk 6 | 7 | TWEAK_NAME = ColorBanners 8 | ColorBanners_FILES = Tweak.xm CBRGradientView.m UIColor+ColorBanners.m CBRPrefsManager.m CBRAppList.m 9 | ColorBanners_FILES += CBRColorCache.m CBRReadabilityManager.m 10 | # ColorBanners_FILES += private/*.m 11 | ColorBanners_FRAMEWORKS = UIKit CoreGraphics QuartzCore 12 | ColorBanners_LDFLAGS += -Wl,-segalign,4000 13 | 14 | include $(THEOS_MAKE_PATH)/tweak.mk 15 | 16 | after-install:: 17 | install.exec "killall -9 SpringBoard" 18 | SUBPROJECTS += colorbannersprefs 19 | include $(THEOS_MAKE_PATH)/aggregate.mk 20 | -------------------------------------------------------------------------------- /Defines.h: -------------------------------------------------------------------------------- 1 | // #define DEBUG 2 | 3 | #ifdef DEBUG 4 | #define CBRLOG(fmt, ...) NSLog(@"[ColorBanners]-%d %@", __LINE__, [NSString stringWithFormat:fmt, ##__VA_ARGS__]) 5 | #else 6 | #define CBRLOG(fmt, ...) 7 | #endif 8 | 9 | #define INFO(fmt, ...) NSLog(@"[ColorBanners] INFO %@", [NSString stringWithFormat:fmt, ##__VA_ARGS__]) 10 | 11 | #define INTERNAL_NOTIFICATION_NAME @"CBRReloadPreferences" 12 | #define TEST_LS "com.golddavid.colorbanners/test-ls-notification" 13 | #define TEST_BANNER "com.golddavid.colorbanners/test-banner" 14 | #define RESPRING "com.golddavid.colorbanners/respring" 15 | 16 | #ifndef kCFCoreFoundationVersionNumber_iOS_9_0 17 | #define kCFCoreFoundationVersionNumber_iOS_9_0 1240.10 18 | #endif 19 | 20 | #define IS_IOS9_OR_NEWER (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_9_0) 21 | -------------------------------------------------------------------------------- /colorbannersprefs/PSControlTableCell.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This header is generated by classdump-dyld 0.1 3 | * on Wednesday, November 27, 2013 at 11:21:54 PM Eastern European Standard Time 4 | * Operating System: Version 7.0.3 (Build 11B511) 5 | * Image Source: /System/Library/PrivateFrameworks/Preferences.framework/Preferences 6 | * classdump-dyld is free of use, Copyright © 2013 by Elias Limneos. 7 | */ 8 | 9 | #import "PSTableCell.h" 10 | 11 | @class UIControl; 12 | 13 | @interface PSControlTableCell : PSTableCell { 14 | 15 | UIControl* _control; 16 | 17 | } 18 | 19 | @property (nonatomic,retain) UIControl * control; 20 | -(void)setControl:(UIControl *)arg1 ; 21 | -(id)valueLabel; 22 | -(void)dealloc; 23 | -(BOOL)canReload; 24 | -(id)initWithStyle:(int)arg1 reuseIdentifier:(id)arg2 specifier:(id)arg3 ; 25 | -(void)refreshCellContentsWithSpecifier:(id)arg1 ; 26 | -(id)newControl; 27 | -(void)controlChanged:(id)arg1 ; 28 | -(id)controlValue; 29 | -(id)control; 30 | @end 31 | -------------------------------------------------------------------------------- /colorbannersprefs/ColorBannersPrefs.h: -------------------------------------------------------------------------------- 1 | #import "PreferenceHeaders.h" 2 | 3 | @interface ColorBannersPrefsListController : PSListController 4 | @end 5 | 6 | @interface ColorBannersBannerPrefsController : PSListController { 7 | NSMutableArray *_constantColorSpecifiers; 8 | NSArray *_liveAnalysisSpecifiers; 9 | } 10 | @end 11 | 12 | @interface ColorBannersLSPrefsController : PSListController { 13 | NSMutableArray *_constantColorSpecifiers; 14 | } 15 | @end 16 | 17 | @interface ColorBannersNCPrefsController : PSListController { 18 | NSMutableArray *_constantColorSpecifiers; 19 | } 20 | @end 21 | 22 | @protocol PreferencesTableCustomView 23 | - (id)initWithSpecifier:(id)specifier; 24 | @optional 25 | - (CGFloat)preferredHeightForWidth:(CGFloat)width; 26 | - (CGFloat)preferredHeightForWidth:(CGFloat)width inTableView:(id)tableView; 27 | @end 28 | 29 | @interface ColorBannersHeaderCell : PSTableCell { 30 | UILabel *_titleLabel; 31 | UILabel *_subtitleLabel; 32 | } 33 | @end 34 | -------------------------------------------------------------------------------- /colorbannersprefs/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ColorBannersPrefs 9 | CFBundleIdentifier 10 | com.golddavid.colorbannerprefs 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1.0 21 | DTPlatformName 22 | iphoneos 23 | MinimumOSVersion 24 | 3.0 25 | NSPrincipalClass 26 | ColorBannersPrefsListController 27 | 28 | 29 | -------------------------------------------------------------------------------- /CBRGradientView.m: -------------------------------------------------------------------------------- 1 | #import "CBRGradientView.h" 2 | 3 | @implementation CBRGradientView 4 | 5 | + (Class)layerClass { 6 | return [CAGradientLayer class]; 7 | } 8 | 9 | - (instancetype)initWithFrame:(CGRect)frame { 10 | self = [super initWithFrame:frame]; 11 | if (self) { 12 | self.opaque = NO; 13 | } 14 | return self; 15 | } 16 | 17 | - (void)setSolidColor:(UIColor *)color { 18 | self.backgroundColor = color; 19 | if (color) { 20 | [self setColors:nil]; 21 | } 22 | } 23 | 24 | - (void)setColors:(NSArray *)colors { 25 | [colors retain]; 26 | [_colors release]; 27 | _colors = colors; 28 | [self refreshGradientLayer]; 29 | if (colors) { 30 | self.backgroundColor = nil; 31 | } 32 | } 33 | 34 | - (void)refreshGradientLayer { 35 | CAGradientLayer *gradientLayer = (CAGradientLayer *)self.layer; 36 | gradientLayer.colors = _colors; 37 | gradientLayer.startPoint = CGPointMake(0.0, 0.5); 38 | gradientLayer.endPoint = CGPointMake(1.0, 0.5); 39 | } 40 | 41 | - (void)dealloc { 42 | [_colors release]; 43 | [super dealloc]; 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /colorbannersprefs/PSSwitchTableCell.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This header is generated by classdump-dyld 0.1 3 | * on Wednesday, November 27, 2013 at 11:21:54 PM Eastern European Standard Time 4 | * Operating System: Version 7.0.3 (Build 11B511) 5 | * Image Source: /System/Library/PrivateFrameworks/Preferences.framework/Preferences 6 | * classdump-dyld is free of use, Copyright © 2013 by Elias Limneos. 7 | */ 8 | 9 | #import "PSControlTableCell.h" 10 | 11 | @class UIActivityIndicatorView; 12 | 13 | @interface PSSwitchTableCell : PSControlTableCell { 14 | 15 | UIActivityIndicatorView* _activityIndicator; 16 | 17 | } 18 | 19 | @property (assign,nonatomic) BOOL loading; 20 | -(void)setLoading:(BOOL)arg1 ; 21 | -(BOOL)loading; 22 | -(void)dealloc; 23 | -(void)layoutSubviews; 24 | -(void)setValue:(id)arg1 ; 25 | -(void)prepareForReuse; 26 | -(void)setCellEnabled:(BOOL)arg1 ; 27 | -(BOOL)canReload; 28 | -(void)reloadWithSpecifier:(id)arg1 animated:(BOOL)arg2 ; 29 | -(id)initWithStyle:(int)arg1 reuseIdentifier:(id)arg2 specifier:(id)arg3 ; 30 | -(void)refreshCellContentsWithSpecifier:(id)arg1 ; 31 | -(id)newControl; 32 | -(id)controlValue; 33 | @end 34 | -------------------------------------------------------------------------------- /NSDistributedNotificationCenter.h: -------------------------------------------------------------------------------- 1 | @interface NSDistributedNotificationCenter : NSNotificationCenter 2 | 3 | + (instancetype)defaultCenter; 4 | + (instancetype)notificationCenterForType:(id)arg1; 5 | 6 | - (void)addObserver:(id)arg1 selector:(SEL)arg2 name:(id)arg3 object:(id)arg4 suspensionBehavior:(unsigned int)arg5; 7 | - (void)addObserver:(id)arg1 selector:(SEL)arg2 name:(id)arg3 object:(id)arg4; 8 | - (id)addObserverForName:(id)arg1 object:(id)arg2 queue:(id)arg3 usingBlock:(id)arg4; 9 | - (id)addObserverForName:(id)arg1 object:(id)arg2 suspensionBehavior:(unsigned int)arg3 queue:(id)arg4 usingBlock:(id)arg5; 10 | - (id)init; 11 | - (void)postNotification:(id)arg1; 12 | - (void)postNotificationName:(id)arg1 object:(id)arg2 userInfo:(id)arg3 deliverImmediately:(BOOL)arg4; 13 | - (void)postNotificationName:(id)arg1 object:(id)arg2 userInfo:(id)arg3 options:(unsigned int)arg4; 14 | - (void)postNotificationName:(id)arg1 object:(id)arg2 userInfo:(id)arg3; 15 | - (void)postNotificationName:(id)arg1 object:(id)arg2; 16 | - (void)removeObserver:(id)arg1 name:(id)arg2 object:(id)arg3; 17 | - (void)setSuspended:(BOOL)arg1; 18 | - (BOOL)suspended; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /ColorBadges.h: -------------------------------------------------------------------------------- 1 | #define GETRED(rgb) ((rgb >> 16) & 0xFF) 2 | #define GETGREEN(rgb) ((rgb >> 8) & 0xFF) 3 | #define GETBLUE(rgb) (rgb & 0xFF) 4 | #define UIColorFromRGB(rgb) [UIColor colorWithRed:GETRED(rgb)/255.0 green:GETGREEN(rgb)/255.0 blue:GETBLUE(rgb)/255.0 alpha:1.0] 5 | 6 | @interface ColorBadges : NSObject 7 | 8 | + (instancetype)sharedInstance; 9 | + (BOOL)isDarkColor:(int)color; 10 | + (BOOL)areBordersEnabled; 11 | + (BOOL)isEnabled; 12 | 13 | // Return RGB ints. i.e. 0xRRGGBB. 14 | - (int)colorForImage:(UIImage *)image; 15 | - (int)colorForIcon:(id)icon; // Must be an SBIcon * 16 | 17 | @end 18 | 19 | // You can use the API like the following. Note that you may need to dlopen ColorBadges first. 20 | /* 21 | @implementation YourObject 22 | - (void)configureMyBadge:(id)badge forIcon:(id)icon { 23 | Class cb = %c(ColorBadges); 24 | if ([cb isEnabled]) { 25 | int color = [[cb sharedInstance] colorForIcon:icon]; 26 | badge.tintColor = UIColorFromRGB(color); 27 | UIColor *textColor = ([cb isDarkColor:color]) ? [UIColor whiteColor] : [UIColor blackColor]; 28 | badge.textColor = textColor; 29 | 30 | if ([cb areBordersEnabled]) { 31 | UIColor *borderColor = textColor; 32 | // Add border. 33 | } 34 | } else { 35 | badge.tintColor = [UIColor redColor]; // Default color 36 | } 37 | } 38 | @end 39 | */ 40 | -------------------------------------------------------------------------------- /colorbannersprefs/PSViewController.h: -------------------------------------------------------------------------------- 1 | /* Generated by RuntimeBrowser 2 | Image: /System/Library/PrivateFrameworks/Preferences.framework/Preferences 3 | */ 4 | 5 | #import 6 | #import 7 | 8 | //@class PSRootController, PSSpecifier, UIViewController; 9 | 10 | @interface PSViewController : UIViewController /**/ { 11 | /*UIViewController *_parentController; 12 | PSRootController *_rootController; 13 | PSSpecifier *_specifier;*/ 14 | } 15 | 16 | - (BOOL)canBeShownFromSuspendedState; 17 | - (void)dealloc; 18 | - (void)didLock; 19 | - (void)didUnlock; 20 | - (void)didWake; 21 | - (void)formSheetViewDidDisappear; 22 | - (void)formSheetViewWillDisappear; 23 | - (void)handleURL:(id)arg1; 24 | - (id)parentController; 25 | - (void)popupViewDidDisappear; 26 | - (void)popupViewWillDisappear; 27 | - (void)pushController:(id)arg1; 28 | - (id)readPreferenceValue:(id)arg1; 29 | - (id)rootController; 30 | - (void)setParentController:(id)arg1; 31 | - (void)setPreferenceValue:(id)arg1 specifier:(id)arg2; 32 | - (void)setRootController:(id)arg1; 33 | - (void)setSpecifier:(id)arg1; 34 | - (id)specifier; 35 | - (void)statusBarWillAnimateByHeight:(float)arg1; 36 | - (void)suspend; 37 | - (void)willBecomeActive; 38 | - (void)willResignActive; 39 | - (void)willUnlock; 40 | 41 | @end -------------------------------------------------------------------------------- /colorbannersprefs/Resources/ColorBannersPrefs.plist: -------------------------------------------------------------------------------- 1 | { 2 | title = "ColorBanners"; 3 | items = ( 4 | { 5 | cell = PSGroupCell; 6 | headerCellClass = ColorBannersHeaderCell; 7 | }, 8 | { 9 | cell = PSLinkListCell; 10 | detail = ColorBannersBannerPrefsController; 11 | label = "Banners"; 12 | icon = "Banners.png"; 13 | key = "BannersEnabled"; 14 | default = 1; 15 | defaults = "com.golddavid.colorbanners"; 16 | get = "getLabelForSpecifier:"; 17 | }, 18 | { 19 | cell = PSLinkListCell; 20 | detail = ColorBannersLSPrefsController; 21 | label = "Lock Screen"; 22 | icon = "LockScreen.png"; 23 | key = "LSEnabled"; 24 | default = 1; 25 | defaults = "com.golddavid.colorbanners"; 26 | get = "getLabelForSpecifier:"; 27 | }, 28 | { 29 | cell = PSLinkListCell; 30 | detail = ColorBannersNCPrefsController; 31 | label = "Notification Center"; 32 | icon = "NC.png"; 33 | key = "NCEnabled"; 34 | default = 1; 35 | defaults = "com.golddavid.colorbanners"; 36 | get = "getLabelForSpecifier:"; 37 | }, 38 | 39 | { 40 | cell = PSGroupCell; 41 | label = "Testing"; 42 | }, 43 | { 44 | cell = PSButtonCell; 45 | label = "Test Banner"; 46 | action = "testBanner"; 47 | }, 48 | { 49 | cell = PSButtonCell; 50 | label = "Test Notification"; 51 | action = "testLockScreenNotification"; 52 | }, 53 | 54 | { 55 | cell = PSGroupCell; 56 | height = 20; 57 | footerText = "© 2015 David Goldman 58 | Icon by Hœnir"; 59 | } 60 | ); 61 | } 62 | -------------------------------------------------------------------------------- /CBRPrefsManager.h: -------------------------------------------------------------------------------- 1 | 2 | @interface CBRPrefsManager : NSObject { 3 | 4 | } 5 | 6 | @property(nonatomic, assign, getter=areBannersEnabled) BOOL bannersEnabled; 7 | @property(nonatomic, assign, getter=isLSEnabled) BOOL lsEnabled; 8 | @property(nonatomic, assign, getter=isNCEnabled) BOOL ncEnabled; 9 | 10 | @property(nonatomic, assign, getter=shouldUseBannerGradient) BOOL useBannerGradient; 11 | @property(nonatomic, assign, getter=shouldUseLSGradient) BOOL useLSGradient; 12 | @property(nonatomic, assign, getter=shouldUseNCGradient) BOOL useNCGradient; 13 | 14 | @property(nonatomic, assign, getter=shouldBannersUseConstantColor) BOOL bannersUseConstantColor; 15 | @property(nonatomic, assign, getter=shouldLSUseConstantColor) BOOL lsUseConstantColor; 16 | @property(nonatomic, assign, getter=shouldNCUseConstantColor) BOOL ncUseConstantColor; 17 | 18 | @property(nonatomic, assign) int bannerBackgroundColor; 19 | @property(nonatomic, assign) int lsBackgroundColor; 20 | @property(nonatomic, assign) int ncBackgroundColor; 21 | 22 | @property(nonatomic, assign) CGFloat bannerAlpha; 23 | @property(nonatomic, assign) CGFloat lsAlpha; 24 | @property(nonatomic, assign) CGFloat ncAlpha; 25 | 26 | @property(nonatomic, assign, getter=shouldRemoveLSBlur) BOOL removeLSBlur; 27 | @property(nonatomic, assign, getter=shouldShowSeparators) BOOL showSeparators; 28 | @property(nonatomic, assign, getter=shouldDisableDimming) BOOL disableDimming; 29 | @property(nonatomic, assign, getter=shouldColorDismissButton) BOOL colorDismissButton; 30 | 31 | @property(nonatomic, assign) BOOL prefersWhiteText; 32 | 33 | @property(nonatomic, assign) BOOL wantsDeepBannerAnalyzing; 34 | @property(nonatomic, assign) BOOL wantsLiveAnalysis; 35 | 36 | @property(nonatomic, assign, getter=shouldRoundCorners) BOOL roundCorners; 37 | @property(nonatomic, assign, getter=shouldRemoveBannersBlur) BOOL removeBannersBlur; 38 | @property(nonatomic, assign, getter=shouldHideQRRect) BOOL hideQRRect; 39 | @property(nonatomic, assign, getter=shouldHideGrabber) BOOL hideGrabber; 40 | 41 | + (instancetype)sharedInstance; 42 | 43 | - (void)reload; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /colorbannersprefs/Resources/NotificationCenter.plist: -------------------------------------------------------------------------------- 1 | { 2 | title = "Notification Center"; 3 | items = ( 4 | { 5 | cell = PSSwitchCell; 6 | label = "Enabled"; 7 | key = "NCEnabled"; 8 | default = 1; 9 | defaults = "com.golddavid.colorbanners"; 10 | PostNotification = "com.golddavid.colorbanners/reloadprefs-main"; 11 | }, 12 | 13 | { 14 | cell = PSGroupCell; 15 | }, 16 | { 17 | cell = PSSwitchCell; 18 | label = "Use Gradient"; 19 | key = "NCGradient"; 20 | default = 1; 21 | defaults = "com.golddavid.colorbanners"; 22 | PostNotification = "com.golddavid.colorbanners/reloadprefs"; 23 | }, 24 | { 25 | cell = PSSwitchCell; 26 | set = "setNCConstantColorsEnabled:forSpecifier:"; 27 | id = "CUSTOM_COLOR_MINUS_ONE"; 28 | label = "Use Constant Colors"; 29 | key = "NCUseConstant"; 30 | default = 0; 31 | defaults = "com.golddavid.colorbanners"; 32 | PostNotification = "com.golddavid.colorbanners/reloadprefs"; 33 | }, 34 | 35 | { 36 | cell = PSGroupCell; 37 | label = "Constant Colors"; 38 | id = "CUSTOM_COLOR_GROUP"; 39 | }, 40 | { 41 | cell = PSLinkCell; 42 | cellClass = PFColorCell; 43 | label = "Constant Background Color"; 44 | title = "Background Color"; 45 | color_key = "NCBackgroundColor"; 46 | color_defaults = "com.golddavid.colorbanners"; 47 | color_postNotification = "com.golddavid.colorbanners/reloadprefs-nc"; 48 | color_fallback = "#ffffff"; 49 | usesRGB = 1; 50 | usesAlpha = 0; 51 | }, 52 | 53 | { 54 | cell = PSGroupCell; 55 | label = "Notification Background Alpha"; 56 | footerText = "Changes may require a respring to properly take effect."; 57 | }, 58 | { 59 | cell = PSSliderCell; 60 | key = "NCAlpha"; 61 | showValue = 1; 62 | min = 0; 63 | max = 1; 64 | default = 0.7; 65 | defaults = "com.golddavid.colorbanners"; 66 | PostNotification = "com.golddavid.colorbanners/reloadprefs"; 67 | } 68 | ); 69 | } 70 | -------------------------------------------------------------------------------- /colorbannersprefs/ColorBannersCells.m: -------------------------------------------------------------------------------- 1 | #import "ColorBannersPrefs.h" 2 | 3 | @implementation ColorBannersHeaderCell 4 | 5 | - (instancetype)initWithStyle:(int)style reuseIdentifier:(id)reuseIdentifier specifier:(id)specifier { 6 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier specifier:specifier]; 7 | 8 | if (self) { 9 | self.backgroundColor = [UIColor clearColor]; 10 | 11 | CGFloat width = self.contentView.bounds.size.width; 12 | CGRect titleFrame = CGRectMake(0, 20, width, 55); 13 | CGRect subtitleFrame = CGRectMake(0, 75, width, 19); 14 | 15 | _titleLabel = [[UILabel alloc] initWithFrame:titleFrame]; 16 | _titleLabel.font = [UIFont fontWithName:@"HelveticaNeue-UltraLight" size:48]; 17 | _titleLabel.textColor = [UIColor darkGrayColor]; 18 | _titleLabel.text = @"ColorBanners"; 19 | _titleLabel.backgroundColor = [UIColor clearColor]; 20 | _titleLabel.textAlignment = NSTextAlignmentCenter; 21 | _titleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth; 22 | _titleLabel.contentMode = UIViewContentModeScaleToFill; 23 | 24 | _subtitleLabel = [[UILabel alloc] initWithFrame:subtitleFrame]; 25 | _subtitleLabel.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:16]; 26 | _subtitleLabel.text = @"By David Goldman"; 27 | _subtitleLabel.backgroundColor = [UIColor clearColor]; 28 | _subtitleLabel.textColor = [UIColor grayColor]; 29 | _subtitleLabel.textAlignment = NSTextAlignmentCenter; 30 | _subtitleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth; 31 | _subtitleLabel.contentMode = UIViewContentModeScaleToFill; 32 | [self.contentView addSubview:_titleLabel]; 33 | [self.contentView addSubview:_subtitleLabel]; 34 | } 35 | return self; 36 | } 37 | 38 | - (instancetype)initWithSpecifier:(PSSpecifier *)specifier { 39 | return [self initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CBRHeaderCell" specifier:specifier]; 40 | } 41 | 42 | - (void)setFrame:(CGRect)frame { 43 | // Fix for iPad. 44 | frame.origin.x = 0; 45 | [super setFrame:frame]; 46 | } 47 | 48 | - (void)dealloc { 49 | [_titleLabel release]; 50 | [_subtitleLabel release]; 51 | [super dealloc]; 52 | } 53 | 54 | - (CGFloat)preferredHeightForWidth:(CGFloat)width { 55 | return 120.0; 56 | } 57 | 58 | - (CGFloat)preferredHeightForWidth:(CGFloat)width inTableView:(id)tableView { 59 | return [self preferredHeightForWidth:width]; 60 | } 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /CBRColorCache.m: -------------------------------------------------------------------------------- 1 | #import "CBRColorCache.h" 2 | 3 | #import "ColorBadges.h" 4 | #import "Defines.h" 5 | 6 | #import 7 | 8 | #define DEFAULT_COUNT_LIMIT 100 9 | 10 | static id bucket_Class = nil; 11 | static id cb_Class = nil; 12 | static BOOL prettierBanners_isInstalled = NO; 13 | 14 | static void proxy_init() { 15 | static dispatch_once_t predicate; 16 | 17 | dispatch_once(&predicate, ^{ 18 | bucket_Class = objc_getClass("CBRBucket"); 19 | cb_Class = objc_getClass("ColorBadges"); 20 | 21 | NSString *pBPath = @"/Library/MobileSubstrate/DynamicLibraries/PrettierBanners.dylib"; 22 | prettierBanners_isInstalled = [[NSFileManager defaultManager] fileExistsAtPath:pBPath]; 23 | }); 24 | } 25 | 26 | static int proxy_colorForImage(UIImage *image) { 27 | proxy_init(); 28 | 29 | if (bucket_Class) { 30 | return [bucket_Class colorForImage:image]; 31 | } 32 | return [[cb_Class sharedInstance] colorForImage:image]; 33 | } 34 | 35 | static BOOL proxy_isDarkColor(int color) { 36 | proxy_init(); 37 | 38 | if (bucket_Class) { 39 | return [bucket_Class isDarkColor:color]; 40 | } 41 | return [cb_Class isDarkColor:color]; 42 | } 43 | 44 | @implementation CBRColorCache 45 | 46 | + (instancetype)sharedInstance { 47 | static dispatch_once_t onceToken; 48 | static CBRColorCache *cache; 49 | dispatch_once(&onceToken, ^{ cache = [[CBRColorCache alloc] init]; } ); 50 | return cache; 51 | } 52 | 53 | + (BOOL)isDarkColor:(int)color { 54 | return proxy_isDarkColor(color); 55 | } 56 | 57 | - (instancetype)init { 58 | self = [super init]; 59 | if (self) { 60 | _cache = [[NSCache alloc] init]; 61 | [_cache setCountLimit:DEFAULT_COUNT_LIMIT]; 62 | } 63 | return self; 64 | } 65 | 66 | - (int)colorForIdentifier:(NSString *)identifier image:(UIImage *)image { 67 | if (!identifier) { 68 | CBRLOG(@"No identifier given for image %@", image); 69 | return proxy_colorForImage(image); 70 | } 71 | if (prettierBanners_isInstalled && [identifier isEqualToString:@"com.apple.MobileSMS"]) { 72 | CBRLOG(@"PrettierBanners is installed! Avoiding the cache."); 73 | return proxy_colorForImage(image); 74 | } 75 | 76 | NSNumber *colorNum = [_cache objectForKey:identifier]; 77 | if (colorNum) { 78 | CBRLOG(@"Cache hit for identifier %@", identifier); 79 | 80 | return [colorNum intValue]; 81 | } else { 82 | CBRLOG(@"Cache miss for identifier %@", identifier); 83 | 84 | int color = proxy_colorForImage(image); 85 | [_cache setObject:@(color) forKey:identifier]; 86 | return color; 87 | } 88 | } 89 | 90 | - (int)colorForImage:(UIImage *)image { 91 | if (!image) { 92 | CBRLOG(@"No image given when requesting analysis!"); 93 | } 94 | return proxy_colorForImage(image); 95 | } 96 | 97 | - (void)dealloc { 98 | [_cache release]; 99 | [super dealloc]; 100 | } 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /CBRAppList.m: -------------------------------------------------------------------------------- 1 | #import "CBRAppList.h" 2 | 3 | #import 4 | 5 | @interface SBApplicationController : NSObject 6 | + (id)sharedInstance; 7 | - (id)allBundleIdentifiers; 8 | @end 9 | 10 | @implementation CBRAppList 11 | 12 | + (NSArray *)allAppIdentifiers { 13 | static NSArray *allAppIdentifiers = nil; 14 | static dispatch_once_t predicate; 15 | 16 | dispatch_once(&predicate, ^{ 17 | NSMutableArray *array = [NSMutableArray array]; 18 | SBApplicationController *controller = [objc_getClass("SBApplicationController") sharedInstance]; 19 | NSSet *hiddenIdentifiers = [self hiddenIdentifiers]; 20 | 21 | for (NSString *bundleIdentifier in [controller allBundleIdentifiers]) { 22 | if (![hiddenIdentifiers containsObject:bundleIdentifier]) { 23 | [array addObject:bundleIdentifier]; 24 | } 25 | } 26 | 27 | allAppIdentifiers = [array copy]; 28 | }); 29 | 30 | return allAppIdentifiers; 31 | } 32 | 33 | + (NSString *)randomAppIdentifier { 34 | NSArray *identifiers = [self allAppIdentifiers]; 35 | return identifiers[arc4random() % [identifiers count]]; 36 | } 37 | 38 | // Thanks to AppList (https://github.com/rpetrich/AppList). 39 | + (NSSet *)hiddenIdentifiers { 40 | return [NSSet setWithObjects: 41 | @"com.apple.AdSheet", 42 | @"com.apple.AdSheetPhone", 43 | @"com.apple.AdSheetPad", 44 | @"com.apple.DataActivation", 45 | @"com.apple.DemoApp", 46 | @"com.apple.Diagnostics", 47 | @"com.apple.fieldtest", 48 | @"com.apple.iosdiagnostics", 49 | @"com.apple.iphoneos.iPodOut", 50 | @"com.apple.TrustMe", 51 | @"com.apple.WebSheet", 52 | @"com.apple.springboard", 53 | @"com.apple.purplebuddy", 54 | @"com.apple.datadetectors.DDActionsService", 55 | @"com.apple.FacebookAccountMigrationDialog", 56 | @"com.apple.iad.iAdOptOut", 57 | @"com.apple.ios.StoreKitUIService", 58 | @"com.apple.TextInput.kbd", 59 | @"com.apple.MailCompositionService", 60 | @"com.apple.mobilesms.compose", 61 | @"com.apple.quicklook.quicklookd", 62 | @"com.apple.ShoeboxUIService", 63 | @"com.apple.social.remoteui.SocialUIService", 64 | @"com.apple.WebViewService", 65 | @"com.apple.gamecenter.GameCenterUIService", 66 | @"com.apple.appleaccount.AACredentialRecoveryDialog", 67 | @"com.apple.CompassCalibrationViewService", 68 | @"com.apple.WebContentFilter.remoteUI.WebContentAnalysisUI", 69 | @"com.apple.PassbookUIService", 70 | @"com.apple.uikit.PrintStatus", 71 | @"com.apple.Copilot", 72 | @"com.apple.MusicUIService", 73 | @"com.apple.AccountAuthenticationDialog", 74 | @"com.apple.MobileReplayer", 75 | @"com.apple.SiriViewService", 76 | @"com.apple.TencentWeiboAccountMigrationDialog", 77 | // iOS 8. 78 | @"com.apple.AskPermissionUI", 79 | @"com.apple.CoreAuthUI", 80 | @"com.apple.family", 81 | @"com.apple.mobileme.fmip1", 82 | @"com.apple.GameController", 83 | @"com.apple.HealthPrivacyService", 84 | @"com.apple.InCallService", 85 | @"com.apple.mobilesms.notification", 86 | @"com.apple.PhotosViewService", 87 | @"com.apple.PreBoard", 88 | @"com.apple.PrintKit.Print-Center", 89 | @"com.apple.share", 90 | @"com.apple.SharedWebCredentialViewService", 91 | @"com.apple.webapp", 92 | @"com.apple.webapp1", 93 | nil]; 94 | } 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /CBRReadabilityManager.m: -------------------------------------------------------------------------------- 1 | #import "CBRReadabilityManager.h" 2 | 3 | static CFStringRef kUseLightTextNotification = CFSTR("ColorBanners_Readability_Light"); 4 | static CFStringRef kUseDarkTextNotification = CFSTR("ColorBanners_Readability_Dark"); 5 | static CFStringRef kPrefsAppID = CFSTR("com.golddavid.colorbanners"); 6 | static CFStringRef kPrefsUseDarkTextKey = CFSTR("Readability_UseDarkText"); 7 | 8 | @implementation CBRReadabilityManager 9 | 10 | static void callBack(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, 11 | CFDictionaryRef userInfo) { 12 | CBRReadabilityManager *self = (CBRReadabilityManager *)observer; 13 | NSString *notificationName = (NSString *)name; 14 | 15 | self.shouldUseDarkText = [notificationName isEqualToString:(NSString *)kUseDarkTextNotification]; 16 | } 17 | 18 | static void notify(BOOL useDarkText) { 19 | CFStringRef notification = (useDarkText) ? kUseDarkTextNotification : kUseLightTextNotification; 20 | CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), 21 | notification, 22 | NULL, 23 | NULL, 24 | true); 25 | } 26 | 27 | + (instancetype)sharedInstance { 28 | static dispatch_once_t predicate; 29 | static CBRReadabilityManager *manager; 30 | dispatch_once(&predicate, ^{ manager = [[CBRReadabilityManager alloc] init]; }); 31 | return manager; 32 | } 33 | 34 | - (instancetype)init { 35 | self = [super init]; 36 | if (self) { 37 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), 38 | self, 39 | &callBack, 40 | kUseDarkTextNotification, 41 | NULL, 42 | 0); 43 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), 44 | self, 45 | &callBack, 46 | kUseLightTextNotification, 47 | NULL, 48 | 0); 49 | [self refresh]; 50 | } 51 | return self; 52 | } 53 | 54 | - (void)setShouldUseDarkText:(BOOL)useDarkText { 55 | if (_shouldUseDarkText != useDarkText) { 56 | _shouldUseDarkText = useDarkText; 57 | [self.delegate managersReadabilityStateDidChange:self]; 58 | } 59 | } 60 | 61 | - (void)dealloc { 62 | CFNotificationCenterRemoveEveryObserver(CFNotificationCenterGetDarwinNotifyCenter(), self); 63 | [super dealloc]; 64 | } 65 | 66 | - (void)refresh { 67 | CFPreferencesAppSynchronize(kPrefsAppID); 68 | Boolean keyExists = false; 69 | Boolean useDarkText = CFPreferencesGetAppBooleanValue(kPrefsUseDarkTextKey, 70 | kPrefsAppID, 71 | &keyExists); 72 | if (keyExists) { 73 | self.shouldUseDarkText = (BOOL)useDarkText; 74 | } 75 | } 76 | 77 | - (void)setShouldUseDarkTextAndSynchronize:(BOOL)useDarkText { 78 | if (_shouldUseDarkText != useDarkText) { 79 | _shouldUseDarkText = useDarkText; 80 | CFPreferencesSetAppValue(kPrefsUseDarkTextKey, @(useDarkText), kPrefsAppID); 81 | CFPreferencesAppSynchronize(kPrefsAppID); 82 | notify(useDarkText); 83 | } 84 | } 85 | @end 86 | -------------------------------------------------------------------------------- /colorbannersprefs/Resources/LockScreen.plist: -------------------------------------------------------------------------------- 1 | { 2 | title = "Lock Screen"; 3 | items = ( 4 | { 5 | cell = PSSwitchCell; 6 | label = "Enabled"; 7 | key = "LSEnabled"; 8 | default = 1; 9 | defaults = "com.golddavid.colorbanners"; 10 | PostNotification = "com.golddavid.colorbanners/reloadprefs-main"; 11 | }, 12 | 13 | { 14 | cell = PSGroupCell; 15 | }, 16 | { 17 | cell = PSSwitchCell; 18 | label = "Use Gradient"; 19 | key = "LSGradient"; 20 | default = 1; 21 | defaults = "com.golddavid.colorbanners"; 22 | PostNotification = "com.golddavid.colorbanners/reloadprefs"; 23 | }, 24 | { 25 | cell = PSSwitchCell; 26 | set = "setLSConstantColorsEnabled:forSpecifier:"; 27 | id = "CUSTOM_COLOR_MINUS_ONE"; 28 | label = "Use Constant Colors"; 29 | key = "LSUseConstant"; 30 | default = 0; 31 | defaults = "com.golddavid.colorbanners"; 32 | PostNotification = "com.golddavid.colorbanners/reloadprefs"; 33 | }, 34 | 35 | { 36 | cell = PSGroupCell; 37 | label = "Constant Colors"; 38 | id = "CUSTOM_COLOR_GROUP"; 39 | }, 40 | { 41 | cell = PSLinkCell; 42 | cellClass = PFColorCell; 43 | label = "Constant Background Color"; 44 | title = "Background Color"; 45 | color_key = "LSBackgroundColor"; 46 | color_defaults = "com.golddavid.colorbanners"; 47 | color_postNotification = "com.golddavid.colorbanners/reloadprefs-ls"; 48 | color_fallback = "#ffffff"; 49 | usesRGB = 1; 50 | usesAlpha = 0; 51 | }, 52 | 53 | { 54 | cell = PSGroupCell; 55 | label = "Notification Background Alpha"; 56 | }, 57 | { 58 | cell = PSSliderCell; 59 | key = "LSAlpha"; 60 | showValue = 1; 61 | min = 0; 62 | max = 1; 63 | default = 0.7; 64 | defaults = "com.golddavid.colorbanners"; 65 | PostNotification = "com.golddavid.colorbanners/reloadprefs"; 66 | }, 67 | 68 | { 69 | cell = PSGroupCell; 70 | footerText = "Remove the notification list's blur."; 71 | }, 72 | { 73 | cell = PSSwitchCell; 74 | label = "Show separators"; 75 | key = "ShowSeparators"; 76 | default = 0; 77 | defaults = "com.golddavid.colorbanners"; 78 | PostNotification = "com.golddavid.colorbanners/reloadprefs"; 79 | }, 80 | { 81 | cell = PSSwitchCell; 82 | label = "Disable dimming"; 83 | key = "DisableDimming"; 84 | default = 1; 85 | defaults = "com.golddavid.colorbanners"; 86 | PostNotification = "com.golddavid.colorbanners/reloadprefs"; 87 | }, 88 | { 89 | cell = PSSwitchCell; 90 | label = "Color Dismiss Button"; 91 | key = "ColorDismissButton"; 92 | default = 1; 93 | defaults = "com.golddavid.colorbanners"; 94 | PostNotification = "com.golddavid.colorbanners/reloadprefs"; 95 | }, 96 | { 97 | cell = PSSwitchCell; 98 | label = "Remove Blur"; 99 | key = "RemoveBlur"; 100 | default = 0; 101 | defaults = "com.golddavid.colorbanners"; 102 | PostNotification = "com.golddavid.colorbanners/reloadprefs"; 103 | }, 104 | 105 | { 106 | cell = PSGroupCell; 107 | footerText = "Enable this if you're using a low alpha level with a dark lockscreen wallpaper."; 108 | }, 109 | { 110 | cell = PSSwitchCell; 111 | label = "Prefer White Text"; 112 | key = "PrefersWhiteText"; 113 | default = 0; 114 | defaults = "com.golddavid.colorbanners"; 115 | PostNotification = "com.golddavid.colorbanners/reloadprefs"; 116 | } 117 | ); 118 | } 119 | -------------------------------------------------------------------------------- /colorbannersprefs/PSTableCell.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This header is generated by classdump-dyld 0.1 3 | * on Wednesday, November 27, 2013 at 11:21:53 PM Eastern European Standard Time 4 | * Operating System: Version 7.0.3 (Build 11B511) 5 | * Image Source: /System/Library/PrivateFrameworks/Preferences.framework/Preferences 6 | * classdump-dyld is free of use, Copyright © 2013 by Elias Limneos. 7 | */ 8 | 9 | #import 10 | 11 | @class UIImageView, NSString, PSSpecifier, UILongPressGestureRecognizer; 12 | 13 | @interface PSTableCell : UITableViewCell { 14 | 15 | id _value; 16 | UIImageView* _checkedImageView; 17 | BOOL _checked; 18 | BOOL _shouldHideTitle; 19 | NSString* _hiddenTitle; 20 | int _alignment; 21 | SEL _pAction; 22 | id _pTarget; 23 | BOOL _cellEnabled; 24 | PSSpecifier* _specifier; 25 | int _type; 26 | BOOL _lazyIcon; 27 | BOOL _lazyIconDontUnload; 28 | BOOL _lazyIconForceSynchronous; 29 | NSString* _lazyIconAppID; 30 | BOOL _reusedCell; 31 | BOOL _isCopyable; 32 | UILongPressGestureRecognizer* _longTapRecognizer; 33 | 34 | } 35 | 36 | @property (assign,nonatomic) int type; //@synthesize type=_type - In the implementation block 37 | @property (assign,nonatomic) BOOL reusedCell; //@synthesize reusedCell=_reusedCell - In the implementation block 38 | @property (assign,nonatomic) BOOL isCopyable; //@synthesize isCopyable=_isCopyable - In the implementation block 39 | @property (nonatomic,retain) PSSpecifier * specifier; //@synthesize specifier=_specifier - In the implementation block 40 | @property (nonatomic,retain) UILongPressGestureRecognizer * longTapRecognizer; //@synthesize longTapRecognizer=_longTapRecognizer - In the implementation block 41 | +(int)cellStyle; 42 | +(id)reuseIdentifierForSpecifier:(id)arg1 ; 43 | +(Class)cellClassForSpecifier:(id)arg1 ; 44 | +(id)stringFromCellType:(int)arg1 ; 45 | +(id)reuseIdentifierForClassAndType:(int)arg1 ; 46 | +(id)reuseIdentifierForBasicCellTypes:(int)arg1 ; 47 | +(int)cellTypeFromString:(id)arg1 ; 48 | -(id)specifier; 49 | -(id)valueLabel; 50 | -(void)dealloc; 51 | -(void)layoutSubviews; 52 | -(void)setChecked:(BOOL)arg1 ; 53 | -(void)setTitle:(id)arg1 ; 54 | -(BOOL)canPerformAction:(SEL)arg1 withSender:(id)arg2 ; 55 | -(void)setTarget:(id)arg1 ; 56 | -(void)setType:(int)arg1 ; 57 | -(int)type; 58 | -(SEL)action; 59 | -(void)setValue:(id)arg1 ; 60 | -(id)_automationID; 61 | -(void)setAlignment:(int)arg1 ; 62 | -(id)scriptingInfoWithChildren; 63 | -(id)value; 64 | -(BOOL)canBecomeFirstResponder; 65 | -(id)target; 66 | -(id)title; 67 | -(id)titleLabel; 68 | -(void)setHighlighted:(BOOL)arg1 animated:(BOOL)arg2 ; 69 | -(void)setSelected:(BOOL)arg1 animated:(BOOL)arg2 ; 70 | -(void)prepareForReuse; 71 | -(id)_contentString; 72 | -(void)setAction:(SEL)arg1 ; 73 | -(void)copy:(id)arg1 ; 74 | -(void)setIcon:(id)arg1 ; 75 | -(float)textFieldOffset; 76 | -(BOOL)isChecked; 77 | -(id)iconImageView; 78 | -(void)setCellEnabled:(BOOL)arg1 ; 79 | -(BOOL)cellEnabled; 80 | -(BOOL)canReload; 81 | -(void)reloadWithSpecifier:(id)arg1 animated:(BOOL)arg2 ; 82 | -(id)initWithStyle:(int)arg1 reuseIdentifier:(id)arg2 specifier:(id)arg3 ; 83 | -(void)setReusedCell:(BOOL)arg1 ; 84 | -(void)refreshCellContentsWithSpecifier:(id)arg1 ; 85 | -(void)forceSynchronousIconLoadOnNextIconLoad; 86 | -(void)cellRemovedFromView; 87 | -(BOOL)canBeChecked; 88 | -(id)_copyableText; 89 | -(void)longPressed:(id)arg1 ; 90 | -(void)setShouldHideTitle:(BOOL)arg1 ; 91 | -(id)blankIcon; 92 | -(id)getLazyIcon; 93 | -(id)getLazyIconID; 94 | -(void)setValueChangedTarget:(id)arg1 action:(SEL)arg2 specifier:(id)arg3 ; 95 | -(void)setCellTarget:(id)arg1 ; 96 | -(void)setCellAction:(SEL)arg1 ; 97 | -(id)cellTarget; 98 | -(SEL)cellAction; 99 | -(id)titleTextLabel; 100 | -(id)getIcon; 101 | -(BOOL)reusedCell; 102 | -(BOOL)isCopyable; 103 | -(void)setIsCopyable:(BOOL)arg1 ; 104 | -(id)longTapRecognizer; 105 | @end 106 | -------------------------------------------------------------------------------- /colorbannersprefs/Resources/Banners.plist: -------------------------------------------------------------------------------- 1 | { 2 | title = "Banners"; 3 | items = ( 4 | { 5 | cell = PSSwitchCell; 6 | label = "Enabled"; 7 | key = "BannersEnabled"; 8 | default = 1; 9 | defaults = "com.golddavid.colorbanners"; 10 | PostNotification = "com.golddavid.colorbanners/reloadprefs-main"; 11 | }, 12 | 13 | { 14 | cell = PSGroupCell; 15 | }, 16 | { 17 | cell = PSSwitchCell; 18 | label = "Use Gradient"; 19 | key = "BannerGradient"; 20 | default = 1; 21 | defaults = "com.golddavid.colorbanners"; 22 | PostNotification = "com.golddavid.colorbanners/reloadprefs"; 23 | }, 24 | { 25 | cell = PSSwitchCell; 26 | set = "setBannerConstantColorsEnabled:forSpecifier:"; 27 | id = "CUSTOM_COLOR_MINUS_ONE"; 28 | label = "Use Constant Colors"; 29 | key = "BannerUseConstant"; 30 | default = 0; 31 | defaults = "com.golddavid.colorbanners"; 32 | PostNotification = "com.golddavid.colorbanners/reloadprefs"; 33 | }, 34 | 35 | { 36 | cell = PSGroupCell; 37 | label = "Constant Colors"; 38 | id = "CUSTOM_COLOR_GROUP"; 39 | }, 40 | { 41 | cell = PSLinkCell; 42 | cellClass = PFColorCell; 43 | label = "Constant Background Color"; 44 | title = "Background Color"; 45 | color_key = "BannerBackgroundColor"; 46 | color_defaults = "com.golddavid.colorbanners"; 47 | color_postNotification = "com.golddavid.colorbanners/reloadprefs-banners"; 48 | color_fallback = "#ffffff"; 49 | usesRGB = 1; 50 | usesAlpha = 0; 51 | }, 52 | 53 | { 54 | cell = PSGroupCell; 55 | label = "Banner Background Alpha"; 56 | }, 57 | { 58 | cell = PSSliderCell; 59 | key = "BannerAlpha"; 60 | showValue = 1; 61 | min = 0; 62 | max = 1; 63 | default = 0.7; 64 | defaults = "com.golddavid.colorbanners"; 65 | PostNotification = "com.golddavid.colorbanners/reloadprefs"; 66 | }, 67 | 68 | { 69 | cell = PSGroupCell; 70 | id = "AL GORE"; 71 | label = "AlGoreithmic Options"; 72 | footerText = "Analyzes the view located below the banner when deciding the text color. Use this if you have a fairly low alpha level."; 73 | }, 74 | { 75 | cell = PSSwitchCell; 76 | set = "setDeepBannerAnalysisEnabled:forSpecifier:"; 77 | id = "LIVE_ANALYSIS_MINUS_ONE"; 78 | label = "Analyze Below Banner"; 79 | key = "WantsDeepBannerAnalyzing"; 80 | default = 1; 81 | defaults = "com.golddavid.colorbanners"; 82 | PostNotification = "com.golddavid.colorbanners/reloadprefs"; 83 | }, 84 | { 85 | cell = PSSwitchCell; 86 | id = "LIVE_ANALYSIS_CELL"; 87 | label = "Live Analysis"; 88 | key = "WantsLiveAnalysis"; 89 | default = 1; 90 | defaults = "com.golddavid.colorbanners"; 91 | PostNotification = "com.golddavid.colorbanners/reloadprefs"; 92 | }, 93 | 94 | { 95 | cell = PSGroupCell; 96 | footerText = "Hides the QuickReply rounded-rectangular text field."; 97 | }, 98 | { 99 | cell = PSSwitchCell; 100 | label = "Round Corners"; 101 | key = "RoundCorners"; 102 | default = 0; 103 | defaults = "com.golddavid.colorbanners"; 104 | PostNotification = "com.golddavid.colorbanners/reloadprefs"; 105 | }, 106 | { 107 | cell = PSSwitchCell; 108 | label = "Remove Banner Blur"; 109 | key = "RemoveBannersBlur"; 110 | default = 0; 111 | defaults = "com.golddavid.colorbanners"; 112 | PostNotification = "com.golddavid.colorbanners/reloadprefs"; 113 | }, 114 | { 115 | cell = PSSwitchCell; 116 | label = "Hide Grabber"; 117 | key = "HideGrabber"; 118 | default = 0; 119 | defaults = "com.golddavid.colorbanners"; 120 | PostNotification = "com.golddavid.colorbanners/reloadprefs"; 121 | }, 122 | { 123 | cell = PSSwitchCell; 124 | label = "Hide QR rounded-rect"; 125 | key = "HideQRRect"; 126 | default = 0; 127 | defaults = "com.golddavid.colorbanners"; 128 | PostNotification = "com.golddavid.colorbanners/reloadprefs"; 129 | } 130 | ); 131 | } 132 | -------------------------------------------------------------------------------- /UIColor+ColorBanners.m: -------------------------------------------------------------------------------- 1 | // Adapted from https://github.com/thisandagain/color. 2 | 3 | #import "UIColor+ColorBanners.h" 4 | 5 | static CGFloat clamp(CGFloat x) { 6 | return (x > 1.0) ? 1.0 : ((x < 0.0) ? 0.0 : x); 7 | } 8 | 9 | // HSL to RGB converter. 10 | static void hsl_to_rgb(CGFloat h, CGFloat s, CGFloat l, CGFloat *outR, CGFloat *outG, CGFloat *outB) { 11 | CGFloat temp1, temp2; 12 | CGFloat temp[3]; 13 | int i; 14 | 15 | // Check for saturation. If there isn't any, just return the luminance value for each, which results in gray. 16 | if(s == 0.0) { 17 | if(outR) { 18 | *outR = l; 19 | } 20 | if(outG) { 21 | *outG = l; 22 | } 23 | if(outB) { 24 | *outB = l; 25 | } 26 | return; 27 | } 28 | 29 | // Test for luminance and compute temporary values based on luminance and saturation. 30 | if(l < 0.5) { 31 | temp2 = l * (1.0 + s); 32 | } 33 | else { 34 | temp2 = l + s - l * s; 35 | } 36 | 37 | temp1 = 2.0 * l - temp2; 38 | 39 | // Compute intermediate values based on hue. 40 | temp[0] = h + 1.0 / 3.0; 41 | temp[1] = h; 42 | temp[2] = h - 1.0 / 3.0; 43 | 44 | for(i = 0; i < 3; ++i) { 45 | // Adjust the range. 46 | if(temp[i] < 0.0) { 47 | temp[i] += 1.0; 48 | } 49 | if(temp[i] > 1.0) { 50 | temp[i] -= 1.0; 51 | } 52 | 53 | if(6.0 * temp[i] < 1.0) { 54 | temp[i] = temp1 + (temp2 - temp1) * 6.0 * temp[i]; 55 | } else { 56 | if(2.0 * temp[i] < 1.0) { 57 | temp[i] = temp2; 58 | } else { 59 | if(3.0 * temp[i] < 2.0) { 60 | temp[i] = temp1 + (temp2 - temp1) * ((2.0 / 3.0) - temp[i]) * 6.0; 61 | } 62 | else { 63 | temp[i] = temp1; 64 | } 65 | } 66 | } 67 | } 68 | 69 | // Assign temporary values to R, G, B. 70 | if(outR) { 71 | *outR = temp[0]; 72 | } 73 | if(outG) { 74 | *outG = temp[1]; 75 | } 76 | if(outB) { 77 | *outB = temp[2]; 78 | } 79 | } 80 | 81 | // RGB to HSL converter. 82 | static void rgb_to_hsl(CGFloat r, CGFloat g, CGFloat b, CGFloat *outH, CGFloat *outS, CGFloat *outL) { 83 | CGFloat h, s, l, v, m, vm, r2, g2, b2; 84 | 85 | h = 0; s = 0; 86 | v = MAX(r, g); 87 | v = MAX(v, b); 88 | m = MIN(r, g); 89 | m = MIN(m, b); 90 | 91 | l = (m + v) / 2.0f; 92 | 93 | if (l <= 0.0) { 94 | if(outH) { 95 | *outH = h; 96 | } 97 | if(outS) { 98 | *outS = s; 99 | } 100 | if(outL) { 101 | *outL = l; 102 | } 103 | return; 104 | } 105 | 106 | vm = v - m; 107 | s = vm; 108 | 109 | if (s > 0.0f) { 110 | s /= (l <= 0.5f) ? (v + m) : (2.0 - v - m); 111 | } else { 112 | if(outH) { 113 | *outH = h; 114 | } 115 | if(outS) { 116 | *outS = s; 117 | } 118 | if(outL) { 119 | *outL = l; 120 | } 121 | return; 122 | } 123 | 124 | r2 = (v - r) / vm; 125 | g2 = (v - g) / vm; 126 | b2 = (v - b) / vm; 127 | 128 | if (r == v){ 129 | h = (g == m ? 5.0f + b2 : 1.0f - g2); 130 | }else if (g == v){ 131 | h = (b == m ? 1.0f + r2 : 3.0 - b2); 132 | }else{ 133 | h = (r == m ? 3.0f + g2 : 5.0f - r2); 134 | } 135 | 136 | h /= 6.0f; 137 | 138 | if(outH) { 139 | *outH = h; 140 | } 141 | if(outS) { 142 | *outS = s; 143 | } 144 | if(outL) { 145 | *outL = l; 146 | } 147 | } 148 | 149 | @implementation UIColor(ColorBanners) 150 | 151 | + (UIColor *)cbr_colorWithHue:(CGFloat)hue saturation:(CGFloat)saturation lightness:(CGFloat)lightness alpha:(CGFloat)alpha { 152 | CGFloat r, g, b; 153 | hsl_to_rgb(hue, saturation, lightness, &r, &g, &b); 154 | return [UIColor colorWithRed:r green:g blue:b alpha:alpha]; 155 | } 156 | 157 | - (void)cbr_getHue:(CGFloat *)hue saturation:(CGFloat *)saturation lightness:(CGFloat *)lightness alpha:(CGFloat *)alpha { 158 | CGFloat r, g, b; 159 | [self getRed:&r green:&g blue:&b alpha:alpha]; 160 | rgb_to_hsl(r, g, b, hue, saturation, lightness); 161 | } 162 | 163 | - (UIColor *)cbr_offsetWithHue:(CGFloat)hue saturation:(CGFloat)saturation lightness:(CGFloat)lightness alpha:(CGFloat)alpha { 164 | CGFloat h, s, l, a; 165 | [self cbr_getHue:&h saturation:&s lightness:&l alpha:&a]; 166 | 167 | h = fmodf(hue + h, 1.0f); 168 | s = clamp(saturation + s); 169 | l = clamp(lightness + l); 170 | a = clamp(alpha + a); 171 | 172 | return [UIColor cbr_colorWithHue:h saturation:s lightness:l alpha:a]; 173 | } 174 | 175 | - (UIColor *)cbr_lighten:(CGFloat)amount { 176 | return [self cbr_offsetWithHue:0.0f saturation:0.0f lightness:amount alpha:0.0f]; 177 | } 178 | 179 | - (UIColor *)cbr_darken:(CGFloat)amount { 180 | return [self cbr_offsetWithHue:0.0f saturation:0.0f lightness:-amount alpha:0.0f]; 181 | } 182 | 183 | @end 184 | -------------------------------------------------------------------------------- /colorbannersprefs/PSSpecifier.h: -------------------------------------------------------------------------------- 1 | /* Generated by RuntimeBrowser 2 | Image: /System/Library/PrivateFrameworks/Preferences.framework/Preferences 3 | */ 4 | 5 | #import 6 | #import 7 | #import 8 | 9 | //@class CNFRegAlias, IMAccount, NSArray, NSDictionary, NSMutableDictionary, NSString; 10 | 11 | typedef enum PSTableCellType { 12 | PSGroupCell, 13 | PSLinkCell, 14 | PSLinkListCell, 15 | PSListItemCell, 16 | PSTitleValueCell, 17 | PSSliderCell, 18 | PSSwitchCell, 19 | PSStaticTextCell, 20 | PSEditTextCell, 21 | PSSegmentCell, 22 | PSGiantIconCell, 23 | PSGiantCell, 24 | PSSecureEditTextCell, 25 | PSButtonCell, 26 | PSEditTextViewCell 27 | } PSSpecifierType; 28 | 29 | 30 | @interface PSSpecifier : NSObject { 31 | SEL _buttonAction; 32 | SEL _confirmationAction; 33 | SEL _confirmationCancelAction; 34 | SEL _controllerLoadAction; 35 | NSString *_name; 36 | NSMutableDictionary *_properties; 37 | NSDictionary *_shortTitleDict; 38 | BOOL _showContentString; 39 | NSDictionary *_titleDict; 40 | id _userInfo; 41 | NSArray *_values; 42 | SEL action; 43 | int autoCapsType; 44 | int autoCorrectionType; 45 | SEL cancel; 46 | int cellType; 47 | Class detailControllerClass; 48 | Class editPaneClass; 49 | SEL getter; 50 | int keyboardType; 51 | SEL setter; 52 | id target; 53 | unsigned int textFieldType; 54 | } 55 | 56 | //@property (retain) IMAccount * CNFRegAccount; 57 | //@property (retain) CNFRegAlias * CNFRegAlias; 58 | //@property (retain) CNFRegAlias * CNFRegCallerIdAlias; 59 | @property (assign) SEL buttonAction; 60 | @property (assign) int cellType; 61 | @property (assign) SEL confirmationAction; 62 | @property (assign) SEL confirmationCancelAction; 63 | @property (assign) SEL controllerLoadAction; 64 | @property (assign) Class detailControllerClass; 65 | @property (assign) Class editPaneClass; 66 | @property (retain) NSString * identifier; 67 | @property (retain) NSString * name; 68 | @property (retain) NSDictionary * shortTitleDictionary; 69 | @property (assign) BOOL showContentString; 70 | @property (assign) id target; 71 | @property (retain) NSDictionary * titleDictionary; 72 | @property (retain) id userInfo; 73 | @property (retain) NSArray * values; 74 | 75 | + (id)_dataclassToBundleId; 76 | + (id)acui_linkListCellSpecifierForDataclass:(id)arg1 target:(id)arg2 set:(SEL)arg3 get:(SEL)arg4 detail:(Class)arg5; 77 | + (id)acui_specifierForAppWithBundleID:(id)arg1 target:(id)arg2 set:(SEL)arg3 get:(SEL)arg4; 78 | + (id)acui_specifierForDataclass:(id)arg1 target:(id)arg2 set:(SEL)arg3 get:(SEL)arg4; 79 | + (int)autoCapsTypeForString:(id)arg1; 80 | + (int)autoCorrectionTypeForNumber:(id)arg1; 81 | + (id)buttonSpecifierWithTitle:(id)arg1 target:(id)arg2 action:(SEL)arg3 confirmationInfo:(id)arg4; 82 | + (id)deleteButtonSpecifierWithName:(id)arg1 target:(id)arg2 action:(SEL)arg3; 83 | + (id)emptyGroupSpecifier; 84 | + (id)groupSpecifierWithFooterLinkButton:(id)arg1; 85 | + (id)groupSpecifierWithFooterText:(id)arg1 linkButton:(id)arg2; 86 | + (id)groupSpecifierWithFooterText:(id)arg1 linkButtons:(id)arg2; 87 | + (id)groupSpecifierWithHeader:(id)arg1 footer:(id)arg2 linkButtons:(id)arg3; 88 | + (id)groupSpecifierWithHeader:(id)arg1 footer:(id)arg2; 89 | + (id)groupSpecifierWithName:(id)arg1; 90 | + (int)keyboardTypeForString:(id)arg1; 91 | + (id)preferenceSpecifierNamed:(id)arg1 target:(id)arg2 set:(SEL)arg3 get:(SEL)arg4 detail:(Class)arg5 cell:(int)arg6 edit:(Class)arg7; 92 | + (id)switchSpecifierWithTitle:(id)arg1 target:(id)arg2 setter:(SEL)arg3 getter:(SEL)arg4 key:(id)arg5; 93 | 94 | - (id)CNFRegAccount; 95 | - (id)CNFRegAlias; 96 | - (id)CNFRegCallerIdAlias; 97 | - (id)acui_appBundleID; 98 | - (id)acui_dataclass; 99 | - (SEL)buttonAction; 100 | - (int)cellType; 101 | - (SEL)confirmationAction; 102 | - (SEL)confirmationCancelAction; 103 | - (SEL)controllerLoadAction; 104 | - (void)dealloc; 105 | - (id)description; 106 | - (Class)detailControllerClass; 107 | - (Class)editPaneClass; 108 | - (id)identifier; 109 | - (id)init; 110 | - (void)loadValuesAndTitlesFromDataSource; 111 | - (id)name; 112 | - (id)properties; 113 | - (id)propertyForKey:(id)arg1; 114 | - (void)removePropertyForKey:(id)arg1; 115 | - (void)setButtonAction:(SEL)arg1; 116 | - (void)setCNFRegAccount:(id)arg1; 117 | - (void)setCNFRegAlias:(id)arg1; 118 | - (void)setCNFRegCallerIdAlias:(id)arg1; 119 | - (void)setCellType:(int)arg1; 120 | - (void)setConfirmationAction:(SEL)arg1; 121 | - (void)setConfirmationCancelAction:(SEL)arg1; 122 | - (void)setControllerLoadAction:(SEL)arg1; 123 | - (void)setDetailControllerClass:(Class)arg1; 124 | - (void)setEditPaneClass:(Class)arg1; 125 | - (void)setKeyboardType:(int)arg1 autoCaps:(int)arg2 autoCorrection:(int)arg3; 126 | - (void)setProperties:(id)arg1; 127 | - (void)setProperty:(id)arg1 forKey:(id)arg2; 128 | - (void)setShowContentString:(BOOL)arg1; 129 | - (void)setTarget:(id)arg1; 130 | - (void)setUserInfo:(id)arg1; 131 | - (void)setValues:(id)arg1 titles:(id)arg2 shortTitles:(id)arg3 usingLocalizedTitleSorting:(BOOL)arg4; 132 | - (void)setValues:(id)arg1 titles:(id)arg2 shortTitles:(id)arg3; 133 | - (void)setValues:(id)arg1 titles:(id)arg2; 134 | - (void)setupIconImageWithBundle:(id)arg1; 135 | - (void)setupIconImageWithPath:(id)arg1; 136 | - (id)shortTitleDictionary; 137 | - (BOOL)showContentString; 138 | - (id)target; 139 | - (int)titleCompare:(id)arg1; 140 | - (id)titleDictionary; 141 | - (id)userInfo; 142 | - (id)values; 143 | 144 | @end -------------------------------------------------------------------------------- /CBRPrefsManager.m: -------------------------------------------------------------------------------- 1 | #import "CBRPrefsManager.h" 2 | 3 | #import "Defines.h" 4 | #import "NSDistributedNotificationCenter.h" 5 | 6 | #define PREFS_NAME "com.golddavid.colorbanners" 7 | 8 | #define BANNERS_KEY @"BannersEnabled" 9 | #define BANNERS_GRADIENT_KEY @"BannerGradient" 10 | #define BANNER_ALPHA_KEY @"BannerAlpha" 11 | #define BANNER_BG_KEY @"BannerBackgroundColor" 12 | #define BANNER_CONSTANT_KEY @"BannerUseConstant" 13 | 14 | #define BANNER_DEEP_ANALYSIS_KEY @"WantsDeepBannerAnalyzing" 15 | #define BANNER_LIVE_ANALYSIS_KEY @"WantsLiveAnalysis" 16 | #define BANNERS_BLUR_KEY @"RemoveBannersBlur" 17 | #define RECT_KEY @"HideQRRect" 18 | #define GRABBER_KEY @"HideGrabber" 19 | 20 | #define LS_KEY @"LSEnabled" 21 | #define LS_GRADIENT_KEY @"LSGradient" 22 | #define LS_ALPHA_KEY @"LSAlpha" 23 | #define LS_BG_KEY @"LSBackgroundColor" 24 | #define LS_CONSTANT_KEY @"LSUseConstant" 25 | 26 | #define CORNERS_KEY @"RoundCorners" 27 | #define BLUR_KEY @"RemoveBlur" 28 | #define SEPARATORS_KEY @"ShowSeparators" 29 | #define DIMMING_KEY @"DisableDimming" 30 | #define COLOR_BUTTON_KEY @"ColorDismissButton" 31 | #define WHITE_TEXT_KEY @"PrefersWhiteText" 32 | 33 | #define NC_KEY @"NCEnabled" 34 | #define NC_GRADIENT_KEY @"NCGradient" 35 | #define NC_ALPHA_KEY @"NCAlpha" 36 | #define NC_BG_KEY @"NCBackgroundColor" 37 | #define NC_CONSTANT_KEY @"NCUseConstant" 38 | 39 | // From ColorBadges.h. 40 | #define GETRED(rgb) ((rgb >> 16) & 0xFF) 41 | #define GETGREEN(rgb) ((rgb >> 8) & 0xFF) 42 | #define GETBLUE(rgb) (rgb & 0xFF) 43 | 44 | // Default to white. 45 | #define DEFAULT_COLOR 0xFFFFFF 46 | 47 | // Expected format: #. 48 | static int RGBColorFromNSString(NSString *str) { 49 | unsigned hexColor = DEFAULT_COLOR; 50 | NSScanner *scanner = [NSScanner scannerWithString:str]; 51 | [scanner setScanLocation:1]; // Skip over the '#'. 52 | [scanner scanHexInt:&hexColor]; 53 | return (int)hexColor; 54 | } 55 | 56 | @implementation CBRPrefsManager 57 | 58 | + (instancetype)sharedInstance { 59 | static dispatch_once_t onceToken; 60 | static CBRPrefsManager *cache; 61 | dispatch_once(&onceToken, ^{ cache = [[CBRPrefsManager alloc] init]; } ); 62 | return cache; 63 | } 64 | 65 | - (instancetype)init { 66 | self = [super init]; 67 | if (self) { 68 | [self reload]; 69 | [[NSDistributedNotificationCenter defaultCenter] addObserver:self 70 | selector:@selector(reload) 71 | name:INTERNAL_NOTIFICATION_NAME 72 | object:nil]; 73 | } 74 | return self; 75 | } 76 | 77 | - (NSDictionary *)prefsDictionary { 78 | CFStringRef appID = CFSTR(PREFS_NAME); 79 | CFArrayRef keyList = CFPreferencesCopyKeyList(appID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); 80 | if (!keyList) { 81 | CBRLOG(@"Unable to obtain preferences keyList!"); 82 | return nil; 83 | } 84 | NSDictionary *dictionary = (NSDictionary *)CFPreferencesCopyMultiple(keyList, appID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost); 85 | CFRelease(keyList); 86 | return [dictionary autorelease]; 87 | } 88 | 89 | - (void)reload { 90 | NSDictionary *prefs = [self prefsDictionary]; 91 | 92 | _bannersEnabled = [self boolForValue:prefs[BANNERS_KEY] withDefault:YES]; 93 | _useBannerGradient = [self boolForValue:prefs[BANNERS_GRADIENT_KEY] withDefault:YES]; 94 | _bannerAlpha = [self floatForValue:prefs[BANNER_ALPHA_KEY] withDefault:0.7]; 95 | _bannerBackgroundColor = [self rgbColorForNSString:prefs[BANNER_BG_KEY] withDefault:DEFAULT_COLOR]; 96 | _bannersUseConstantColor = [self boolForValue:prefs[BANNER_CONSTANT_KEY] withDefault:NO]; 97 | 98 | _wantsDeepBannerAnalyzing = [self boolForValue:prefs[BANNER_DEEP_ANALYSIS_KEY] withDefault:YES]; 99 | _wantsLiveAnalysis = [self boolForValue:prefs[BANNER_LIVE_ANALYSIS_KEY] withDefault:YES]; 100 | _removeBannersBlur = [self boolForValue:prefs[BANNERS_BLUR_KEY] withDefault:NO]; 101 | _hideQRRect = [self boolForValue:prefs[RECT_KEY] withDefault:NO]; 102 | _hideGrabber = [self boolForValue:prefs[GRABBER_KEY] withDefault:NO]; 103 | 104 | _lsEnabled = [self boolForValue:prefs[LS_KEY] withDefault:YES]; 105 | _useLSGradient = [self boolForValue:prefs[LS_GRADIENT_KEY] withDefault:YES]; 106 | _lsAlpha = [self floatForValue:prefs[LS_ALPHA_KEY] withDefault:0.7]; 107 | _lsBackgroundColor = [self rgbColorForNSString:prefs[LS_BG_KEY] withDefault:DEFAULT_COLOR]; 108 | _lsUseConstantColor = [self boolForValue:prefs[LS_CONSTANT_KEY] withDefault:NO]; 109 | 110 | _roundCorners = [self boolForValue:prefs[CORNERS_KEY] withDefault:NO]; 111 | _removeLSBlur = [self boolForValue:prefs[BLUR_KEY] withDefault:NO]; 112 | _showSeparators = [self boolForValue:prefs[SEPARATORS_KEY] withDefault:NO]; 113 | _disableDimming = [self boolForValue:prefs[DIMMING_KEY] withDefault:YES]; 114 | _colorDismissButton = [self boolForValue:prefs[COLOR_BUTTON_KEY] withDefault:YES]; 115 | _prefersWhiteText = [self boolForValue:prefs[WHITE_TEXT_KEY] withDefault:NO]; 116 | 117 | _ncEnabled = [self boolForValue:prefs[NC_KEY] withDefault:YES]; 118 | _useNCGradient = [self boolForValue:prefs[NC_GRADIENT_KEY] withDefault:YES]; 119 | _ncAlpha = [self floatForValue:prefs[NC_ALPHA_KEY] withDefault:0.7]; 120 | _ncBackgroundColor = [self rgbColorForNSString:prefs[NC_BG_KEY] withDefault:DEFAULT_COLOR]; 121 | _ncUseConstantColor = [self boolForValue:prefs[NC_CONSTANT_KEY] withDefault:NO]; 122 | } 123 | 124 | - (BOOL)boolForValue:(NSNumber *)value withDefault:(BOOL)defaultValue { 125 | return (value) ? [value boolValue] : defaultValue; 126 | } 127 | 128 | - (CGFloat)floatForValue:(NSNumber *)value withDefault:(CGFloat)defaultValue { 129 | return (value) ? (CGFloat)[value floatValue] : defaultValue; 130 | } 131 | 132 | - (int)rgbColorForNSString:(NSString *)string withDefault:(int)defaultValue { 133 | return (string) ? RGBColorFromNSString(string) : defaultValue; 134 | } 135 | 136 | - (void)dealloc { 137 | [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:INTERNAL_NOTIFICATION_NAME object:nil]; 138 | [super dealloc]; 139 | } 140 | 141 | @end 142 | -------------------------------------------------------------------------------- /colorbannersprefs/PSListController.h: -------------------------------------------------------------------------------- 1 | /* Generated by RuntimeBrowser 2 | Image: /System/Library/PrivateFrameworks/Preferences.framework/Preferences 3 | */ 4 | 5 | #import "PSViewController.h" 6 | 7 | #import 8 | #import 9 | 10 | @class NSArray, NSMutableArray, NSMutableDictionary, NSString, UIActionSheet, UIAlertView, UIKeyboard, UIPopoverController, UITableView, UIView; 11 | 12 | @interface PSListController : PSViewController { 13 | 14 | /* 15 | struct CGPoint { 16 | float x; 17 | float y; 18 | UIActionSheet *_actionSheet; 19 | UIAlertView *_alertView; 20 | NSMutableArray *_bundleControllers; 21 | BOOL _bundlesLoaded; 22 | BOOL _cachesCells; 23 | NSMutableDictionary *_cells; 24 | UIView *_containerView; 25 | } _contentOffsetWithKeyboard; 26 | */ 27 | 28 | BOOL _edgeToEdgeCells; 29 | BOOL _forceSynchronousIconLoadForCreatedCells; 30 | NSMutableArray *_groups; 31 | BOOL _hasAppeared; 32 | //UIKeyboard *_keyboard; 33 | BOOL _keyboardWasVisible; 34 | NSString *_offsetItemName; 35 | BOOL _popupIsDismissing; 36 | BOOL _popupIsModal; 37 | // UIPopoverController *_popupStylePopoverController; 38 | BOOL _popupStylePopoverShouldRePresent; 39 | NSMutableArray *_prequeuedReusablePSTableCells; 40 | BOOL _reusesCells; 41 | BOOL _showingSetupController; 42 | NSString *_specifierID; 43 | NSArray *_specifiers; 44 | NSMutableDictionary *_specifiersByID; 45 | BOOL _swapAlertButtons; 46 | UITableView *_table; 47 | float _verticalContentOffset; 48 | } 49 | 50 | @property BOOL edgeToEdgeCells; 51 | @property BOOL forceSynchronousIconLoadForCreatedCells; 52 | 53 | + (BOOL)displaysButtonBar; 54 | 55 | - (void)_addIdentifierForSpecifier:(id)arg1; 56 | - (id)_createGroupIndices:(id)arg1; 57 | - (id)_customViewForSpecifier:(id)arg1 class:(Class)arg2 isHeader:(BOOL)arg3; 58 | - (BOOL)_getGroup:(int*)arg1 row:(int*)arg2 ofSpecifierAtIndex:(int)arg3 groups:(id)arg4; 59 | - (float)_getKeyboardIntersectionHeight; 60 | - (void)_handleActionSheet:(id)arg1 clickedButtonAtIndex:(int)arg2; 61 | - (void)_insertContiguousSpecifiers:(id)arg1 atIndex:(int)arg2 animated:(BOOL)arg3; 62 | - (void)_keyboardDidHide:(id)arg1; 63 | - (void)_keyboardWillHide:(id)arg1; 64 | - (void)_keyboardWillShow:(id)arg1; 65 | - (void)_loadBundleControllers; 66 | - (int)_nextGroupInSpecifiersAfterIndex:(int)arg1 inArray:(id)arg2; 67 | - (void)_removeContiguousSpecifiers:(id)arg1 animated:(BOOL)arg2; 68 | - (void)_removeIdentifierForSpecifier:(id)arg1; 69 | - (void)_returnKeyPressed:(id)arg1; 70 | - (void)_scrollToSpecifierNamed:(id)arg1; 71 | - (void)_setContentInset:(float)arg1; 72 | - (void)_setNotShowingSetupController; 73 | - (float)_tableView:(id)arg1 heightForCustomInSection:(int)arg2 isHeader:(BOOL)arg3; 74 | - (id)_tableView:(id)arg1 viewForCustomInSection:(int)arg2 isHeader:(BOOL)arg3; 75 | - (void)_unloadBundleControllers; 76 | - (void)actionSheet:(id)arg1 clickedButtonAtIndex:(NSInteger)arg2; 77 | - (void)actionSheet:(id)arg1 didDismissWithButtonIndex:(NSInteger)arg2; 78 | - (void)addSpecifier:(id)arg1 animated:(BOOL)arg2; 79 | - (void)addSpecifier:(id)arg1; 80 | - (void)addSpecifiersFromArray:(id)arg1 animated:(BOOL)arg2; 81 | - (void)addSpecifiersFromArray:(id)arg1; 82 | - (void)alertView:(id)arg1 clickedButtonAtIndex:(NSInteger)arg2; 83 | - (void)beginUpdates; 84 | - (id)bundle; 85 | - (id)cachedCellForSpecifier:(id)arg1; 86 | - (id)cachedCellForSpecifierID:(id)arg1; 87 | - (void)clearCache; 88 | - (void)confirmationViewAcceptedForSpecifier:(id)arg1; 89 | - (void)confirmationViewCancelledForSpecifier:(id)arg1; 90 | - (BOOL)containsSpecifier:(id)arg1; 91 | - (id)controllerForRowAtIndexPath:(id)arg1; 92 | - (id)controllerForSpecifier:(id)arg1; 93 | - (void)createGroupIndices; 94 | - (void)createPrequeuedPSTableCells:(unsigned int)arg1; 95 | - (void)dealloc; 96 | - (id)description; 97 | - (void)didRotateFromInterfaceOrientation:(int)arg1; 98 | - (void)dismissConfirmationViewForSpecifier:(id)arg1 animated:(BOOL)arg2; 99 | - (void)dismissPopover; 100 | - (void)dismissPopoverAnimated:(BOOL)arg1; 101 | - (BOOL)edgeToEdgeCells; 102 | - (void)endUpdates; 103 | - (id)findFirstVisibleResponder; 104 | - (BOOL)forceSynchronousIconLoadForCreatedCells; 105 | - (void)formSheetViewWillDisappear; 106 | - (BOOL)getGroup:(int*)arg1 row:(int*)arg2 ofSpecifier:(id)arg3; 107 | - (BOOL)getGroup:(int*)arg1 row:(int*)arg2 ofSpecifierAtIndex:(int)arg3; 108 | - (BOOL)getGroup:(int*)arg1 row:(int*)arg2 ofSpecifierID:(id)arg3; 109 | - (void)handleURL:(id)arg1; 110 | - (int)indexForIndexPath:(id)arg1; 111 | - (int)indexForRow:(int)arg1 inGroup:(int)arg2; 112 | - (int)indexOfGroup:(int)arg1; 113 | - (int)indexOfSpecifier:(id)arg1; 114 | - (int)indexOfSpecifierID:(id)arg1; 115 | - (id)indexPathForIndex:(int)arg1; 116 | - (id)indexPathForSpecifier:(id)arg1; 117 | - (id)init; 118 | - (id)initForContentSize:(CGSize)arg1; 119 | - (void)insertContiguousSpecifiers:(id)arg1 afterSpecifier:(id)arg2 animated:(BOOL)arg3; 120 | - (void)insertContiguousSpecifiers:(id)arg1 afterSpecifier:(id)arg2; 121 | - (void)insertContiguousSpecifiers:(id)arg1 afterSpecifierID:(id)arg2 animated:(BOOL)arg3; 122 | - (void)insertContiguousSpecifiers:(id)arg1 afterSpecifierID:(id)arg2; 123 | - (void)insertContiguousSpecifiers:(id)arg1 atEndOfGroup:(int)arg2 animated:(BOOL)arg3; 124 | - (void)insertContiguousSpecifiers:(id)arg1 atEndOfGroup:(int)arg2; 125 | - (void)insertContiguousSpecifiers:(id)arg1 atIndex:(int)arg2 animated:(BOOL)arg3; 126 | - (void)insertContiguousSpecifiers:(id)arg1 atIndex:(int)arg2; 127 | - (void)insertSpecifier:(id)arg1 afterSpecifier:(id)arg2 animated:(BOOL)arg3; 128 | - (void)insertSpecifier:(id)arg1 afterSpecifier:(id)arg2; 129 | - (void)insertSpecifier:(id)arg1 afterSpecifierID:(id)arg2 animated:(BOOL)arg3; 130 | - (void)insertSpecifier:(id)arg1 afterSpecifierID:(id)arg2; 131 | - (void)insertSpecifier:(id)arg1 atEndOfGroup:(int)arg2 animated:(BOOL)arg3; 132 | - (void)insertSpecifier:(id)arg1 atEndOfGroup:(int)arg2; 133 | - (void)insertSpecifier:(id)arg1 atIndex:(int)arg2 animated:(BOOL)arg3; 134 | - (void)insertSpecifier:(id)arg1 atIndex:(int)arg2; 135 | - (void)lazyLoadBundle:(id)arg1; 136 | - (id)loadSpecifiersFromPlistName:(id)arg1 target:(id)arg2; 137 | - (void)loadView; 138 | - (void)loseFocus; 139 | - (void)migrateSpecifierMetadataFrom:(id)arg1 to:(id)arg2; 140 | - (int)numberOfGroups; 141 | - (BOOL)performActionForSpecifier:(id)arg1; 142 | - (BOOL)performButtonActionForSpecifier:(id)arg1; 143 | - (BOOL)performConfirmationActionForSpecifier:(id)arg1; 144 | - (BOOL)performConfirmationCancelActionForSpecifier:(id)arg1; 145 | - (BOOL)performLoadActionForSpecifier:(id)arg1; 146 | - (void)popoverController:(id)arg1 animationCompleted:(int)arg2; 147 | - (BOOL)popoverControllerShouldDismissPopover:(id)arg1; 148 | - (id)popupStylePopoverController; 149 | - (void)popupViewWillDisappear; 150 | - (void)prepareSpecifiersMetadata; 151 | - (void)pushController:(id)arg1 animate:(BOOL)arg2; 152 | - (void)pushController:(id)arg1; 153 | - (void)reload; 154 | - (void)reloadIconForSpecifierForBundle:(id)arg1; 155 | - (void)reloadSpecifier:(id)arg1 animated:(BOOL)arg2; 156 | - (void)reloadSpecifier:(id)arg1; 157 | - (void)reloadSpecifierAtIndex:(int)arg1 animated:(BOOL)arg2; 158 | - (void)reloadSpecifierAtIndex:(int)arg1; 159 | - (void)reloadSpecifierID:(id)arg1 animated:(BOOL)arg2; 160 | - (void)reloadSpecifierID:(id)arg1; 161 | - (void)reloadSpecifiers; 162 | - (void)removeContiguousSpecifiers:(id)arg1 animated:(BOOL)arg2; 163 | - (void)removeContiguousSpecifiers:(id)arg1; 164 | - (void)removeLastSpecifier; 165 | - (void)removeLastSpecifierAnimated:(BOOL)arg1; 166 | - (void)removeSpecifier:(id)arg1 animated:(BOOL)arg2; 167 | - (void)removeSpecifier:(id)arg1; 168 | - (void)removeSpecifierAtIndex:(int)arg1 animated:(BOOL)arg2; 169 | - (void)removeSpecifierAtIndex:(int)arg1; 170 | - (void)removeSpecifierID:(id)arg1 animated:(BOOL)arg2; 171 | - (void)removeSpecifierID:(id)arg1; 172 | - (void)replaceContiguousSpecifiers:(id)arg1 withSpecifiers:(id)arg2 animated:(BOOL)arg3; 173 | - (void)replaceContiguousSpecifiers:(id)arg1 withSpecifiers:(id)arg2; 174 | - (void)returnPressedAtEnd; 175 | - (int)rowsForGroup:(int)arg1; 176 | - (void)selectRowForSpecifier:(id)arg1; 177 | - (void)setCachesCells:(BOOL)arg1; 178 | - (void)setDesiredVerticalContentOffset:(float)arg1; 179 | - (void)setDesiredVerticalContentOffsetItemNamed:(id)arg1; 180 | - (void)setEdgeToEdgeCells:(BOOL)arg1; 181 | - (void)setForceSynchronousIconLoadForCreatedCells:(BOOL)arg1; 182 | - (void)setReusesCells:(BOOL)arg1; 183 | - (void)setSpecifier:(id)arg1; 184 | - (void)setSpecifierID:(id)arg1; 185 | - (void)setSpecifiers:(id)arg1; 186 | - (void)setTitle:(id)arg1; 187 | - (BOOL)shouldReloadSpecifiersOnResume; 188 | - (BOOL)shouldSelectResponderOnAppearance; 189 | - (void)showConfirmationViewForSpecifier:(id)arg1 useAlert:(BOOL)arg2 swapAlertButtons:(BOOL)arg3; 190 | - (void)showConfirmationViewForSpecifier:(id)arg1; 191 | - (void)showPINSheet:(id)arg1; 192 | - (id)specifier; 193 | - (id)specifierAtIndex:(int)arg1; 194 | - (id)specifierForID:(id)arg1; 195 | - (id)specifierID; 196 | - (id)specifiers; 197 | - (id)specifiersInGroup:(int)arg1; 198 | - (id)table; 199 | - (Class)tableViewClass; 200 | - (void)updateSpecifiers:(id)arg1 withSpecifiers:(id)arg2; 201 | - (void)updateSpecifiersInRange:(NSRange)arg1 withSpecifiers:(id)arg2; 202 | - (float)verticalContentOffset; 203 | - (void)viewDidAppear:(BOOL)arg1; 204 | - (void)viewDidLayoutSubviews; 205 | - (void)viewDidLoad; 206 | - (void)viewDidUnload; 207 | - (void)viewWillAppear:(BOOL)arg1; 208 | - (void)viewWillDisappear:(BOOL)arg1; 209 | - (void)willAnimateRotationToInterfaceOrientation:(int)arg1 duration:(double)arg2; 210 | 211 | @end -------------------------------------------------------------------------------- /PrivateHeaders.h: -------------------------------------------------------------------------------- 1 | // Test notifications (see PriorityHub and TinyBar). 2 | @class CBRReadabilityManager; 3 | 4 | @interface SBLockScreenViewController : UIViewController 5 | @end 6 | 7 | @interface SBLockScreenManager : NSObject 8 | @property(readonly, assign, nonatomic) SBLockScreenViewController *lockScreenViewController; 9 | 10 | + (id)sharedInstance; 11 | - (void)lockUIFromSource:(int)arg1 withOptions:(id)arg2; 12 | @end 13 | 14 | @interface BBAction : NSObject 15 | + (id)action; 16 | + (id)actionWithLaunchURL:(id)url; 17 | @end 18 | 19 | @interface BBBulletin 20 | @property(copy, nonatomic) NSString *sectionID; 21 | @property(copy, nonatomic) NSString *title; 22 | @property(copy, nonatomic) NSString *subtitle; 23 | @property(copy, nonatomic) NSString *message; 24 | @property(copy, nonatomic) BBAction *defaultAction; 25 | @property(retain, nonatomic) NSDate *date; 26 | @property(retain, nonatomic) NSDate *publicationDate; 27 | @property(retain, nonatomic) NSDate *lastInterruptDate; 28 | @property(copy, nonatomic) NSString *bulletinID; 29 | @property(assign, nonatomic) BOOL clearable; 30 | @property(assign, nonatomic) BOOL showsMessagePreview; 31 | @end 32 | 33 | @interface BBBulletinRequest : BBBulletin 34 | @end 35 | 36 | @interface BBServer : NSObject 37 | - (id)_sectionInfoForSectionID:(NSString *)sectionID effective:(BOOL)effective; 38 | - (void)publishBulletin:(BBBulletin *)bulletin destinations:(NSUInteger)dests alwaysToLockScreen:(BOOL)lock; 39 | @end 40 | 41 | 42 | @interface SBLockScreenNotificationListController : NSObject 43 | - (void)observer:(id)arg1 addBulletin:(id)arg2 forFeed:(NSUInteger)arg3 playLightsAndSirens:(BOOL)arg4 withReply:(id)arg5; 44 | @end 45 | 46 | @interface SBBulletinBannerController : NSObject 47 | + (id)sharedInstance; 48 | - (void)observer:(id)arg1 addBulletin:(id)arg2 forFeed:(NSUInteger)arg3; 49 | - (void)observer:(id)arg1 addBulletin:(id)arg2 forFeed:(NSUInteger)arg3 playLightsAndSirens:(BOOL)arg4 withReply:(id)arg5; 50 | @end 51 | 52 | @interface SBBannerController : NSObject 53 | + (id)sharedInstance; 54 | 55 | - (id)_bannerContext; 56 | - (void)_replaceIntervalElapsed; 57 | - (void)_dismissIntervalElapsed; 58 | @end 59 | 60 | // Respringing. 61 | 62 | @interface SpringBoard : UIApplication 63 | - (void)_relaunchSpringBoardNow; 64 | @end 65 | @interface FBSystemService : NSObject 66 | + (id)sharedInstance; 67 | 68 | - (void)exitAndRelaunch:(BOOL)unknown; 69 | @end 70 | 71 | // Lockscreen Notifications. 72 | 73 | @interface SBAwayBulletinListItem : NSObject 74 | @property(retain) BBBulletin *activeBulletin; 75 | 76 | - (id)iconImage; 77 | @end 78 | 79 | @interface UITableViewCellDeleteConfirmationView : UIView 80 | @end 81 | 82 | @interface SBTableViewCellDismissActionButton : UIView 83 | @property(assign, nonatomic) BOOL drawsBottomSeparator; 84 | @property(assign, nonatomic) BOOL drawsTopSeparator; 85 | @end 86 | @interface SBTableViewCellDismissActionButton(ColorBanners) 87 | - (void)colorize:(int)color; 88 | @end 89 | 90 | @interface SBLockScreenBulletinCell : UIView 91 | @property(retain, nonatomic) UIColor *eventDateColor; 92 | @property(retain, nonatomic) UIColor *relevanceDateColor; 93 | @property(retain, nonatomic) UIColor *secondaryTextColor; 94 | @property(retain, nonatomic) UIColor *subtitleTextColor; 95 | @property(retain, nonatomic) UIColor *primaryTextColor; 96 | 97 | @property(retain, nonatomic) UILabel *eventDateLabel; 98 | @property(retain, nonatomic) UILabel *relevanceDateLabel; 99 | @property(readonly, nonatomic) UIView *realContentView; 100 | 101 | + (id)defaultColorForEventDate; 102 | + (id)defaultColorForRelevanceDate; 103 | + (id)defaultColorForSecondaryText; 104 | + (id)defaultColorForSubtitleText; 105 | + (id)defaultColorForPrimaryText; 106 | 107 | - (id)_vibrantTextColor; 108 | - (UITableViewCellDeleteConfirmationView *)_swipeToDeleteConfirmationView; 109 | @end 110 | @interface SBLockScreenBulletinCell(ColorBanners) 111 | - (void)revertIfNeeded; 112 | - (void)refreshAlphaAndVibrancy; 113 | - (void)colorize:(int)color; 114 | - (void)colorizeBackground:(int)color; 115 | - (void)colorizeText:(int)color; 116 | 117 | - (NSNumber *)cbr_color; 118 | - (void)cbr_setColor:(NSNumber *)color; 119 | @end 120 | 121 | // Banners. 122 | 123 | @interface SBBulletinBannerItem : NSObject 124 | - (id)iconImage; 125 | - (BBBulletin *)seedBulletin; 126 | @end 127 | 128 | @interface SBLockScreenNotificationBannerItem 129 | @property(readonly, assign, nonatomic) SBAwayBulletinListItem *listItem; 130 | 131 | - (id)iconImage; 132 | @end 133 | 134 | @interface SBDefaultBannerView : UIView 135 | - (void)setColor:(id)color forElement:(int)element; 136 | - (void)_setRelevanceDateColor:(id)color; 137 | @end 138 | 139 | @interface SBDefaultBannerTextView : UIView 140 | @property(readonly, assign, nonatomic) UILabel *relevanceDateLabel; 141 | @end 142 | @interface SBDefaultBannerTextView(TinyBar) 143 | - (UILabel *)tb_titleLabel; 144 | - (UILabel *)tb_secondaryLabel; 145 | @end 146 | @interface SBDefaultBannerTextView(ColorBanners) 147 | - (void)setPrimaryTextColor:(UIColor *)color; 148 | - (void)setSecondaryTextColor:(UIColor *)color; 149 | - (UIColor *)secondaryTextColor; 150 | @end 151 | 152 | @interface SBUIBannerContext : NSObject 153 | - (id)item; 154 | @end 155 | 156 | @interface SBBannerContextView : UIView 157 | @property(retain, nonatomic) UIView *pullDownView; 158 | - (void)_setGrabberColor:(id)color; 159 | @end 160 | @interface SBBannerContextView(ColorBanners) 161 | - (void)colorizeBackgroundForColor:(int)color alpha:(CGFloat)alpha preferringBlack:(BOOL)wantsBlack; 162 | - (void)colorizeTextForColor:(int)color alpha:(CGFloat)alpha preferringBlack:(BOOL)wantsBlack; 163 | - (void)colorizeGrabberForColor:(int)color alpha:(CGFloat)alpha preferringBlack:(BOOL)wantsBlack; 164 | - (void)colorizePullDown:(UIView *)v forColor:(int)color alpha:(CGFloat)alpha preferringBlack:(BOOL)wantsBlack; 165 | - (void)recolorizePullDown:(UIView *)pullDownView; 166 | - (void)colorize:(int)color withBackground:(int)bg force:(BOOL)force; 167 | - (void)colorize:(int)color; 168 | 169 | - (NSNumber *)cbr_color; 170 | - (void)cbr_setColor:(NSNumber *)color; 171 | - (NSNumber *)cbr_prefersBlack; 172 | - (void)cbr_setPrefersBlack:(NSNumber *)prefersBlack; 173 | @end 174 | 175 | #pragma mark - Banner Buttons 176 | 177 | @interface SBBannerButtonView : UIView 178 | @property(retain, nonatomic) NSArray *buttons; 179 | @end 180 | @interface SBBannerButtonView(ColorBanners) 181 | - (void)colorizeWithColor:(int)color alpha:(CGFloat)alpha preferringBlack:(BOOL)wantsBlack; 182 | @end 183 | 184 | @interface SBNotificationVibrantButton : UIView 185 | - (id)_buttonImageForColor:(id)color selected:(BOOL)selected; 186 | @end 187 | @interface SBNotificationVibrantButton(ColorBanners) 188 | - (void)colorizeWithColor:(int)color alpha:(CGFloat)alpha preferringBlack:(BOOL)wantsBlack; 189 | - (void)configureButton:(UIButton *)button 190 | withTintColor:(UIColor *)tintColor 191 | selectedTintColor:(UIColor *)selectedTintColor 192 | textColor:(UIColor *)textColor 193 | selectedTextColor:(UIColor *)selectedtextColor; 194 | @end 195 | 196 | #pragma mark - Backdrop 197 | 198 | @interface _UIBackdropViewSettings : NSObject 199 | @property double statisticsInterval; 200 | @property BOOL requiresColorStatistics; 201 | 202 | @property(retain) UIColor * colorTint; 203 | @property(retain) UIColor * combinedTintColor; 204 | 205 | + (id)settingsForStyle:(int)style; 206 | @end 207 | 208 | @interface _UIBackdropEffectView : UIView 209 | @end 210 | 211 | @interface _UIBackdropView : UIView 212 | @property(retain) id colorSaturateFilter; 213 | @property(retain) id tintFilter; 214 | - (void)_updateFilters; 215 | - (void)transitionToSettings:(id)arg1; 216 | - (void)setComputesColorSettings:(BOOL)computes; 217 | - (id)inputSettings; 218 | 219 | @property(retain) UIColor * colorMatrixColorTint; 220 | @property(retain) _UIBackdropViewSettings * outputSettings; 221 | @property(retain) _UIBackdropEffectView * backdropEffectView; 222 | @end 223 | @interface _UIBackdropView(ColorBanners) 224 | - (void)setIsForBannerContextView:(BOOL)flag; 225 | - (BOOL)isForBannerContextView; 226 | @end 227 | 228 | @interface CABackdropLayer : CALayer 229 | - (id)statisticsValues; 230 | @end 231 | 232 | // Notification Center - headers. 233 | 234 | @interface SBBulletinListSection : NSObject 235 | @property(retain, nonatomic) UIImage *iconImage; 236 | @end 237 | 238 | @interface SBNotificationCenterSectionInfo : NSObject 239 | @property(readonly, assign, nonatomic) NSString *identifier; 240 | @property(readonly, retain, nonatomic) id representedObject; 241 | @property(retain, nonatomic) UIImage *icon; 242 | // iOS 8. 243 | @property(readonly, assign, nonatomic) NSString *listSectionIdentifier; 244 | @property(readonly, assign, nonatomic) SBBulletinListSection *representedListSection; 245 | @end 246 | 247 | @interface SBNotificationCenterHeaderView : UIView 248 | @property(readonly, assign, nonatomic) UILabel *titleLabel; 249 | @property(nonatomic,retain,readonly) UIView *contentView; 250 | - (NSNumber *)cbr_color; 251 | - (void)cbr_setColor:(NSNumber *)color; 252 | - (NSNumber *)cbr_activeColor; 253 | - (void)cbr_setActiveColor:(NSNumber *)color; 254 | 255 | - (void)cbr_colorizeIfNeeded; 256 | - (void)cbr_colorize:(int)color; 257 | - (void)cbr_revert; 258 | @end 259 | 260 | // Notification center - cells. 261 | 262 | @interface SBNotificationsBulletinInfo : NSObject 263 | @property (nonatomic,retain) SBNotificationCenterSectionInfo *sectionInfo; 264 | @property (nonatomic,retain) UIImage *icon; 265 | 266 | @property (nonatomic,readonly) NSString *originalSectionIdentifier; 267 | @property (nonatomic,readonly) BBBulletin *representedBulletin; 268 | @end 269 | 270 | @interface SBNotificationsAllModeBulletinInfo : SBNotificationsBulletinInfo 271 | @end 272 | 273 | @interface SBNotificationsBulletinCell : UIView 274 | @end 275 | 276 | #pragma mark - iOS 9 Notification Center 277 | 278 | @interface SBWidgetRowInfo : NSObject 279 | - (id)icon; 280 | - (id)identifier; 281 | @end 282 | 283 | @interface SBWidgetSectionInfo : NSObject 284 | @property(copy, nonatomic) NSString *identifier; 285 | @property(retain, nonatomic) SBWidgetRowInfo *widgetRowInfo; 286 | @end 287 | 288 | #pragma mark - QuickReply 289 | 290 | @interface _UITextFieldRoundedRectBackgroundViewNeue : UIImageView 291 | @property(nonatomic, retain) UIColor * strokeColor; 292 | @property(nonatomic, retain) UIColor * fillColor; 293 | - (void)updateView; 294 | @end 295 | 296 | @interface CKInlineAudioReplyButtonController : NSObject 297 | @property (nonatomic, retain) UIButton *startButton; 298 | @property (nonatomic, retain) UIButton *stopButton; 299 | @end 300 | 301 | @interface CKMessageEntryRichTextView : UITextView 302 | @property(nonatomic, retain) UILabel *placeholderLabel; 303 | @end 304 | 305 | @interface CKMessageEntryContentView : UIView 306 | @property (nonatomic, retain) CKMessageEntryRichTextView *textView; 307 | @end 308 | 309 | @interface CKMessageEntryView : UIView 310 | @property(nonatomic, retain) UIView *dividerLine; 311 | @property(nonatomic, retain) UIButton *audioButton; 312 | @property(nonatomic, retain) CKMessageEntryContentView *contentView; 313 | @property(nonatomic, retain) UIButton *sendButton; 314 | @property(nonatomic, retain) CKInlineAudioReplyButtonController *audioReplyButton; 315 | @property(nonatomic, retain) UIButton *deleteAudioRecordingButton; 316 | 317 | // Added by ColorBanners. 318 | - (void)cbr_setModal:(BOOL)modal; 319 | - (BOOL)cbr_isModal; 320 | @end 321 | 322 | @interface CKInlineReplyViewController : UIViewController 323 | @property(nonatomic, getter=isModal) BOOL modal; 324 | @property(nonatomic, retain) CKMessageEntryView * entryView; 325 | 326 | // Added by ColorBanners. 327 | - (void)cbr_updateReadability:(BOOL)useDarkText; 328 | - (void)managersReadabilityStateDidChange:(CBRReadabilityManager *)manager; 329 | @end 330 | 331 | #pragma mark - iOS 9 QuickReply 332 | 333 | @interface NCNotificationActionTextInputViewController : UIViewController 334 | @property (nonatomic, retain) _UITextFieldRoundedRectBackgroundViewNeue *coverView; 335 | @property (nonatomic, retain) UIButton *sendButton; 336 | @property (nonatomic, retain) UITextView *textEntryView; 337 | @property (getter=isModal, nonatomic) BOOL modal; 338 | - (void)cbr_colorize:(int)color alpha:(CGFloat)alpha preferringBlack:(BOOL)wantsBlack; 339 | @end 340 | 341 | #pragma mark - Private 342 | 343 | @interface UIView(UIViewController_Internals) 344 | - (id)_viewDelegate; 345 | @end 346 | 347 | #pragma mark - Auki 2 support 348 | @interface KJUARRTextViewScrollContainerView : NSObject 349 | - (void)setRelevanceDateColor:(UIColor *)color; 350 | - (void)setRelevanceDateLabelLayerCompositingFilter:(NSString *)compositingFilter; 351 | @end 352 | -------------------------------------------------------------------------------- /colorbannersprefs/ColorBannersPrefs.mm: -------------------------------------------------------------------------------- 1 | #import "ColorBannersPrefs.h" 2 | 3 | #import "../NSDistributedNotificationCenter.h" 4 | 5 | 6 | #define PREFS_NAME "com.golddavid.colorbanners" 7 | 8 | #define INTERNAL_NOTIFICATION_NAME @"CBRReloadPreferences" 9 | #define TEST_LS "com.golddavid.colorbanners/test-ls-notification" 10 | #define TEST_BANNER "com.golddavid.colorbanners/test-banner" 11 | #define RESPRING "com.golddavid.colorbanners/respring" 12 | 13 | 14 | #define DEEP_ANALYSIS_INFO @"Analyzes the view located below the banner when deciding the text color. Use this if you have a fairly low alpha level." 15 | #define LIVE_ANALYSIS_INFO @"Live analysis will continually check the view located below the banner for changes and update the text color as necessary." 16 | 17 | static void refreshPrefs(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { 18 | [[NSDistributedNotificationCenter defaultCenter] postNotificationName:INTERNAL_NOTIFICATION_NAME object:nil]; 19 | } 20 | 21 | static void refreshPrefsVolatile(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { 22 | PSListController *controller = (PSListController *)observer; 23 | [controller clearCache]; 24 | [controller reload]; 25 | [[NSDistributedNotificationCenter defaultCenter] postNotificationName:INTERNAL_NOTIFICATION_NAME object:nil]; 26 | } 27 | 28 | @implementation ColorBannersPrefsListController 29 | 30 | - (instancetype)init { 31 | self = [super init]; 32 | if (self) { 33 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), 34 | self, 35 | &refreshPrefs, 36 | CFSTR("com.golddavid.colorbanners/reloadprefs"), 37 | NULL, 38 | 0); 39 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), 40 | self, 41 | &refreshPrefsVolatile, 42 | CFSTR("com.golddavid.colorbanners/reloadprefs-main"), 43 | NULL, 44 | 0); 45 | } 46 | return self; 47 | } 48 | 49 | - (void)dealloc { 50 | CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), 51 | self, 52 | CFSTR("com.golddavid.colorbanners/reloadprefs"), 53 | NULL); 54 | CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), 55 | self, 56 | CFSTR("com.golddavid.colorbanners/reloadprefs-main"), 57 | NULL); 58 | [super dealloc]; 59 | } 60 | 61 | - (id)specifiers { 62 | if(_specifiers == nil) { 63 | _specifiers = [[self loadSpecifiersFromPlistName:@"ColorBannersPrefs" target:self] retain]; 64 | } 65 | return _specifiers; 66 | } 67 | 68 | - (id)getLabelForSpecifier:(PSSpecifier *)specifier { 69 | NSNumber *value = [self readPreferenceValue:specifier]; 70 | if (value) { 71 | return ([value boolValue]) ? @"On" : @"Off"; 72 | } 73 | 74 | NSNumber *defaultValue = [specifier propertyForKey:@"default"]; 75 | return ([defaultValue boolValue]) ? @"On" : @"Off"; 76 | } 77 | 78 | - (void)testLockScreenNotification { 79 | CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), 80 | CFSTR(TEST_LS), 81 | nil, 82 | nil, 83 | true); 84 | } 85 | 86 | - (void)testBanner { 87 | CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), 88 | CFSTR(TEST_BANNER), 89 | nil, 90 | nil, 91 | true); 92 | } 93 | 94 | @end 95 | 96 | @implementation ColorBannersBannerPrefsController 97 | 98 | - (instancetype)init { 99 | self = [super init]; 100 | if (self) { 101 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), 102 | self, 103 | &refreshPrefsVolatile, 104 | CFSTR("com.golddavid.colorbanners/reloadprefs-banners"), 105 | NULL, 106 | 0); 107 | } 108 | return self; 109 | } 110 | 111 | - (void)dealloc { 112 | CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), 113 | self, 114 | CFSTR("com.golddavid.colorbanners/reloadprefs-banners"), 115 | NULL); 116 | [_constantColorSpecifiers release]; 117 | [_liveAnalysisSpecifiers release]; 118 | [super dealloc]; 119 | } 120 | 121 | // Thanks to MultitaskingGestures (https://github.com/hamzasood/MultitaskingGestures). 122 | - (void)setBannerConstantColorsEnabled:(NSNumber *)value forSpecifier:(PSSpecifier *)specifier { 123 | [self setPreferenceValue:value specifier:specifier]; 124 | if ([value boolValue]) { 125 | int index = [_specifiers indexOfObject:[_specifiers specifierForID:@"CUSTOM_COLOR_MINUS_ONE"]] + 1; 126 | [self insertContiguousSpecifiers:_constantColorSpecifiers 127 | atIndex:index 128 | animated:YES]; 129 | } else { 130 | [self removeContiguousSpecifiers:_constantColorSpecifiers animated:YES]; 131 | } 132 | } 133 | 134 | // Thanks to MultitaskingGestures (https://github.com/hamzasood/MultitaskingGestures). 135 | - (void)setDeepBannerAnalysisEnabled:(NSNumber *)value forSpecifier:(PSSpecifier *)specifier { 136 | PSSpecifier *groupSpecifier = [_specifiers specifierForID:@"AL GORE"]; 137 | [self setPreferenceValue:value specifier:specifier]; 138 | 139 | if ([value boolValue]) { 140 | [groupSpecifier setProperty:LIVE_ANALYSIS_INFO forKey:@"footerText"]; 141 | [self reloadSpecifier:groupSpecifier animated:NO]; 142 | 143 | int index = [_specifiers indexOfObject:[_specifiers specifierForID:@"LIVE_ANALYSIS_MINUS_ONE"]] + 1; 144 | [self insertContiguousSpecifiers:_liveAnalysisSpecifiers 145 | atIndex:index 146 | animated:YES]; 147 | } else { 148 | [groupSpecifier setProperty:DEEP_ANALYSIS_INFO forKey:@"footerText"]; 149 | [self reloadSpecifier:groupSpecifier animated:NO]; 150 | 151 | [self removeContiguousSpecifiers:_liveAnalysisSpecifiers animated:YES]; 152 | } 153 | } 154 | 155 | // Thanks to MultitaskingGestures (https://github.com/hamzasood/MultitaskingGestures). 156 | - (id)specifiers { 157 | if(_specifiers == nil) { 158 | NSMutableArray *specifiers = [[self loadSpecifiersFromPlistName:@"Banners" target:self] mutableCopy]; 159 | 160 | // Handle constant color settings. 161 | [_constantColorSpecifiers release]; 162 | _constantColorSpecifiers = [[NSMutableArray alloc] init]; 163 | // Populate the _constantColorSpecifiers array. 164 | int index = [specifiers indexOfObject:[specifiers specifierForID:@"CUSTOM_COLOR_MINUS_ONE"]] + 1; 165 | for (int i = index; i < specifiers.count; ++i) { 166 | PSSpecifier *currentSpec = specifiers[i]; 167 | if (![currentSpec.identifier isEqualToString:@"CUSTOM_COLOR_GROUP"] && 168 | [[PSTableCell stringFromCellType:currentSpec.cellType] isEqualToString:@"PSGroupCell"]) { 169 | break; 170 | } 171 | [_constantColorSpecifiers addObject:currentSpec]; 172 | } 173 | 174 | Boolean keyExists = false; 175 | if (!CFPreferencesGetAppBooleanValue(CFSTR("BannerUseConstant"), 176 | CFSTR(PREFS_NAME), 177 | &keyExists) || !keyExists) { 178 | [specifiers removeObjectsInArray:_constantColorSpecifiers]; 179 | } 180 | 181 | // Handle analysis settings. 182 | [_liveAnalysisSpecifiers release]; 183 | _liveAnalysisSpecifiers = [NSArray arrayWithObject:[specifiers specifierForID:@"LIVE_ANALYSIS_CELL"]]; 184 | [_liveAnalysisSpecifiers retain]; 185 | 186 | // Find group specifier (to update footerText). 187 | PSSpecifier *groupSpecifier = [specifiers specifierForID:@"AL GORE"]; 188 | 189 | keyExists = false; 190 | if (!CFPreferencesGetAppBooleanValue(CFSTR("WantsDeepBannerAnalyzing"), 191 | CFSTR(PREFS_NAME), 192 | &keyExists) && keyExists) { 193 | [specifiers removeObjectsInArray:_liveAnalysisSpecifiers]; 194 | [groupSpecifier setProperty:DEEP_ANALYSIS_INFO forKey:@"footerText"]; 195 | } else { 196 | [groupSpecifier setProperty:LIVE_ANALYSIS_INFO forKey:@"footerText"]; 197 | } 198 | 199 | _specifiers = [specifiers copy]; 200 | [specifiers release]; 201 | } 202 | return _specifiers; 203 | } 204 | 205 | - (void)testBanner:(id)sender { 206 | CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), 207 | CFSTR(TEST_BANNER), 208 | nil, 209 | nil, 210 | true); 211 | } 212 | 213 | - (void)viewDidLoad { 214 | [super viewDidLoad]; 215 | 216 | UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:@"Test" 217 | style:UIBarButtonItemStylePlain 218 | target:self 219 | action:@selector(testBanner:)]; 220 | self.navigationItem.rightBarButtonItem = [button autorelease]; 221 | } 222 | 223 | @end 224 | 225 | @implementation ColorBannersLSPrefsController 226 | 227 | - (instancetype)init { 228 | self = [super init]; 229 | if (self) { 230 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), 231 | self, 232 | &refreshPrefsVolatile, 233 | CFSTR("com.golddavid.colorbanners/reloadprefs-ls"), 234 | NULL, 235 | 0); 236 | } 237 | return self; 238 | } 239 | 240 | - (void)dealloc { 241 | CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), 242 | self, 243 | CFSTR("com.golddavid.colorbanners/reloadprefs-ls"), 244 | NULL); 245 | [_constantColorSpecifiers release]; 246 | [super dealloc]; 247 | } 248 | 249 | // Thanks to MultitaskingGestures (https://github.com/hamzasood/MultitaskingGestures). 250 | - (void)setLSConstantColorsEnabled:(NSNumber *)value forSpecifier:(PSSpecifier *)specifier { 251 | [self setPreferenceValue:value specifier:specifier]; 252 | if ([value boolValue]) { 253 | int index = [_specifiers indexOfObject:[_specifiers specifierForID:@"CUSTOM_COLOR_MINUS_ONE"]] + 1; 254 | [self insertContiguousSpecifiers:_constantColorSpecifiers 255 | atIndex:index 256 | animated:YES]; 257 | } else { 258 | [self removeContiguousSpecifiers:_constantColorSpecifiers animated:YES]; 259 | } 260 | } 261 | 262 | // Thanks to MultitaskingGestures (https://github.com/hamzasood/MultitaskingGestures). 263 | - (id)specifiers { 264 | if(_specifiers == nil) { 265 | NSMutableArray *specifiers = [[self loadSpecifiersFromPlistName:@"LockScreen" target:self] mutableCopy]; 266 | 267 | [_constantColorSpecifiers release]; 268 | _constantColorSpecifiers = [[NSMutableArray alloc] init]; 269 | // Populate the _constantColorSpecifiers array. 270 | int index = [specifiers indexOfObject:[specifiers specifierForID:@"CUSTOM_COLOR_MINUS_ONE"]] + 1; 271 | for (int i = index; i < specifiers.count; ++i) { 272 | PSSpecifier *currentSpec = specifiers[i]; 273 | if (![currentSpec.identifier isEqualToString:@"CUSTOM_COLOR_GROUP"] && 274 | [[PSTableCell stringFromCellType:currentSpec.cellType] isEqualToString:@"PSGroupCell"]) { 275 | break; 276 | } 277 | [_constantColorSpecifiers addObject:currentSpec]; 278 | } 279 | 280 | Boolean keyExists = false; 281 | if (!CFPreferencesGetAppBooleanValue(CFSTR("LSUseConstant"), 282 | CFSTR(PREFS_NAME), 283 | &keyExists) || !keyExists) { 284 | [specifiers removeObjectsInArray:_constantColorSpecifiers]; 285 | } 286 | 287 | _specifiers = [specifiers copy]; 288 | [specifiers release]; 289 | } 290 | return _specifiers; 291 | } 292 | 293 | - (void)testNotification:(id)sender { 294 | CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), 295 | CFSTR(TEST_LS), 296 | nil, 297 | nil, 298 | true); 299 | } 300 | 301 | - (void)viewDidLoad { 302 | [super viewDidLoad]; 303 | 304 | UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:@"Test" 305 | style:UIBarButtonItemStylePlain 306 | target:self 307 | action:@selector(testNotification:)]; 308 | self.navigationItem.rightBarButtonItem = [button autorelease]; 309 | } 310 | 311 | @end 312 | 313 | @implementation ColorBannersNCPrefsController 314 | 315 | - (instancetype)init { 316 | self = [super init]; 317 | if (self) { 318 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), 319 | self, 320 | &refreshPrefsVolatile, 321 | CFSTR("com.golddavid.colorbanners/reloadprefs-nc"), 322 | NULL, 323 | 0); 324 | } 325 | return self; 326 | } 327 | 328 | - (void)dealloc { 329 | CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), 330 | self, 331 | CFSTR("com.golddavid.colorbanners/reloadprefs-nc"), 332 | NULL); 333 | [_constantColorSpecifiers release]; 334 | [super dealloc]; 335 | } 336 | 337 | // Thanks to MultitaskingGestures (https://github.com/hamzasood/MultitaskingGestures). 338 | - (void)setNCConstantColorsEnabled:(NSNumber *)value forSpecifier:(PSSpecifier *)specifier { 339 | [self setPreferenceValue:value specifier:specifier]; 340 | if ([value boolValue]) { 341 | int index = [_specifiers indexOfObject:[_specifiers specifierForID:@"CUSTOM_COLOR_MINUS_ONE"]] + 1; 342 | [self insertContiguousSpecifiers:_constantColorSpecifiers 343 | atIndex:index 344 | animated:YES]; 345 | } else { 346 | [self removeContiguousSpecifiers:_constantColorSpecifiers animated:YES]; 347 | } 348 | } 349 | 350 | // Thanks to MultitaskingGestures (https://github.com/hamzasood/MultitaskingGestures). 351 | - (id)specifiers { 352 | if(_specifiers == nil) { 353 | NSMutableArray *specifiers = [[self loadSpecifiersFromPlistName:@"NotificationCenter" target:self] mutableCopy]; 354 | 355 | [_constantColorSpecifiers release]; 356 | _constantColorSpecifiers = [[NSMutableArray alloc] init]; 357 | // Populate the _constantColorSpecifiers array. 358 | int index = [specifiers indexOfObject:[specifiers specifierForID:@"CUSTOM_COLOR_MINUS_ONE"]] + 1; 359 | for (int i = index; i < specifiers.count; ++i) { 360 | PSSpecifier *currentSpec = specifiers[i]; 361 | if (![currentSpec.identifier isEqualToString:@"CUSTOM_COLOR_GROUP"] && 362 | [[PSTableCell stringFromCellType:currentSpec.cellType] isEqualToString:@"PSGroupCell"]) { 363 | break; 364 | } 365 | [_constantColorSpecifiers addObject:currentSpec]; 366 | } 367 | 368 | Boolean keyExists = false; 369 | if (!CFPreferencesGetAppBooleanValue(CFSTR("NCUseConstant"), 370 | CFSTR(PREFS_NAME), 371 | &keyExists) || !keyExists) { 372 | [specifiers removeObjectsInArray:_constantColorSpecifiers]; 373 | } 374 | 375 | _specifiers = [specifiers copy]; 376 | [specifiers release]; 377 | } 378 | return _specifiers; 379 | } 380 | 381 | - (void)respring:(id)sender { 382 | CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), 383 | CFSTR(RESPRING), 384 | nil, 385 | nil, 386 | true); 387 | } 388 | 389 | - (void)viewDidLoad { 390 | [super viewDidLoad]; 391 | 392 | UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:@"Respring" 393 | style:UIBarButtonItemStylePlain 394 | target:self 395 | action:@selector(respring:)]; 396 | self.navigationItem.rightBarButtonItem = [button autorelease]; 397 | } 398 | 399 | @end 400 | -------------------------------------------------------------------------------- /Tweak.xm: -------------------------------------------------------------------------------- 1 | #import "ColorBadges.h" 2 | 3 | #import 4 | 5 | #import "Defines.h" 6 | #import "PrivateHeaders.h" 7 | #import "CBRAppList.h" 8 | #import "CBRColorCache.h" 9 | #import "CBRGradientView.h" 10 | #import "CBRPrefsManager.h" 11 | #import "CBRReadabilityManager.h" 12 | #import "UIColor+ColorBanners.h" 13 | 14 | #define UIColorFromRGBWithAlpha(rgb, a) [UIColor colorWithRed:GETRED(rgb)/255.0 green:GETGREEN(rgb)/255.0 blue:GETBLUE(rgb)/255.0 alpha:a] 15 | #define VIEW_TAG 0xDAE1DEE 16 | #define DARK_GRAY 0x555555 17 | #define MAX_RETRIES 15 18 | 19 | static BOOL isWhitish(int rgb) { 20 | return ![CBRColorCache isDarkColor:rgb]; 21 | } 22 | 23 | static int colorToRGBInt(int r, int g, int b) { 24 | return ((r << 16) | 25 | (g << 8) | 26 | (b)); 27 | } 28 | 29 | static BOOL compositeIsWhitish(int rgb, int bg, CGFloat fgAlpha) { 30 | int r = GETRED(rgb); 31 | int g = GETGREEN(rgb); 32 | int b = GETBLUE(rgb); 33 | 34 | int x = GETRED(bg); 35 | int y = GETGREEN(bg); 36 | int z = GETBLUE(bg); 37 | 38 | CGFloat bgAlpha = 1 - fgAlpha; 39 | int outRed = (int)(fgAlpha * r) + (int)(bgAlpha * x); 40 | int outGreen = (int)(fgAlpha * g) + (int)(bgAlpha * y); 41 | int outBlue = (int)(fgAlpha * b) + (int)(bgAlpha * z); 42 | return isWhitish(colorToRGBInt(outRed, outGreen, outBlue)); 43 | } 44 | 45 | // Hack to improve the LS text coloring when the "prefersWhiteText" option is enabled. 46 | static BOOL ls_isWhitish(int rgb) { 47 | if ([CBRPrefsManager sharedInstance].prefersWhiteText) { 48 | return compositeIsWhitish(rgb, DARK_GRAY, [CBRPrefsManager sharedInstance].lsAlpha); 49 | } 50 | return isWhitish(rgb); 51 | } 52 | 53 | static NSAttributedString * copyAttributedStringWithColor(NSAttributedString *str, UIColor *color) { 54 | NSMutableAttributedString *copy = [str mutableCopy]; 55 | [copy addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange(0, [copy length])]; 56 | return copy; 57 | } 58 | 59 | // Used for lockscreen notifications. 60 | static id bbServer = nil; 61 | 62 | // TODO(DavidGoldman): Figure out how to use BBAction so that it will be dismissed properly. 63 | // Thanks to PriorityHub. 64 | static void showTestLockScreenNotification(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { 65 | [[%c(SBLockScreenManager) sharedInstance] lockUIFromSource:1 withOptions:nil]; 66 | 67 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.7 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 68 | NSString *sectionID = [CBRAppList randomAppIdentifier]; 69 | NSUInteger count = 0; 70 | if ([bbServer respondsToSelector:@selector(_sectionInfoForSectionID:effective:)]) { 71 | while (![bbServer _sectionInfoForSectionID:sectionID effective:YES] && count < MAX_RETRIES) { 72 | sectionID = [CBRAppList randomAppIdentifier]; 73 | } 74 | } 75 | 76 | BBBulletin *bulletin = [[[%c(BBBulletinRequest) alloc] init] autorelease]; 77 | bulletin.title = @"ColorBanners"; 78 | bulletin.subtitle = @"This is a test notification!"; 79 | bulletin.sectionID = sectionID; 80 | bulletin.bulletinID = @"com.golddavid.colorbanners"; 81 | bulletin.clearable = YES; 82 | bulletin.showsMessagePreview = YES; 83 | NSDate *date = [NSDate date]; 84 | bulletin.date = date; 85 | bulletin.publicationDate = date; 86 | bulletin.lastInterruptDate = date; 87 | 88 | NSURL *url= [NSURL URLWithString:@"prefs:root=ColorBanners"]; 89 | bulletin.defaultAction = [%c(BBAction) actionWithLaunchURL:url]; 90 | 91 | if ([bbServer respondsToSelector:@selector(publishBulletin:destinations:alwaysToLockScreen:)]) { 92 | [bbServer publishBulletin:bulletin destinations:4 alwaysToLockScreen:YES]; 93 | } 94 | }); 95 | } 96 | 97 | // Thanks for TinyBar (https://github.com/alexzielenski/TinyBar). 98 | static void showTestBanner(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { 99 | SBBannerController *controller = [%c(SBBannerController) sharedInstance]; 100 | if ([controller _bannerContext]) { // Don't do anything if there is already a banner showing. 101 | return; 102 | } 103 | // Not sure if these are needed - see TinyBar. 104 | [NSObject cancelPreviousPerformRequestsWithTarget:controller 105 | selector:@selector(_replaceIntervalElapsed) 106 | object:nil]; 107 | [NSObject cancelPreviousPerformRequestsWithTarget:controller 108 | selector:@selector(_dismissIntervalElapsed) 109 | object:nil]; 110 | [controller _replaceIntervalElapsed]; 111 | [controller _dismissIntervalElapsed]; 112 | 113 | BBBulletin *bulletin = [[[%c(BBBulletinRequest) alloc] init] autorelease]; 114 | bulletin.title = @"ColorBanners"; 115 | bulletin.message = @"This is a test banner!"; 116 | bulletin.bulletinID = @"com.golddavid.colorbanners"; 117 | bulletin.sectionID = [CBRAppList randomAppIdentifier]; 118 | bulletin.defaultAction = [%c(BBAction) action]; 119 | 120 | SBBulletinBannerController *bc = [%c(SBBulletinBannerController) sharedInstance]; 121 | if ([bc respondsToSelector:@selector(observer:addBulletin:forFeed:)]) { 122 | [bc observer:nil addBulletin:bulletin forFeed:2]; 123 | } else if ([bc respondsToSelector:@selector(observer:addBulletin:forFeed:playLightsAndSirens:withReply:)]) { 124 | [bc observer:nil addBulletin:bulletin forFeed:2 playLightsAndSirens:YES withReply:nil]; 125 | } 126 | } 127 | 128 | static void respring(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { 129 | SpringBoard *sb = (SpringBoard *)[UIApplication sharedApplication]; 130 | if ([sb respondsToSelector:@selector(_relaunchSpringBoardNow)]) { 131 | [sb _relaunchSpringBoardNow]; 132 | } else if (%c(FBSystemService)) { 133 | [[%c(FBSystemService) sharedInstance] exitAndRelaunch:YES]; 134 | } 135 | } 136 | 137 | %group TestNotifications 138 | %hook BBServer 139 | - (id)init { 140 | id me = %orig; 141 | bbServer = me; 142 | return me; 143 | } 144 | - (void)dealloc { 145 | if (bbServer == self) { 146 | bbServer = nil; 147 | } 148 | %orig; 149 | } 150 | %end 151 | %end 152 | 153 | %group LockScreen 154 | %hook SBLockScreenNotificationListView 155 | 156 | // TODO(DavidGoldman): Try to improve this somehow. Not exactly sure which coloring part causes 157 | // slowdowns (probably the gradient though). 158 | // 159 | // Move this into -|tableView:cellForRowAtIndexPath:| to provide proper PrettierBanners support. 160 | - (void)_setContentForTableCell:(SBLockScreenBulletinCell *)cell 161 | withItem:(SBAwayBulletinListItem *)item 162 | atIndexPath:(id)path { 163 | %orig; 164 | 165 | Class sbbc = %c(SBLockScreenBulletinCell); 166 | CBRPrefsManager *prefsManager = [CBRPrefsManager sharedInstance]; 167 | if (prefsManager.lsEnabled && [cell isMemberOfClass:sbbc]) { 168 | int color; 169 | 170 | if (prefsManager.lsUseConstantColor) { 171 | color = prefsManager.lsBackgroundColor; 172 | } else { 173 | UIImage *image = [item iconImage]; 174 | if (!image) { 175 | [cell revertIfNeeded]; 176 | return; 177 | } 178 | 179 | // Don't cache bulletins from Calendar for Lockscreen. 180 | NSString *bulletinID = item.activeBulletin.bulletinID; 181 | if ([bulletinID hasPrefix:@"LockScreenCalendar"]) { 182 | color = [[CBRColorCache sharedInstance] colorForImage:image]; 183 | } else { 184 | color = [[CBRColorCache sharedInstance] colorForIdentifier:item.activeBulletin.sectionID 185 | image:image]; 186 | } 187 | } 188 | 189 | [cell colorize:color]; 190 | } 191 | } 192 | 193 | // Hiding separators thanks to PriorityHub. 194 | - (void)layoutSubviews { 195 | %orig; 196 | 197 | BOOL showSeparators = [CBRPrefsManager sharedInstance].showSeparators; 198 | 199 | UITableView *tableView = MSHookIvar(self, "_tableView"); 200 | UITableViewCellSeparatorStyle style = 201 | showSeparators ? UITableViewCellSeparatorStyleSingleLine : UITableViewCellSeparatorStyleNone; 202 | tableView.separatorStyle = style; 203 | 204 | UIView *topSeparator = MSHookIvar(self, "_topPocketView"); 205 | UIView *bottomSeparator = MSHookIvar(self, "_bottomPocketView"); 206 | topSeparator.hidden = !showSeparators; 207 | bottomSeparator.hidden = !showSeparators; 208 | } 209 | 210 | %end 211 | 212 | %hook SBLockScreenBulletinCell 213 | 214 | - (void)prepareForReuse { 215 | %orig; 216 | 217 | if (![CBRPrefsManager sharedInstance].lsEnabled) { 218 | [self revertIfNeeded]; 219 | } 220 | } 221 | 222 | - (UIColor *)_vibrantTextColor { 223 | NSNumber *colorObj = [self cbr_color]; 224 | if (colorObj && ls_isWhitish([colorObj intValue])) { 225 | return [UIColor darkGrayColor]; 226 | } 227 | return %orig; 228 | } 229 | 230 | // This method adds the compositingFilter and updates the text color via _vibrantTextColor. 231 | - (void)_updateUnlockText:(NSString *)text { 232 | %orig; 233 | 234 | NSNumber *colorObj = [self cbr_color]; 235 | if (colorObj && ls_isWhitish([colorObj intValue])) { 236 | MSHookIvar(self, "_unlockTextLabel").layer.compositingFilter = nil; 237 | } 238 | } 239 | 240 | // TODO(DavidGoldman): Possibly move this hook into the superclass (SBLockScreenNotificationCell). 241 | - (void)setContentAlpha:(CGFloat)alpha { 242 | if ([CBRPrefsManager sharedInstance].disableDimming) { 243 | alpha = 1; 244 | } 245 | 246 | %orig; 247 | } 248 | 249 | %new 250 | - (void)revertIfNeeded { 251 | if (![self cbr_color]) { 252 | return; 253 | } 254 | 255 | // // Hide/revert all the things! 256 | [self cbr_setColor:nil]; 257 | 258 | // Hide gradient. 259 | CBRGradientView *gradientView = (CBRGradientView *)[self.realContentView viewWithTag:VIEW_TAG]; 260 | gradientView.hidden = YES; 261 | 262 | // Revert text colors. 263 | NSString *compositingFilter = @"colorDodgeBlendMode"; 264 | self.eventDateLabel.layer.compositingFilter = compositingFilter; 265 | self.relevanceDateLabel.layer.compositingFilter = compositingFilter; 266 | MSHookIvar(self, "_unlockTextLabel").layer.compositingFilter = compositingFilter; 267 | 268 | Class BulletinCell = %c(SBLockScreenBulletinCell); 269 | self.primaryTextColor = [BulletinCell defaultColorForPrimaryText]; 270 | self.subtitleTextColor = [BulletinCell defaultColorForSubtitleText]; 271 | self.secondaryTextColor = [BulletinCell defaultColorForSecondaryText]; 272 | 273 | UIColor *vibrantColor = [self _vibrantTextColor]; 274 | self.relevanceDateColor = vibrantColor; 275 | self.eventDateColor = vibrantColor; 276 | } 277 | 278 | %new 279 | - (void)refreshAlphaAndVibrancy { 280 | int color = [[self cbr_color] intValue]; 281 | 282 | CBRGradientView *gradientView = (CBRGradientView *)[self.realContentView viewWithTag:VIEW_TAG]; 283 | gradientView.alpha = [CBRPrefsManager sharedInstance].lsAlpha; 284 | 285 | BOOL wantsBlack = ls_isWhitish(color); 286 | NSString *compositingFilter = (wantsBlack) ? nil : @"colorDodgeBlendMode"; 287 | 288 | self.eventDateLabel.layer.compositingFilter = compositingFilter; 289 | self.relevanceDateLabel.layer.compositingFilter = compositingFilter; 290 | MSHookIvar(self, "_unlockTextLabel").layer.compositingFilter = compositingFilter; 291 | 292 | // TODO(DavidGoldman): See if this "smart" refresh/reversion is worth it. I highly doubt it. 293 | [self colorizeText:color]; 294 | } 295 | 296 | %new 297 | - (void)colorizeBackground:(int)color { 298 | CBRGradientView *gradientView = (CBRGradientView *)[self.realContentView viewWithTag:VIEW_TAG]; 299 | UIColor *color1 = UIColorFromRGB(color); 300 | 301 | if (!gradientView) { 302 | gradientView = [[CBRGradientView alloc] initWithFrame:self.frame]; 303 | gradientView.tag = VIEW_TAG; 304 | [self.realContentView insertSubview:gradientView atIndex:0]; 305 | [gradientView release]; 306 | } 307 | gradientView.hidden = NO; 308 | gradientView.alpha = [CBRPrefsManager sharedInstance].lsAlpha; 309 | 310 | if ([CBRPrefsManager sharedInstance].useLSGradient) { 311 | UIColor *color2 = (ls_isWhitish(color)) ? [color1 cbr_darken:0.2] : [color1 cbr_lighten:0.2]; 312 | NSArray *colors = @[ (id)color1.CGColor, (id)color2.CGColor ]; 313 | [gradientView setColors:colors]; 314 | } else { 315 | [gradientView setSolidColor:color1]; 316 | } 317 | } 318 | 319 | %new 320 | - (void)colorizeText:(int)color { 321 | BOOL wantsBlack = ls_isWhitish(color); 322 | NSString *compositingFilter = (wantsBlack) ? nil : @"colorDodgeBlendMode"; 323 | 324 | self.eventDateLabel.layer.compositingFilter = compositingFilter; 325 | self.relevanceDateLabel.layer.compositingFilter = compositingFilter; 326 | UILabel *unlockTextLabel = MSHookIvar(self, "_unlockTextLabel"); 327 | unlockTextLabel.layer.compositingFilter = compositingFilter; 328 | 329 | if (wantsBlack) { 330 | UIColor *textColor = [UIColor darkGrayColor]; 331 | self.primaryTextColor = textColor; 332 | self.subtitleTextColor = textColor; 333 | self.secondaryTextColor = textColor; 334 | self.relevanceDateColor = textColor; 335 | self.eventDateColor = textColor; 336 | unlockTextLabel.textColor = textColor; 337 | } else { 338 | Class BulletinCell = %c(SBLockScreenBulletinCell); 339 | self.primaryTextColor = [BulletinCell defaultColorForPrimaryText]; 340 | self.subtitleTextColor = [BulletinCell defaultColorForSubtitleText]; 341 | self.secondaryTextColor = [BulletinCell defaultColorForSecondaryText]; 342 | 343 | UIColor *vibrantColor = [self _vibrantTextColor]; 344 | self.relevanceDateColor = vibrantColor; 345 | self.eventDateColor = vibrantColor; 346 | unlockTextLabel.textColor = vibrantColor; 347 | } 348 | } 349 | 350 | - (void)layoutSubviews { 351 | %orig; 352 | 353 | CBRGradientView *gradientView = (CBRGradientView *)[self.realContentView viewWithTag:VIEW_TAG]; 354 | gradientView.frame = self.realContentView.bounds; 355 | } 356 | 357 | %new 358 | - (void)colorize:(int)color { 359 | NSNumber *colorObj = @(color); 360 | if ([colorObj isEqual:[self cbr_color]]) { 361 | CBRLOG(@"%@: Ignoring repeated colorize %d", self, color); 362 | [self refreshAlphaAndVibrancy]; 363 | return; 364 | } else { 365 | CBRLOG(@"%@: Colorize to %d from %@", self, color, [self cbr_color]); 366 | } 367 | 368 | [self cbr_setColor:colorObj]; 369 | [self colorizeBackground:color]; 370 | [self colorizeText:color]; 371 | } 372 | 373 | %new 374 | - (NSNumber *)cbr_color { 375 | return objc_getAssociatedObject(self, @selector(cbr_color)); 376 | } 377 | 378 | %new 379 | - (void)cbr_setColor:(NSNumber *)color { 380 | objc_setAssociatedObject(self, @selector(cbr_color), color, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 381 | } 382 | 383 | - (void)_beginSwiping { 384 | %orig; 385 | 386 | NSNumber *colorObj = [self cbr_color]; 387 | if (colorObj) { 388 | int color = [colorObj intValue]; 389 | 390 | UITableViewCellDeleteConfirmationView *view = [self _swipeToDeleteConfirmationView]; 391 | NSArray *buttons = MSHookIvar(view, "_actionButtons"); 392 | for (id button in buttons) { 393 | if ([button isMemberOfClass:%c(SBTableViewCellDismissActionButton)]) { 394 | SBTableViewCellDismissActionButton *actionButton = button; 395 | [actionButton colorize:color]; 396 | } 397 | } 398 | } 399 | } 400 | 401 | %end 402 | 403 | %hook SBTableViewCellDismissActionButton 404 | 405 | %new 406 | - (void)colorize:(int)color { 407 | if ([CBRPrefsManager sharedInstance].colorDismissButton) { 408 | CGFloat alpha = [CBRPrefsManager sharedInstance].lsAlpha * 3 / 4; 409 | self.backgroundColor = UIColorFromRGBWithAlpha(color, alpha); 410 | } 411 | 412 | if (![CBRPrefsManager sharedInstance].showSeparators) { 413 | self.drawsBottomSeparator = NO; 414 | self.drawsTopSeparator = NO; 415 | } 416 | } 417 | 418 | %end 419 | 420 | %end 421 | 422 | %group Banners 423 | %hook SBBannerContextView 424 | 425 | %new 426 | - (void)colorize:(int)color { 427 | [self cbr_setColor:@(color)]; 428 | [self colorize:color withBackground:-1 force:YES]; 429 | 430 | CBRPrefsManager *manager = [CBRPrefsManager sharedInstance]; 431 | if (manager.bannerAlpha == 1 || !manager.wantsDeepBannerAnalyzing) { 432 | return; 433 | } 434 | 435 | // Modify the settings to use color statistics/computing color. 436 | _UIBackdropView *backdropView = MSHookIvar<_UIBackdropView *>(self, "_backdropView"); 437 | _UIBackdropViewSettings *s = [backdropView inputSettings]; 438 | s.statisticsInterval = 0.25; 439 | s.requiresColorStatistics = YES; 440 | 441 | [backdropView setIsForBannerContextView:YES]; 442 | [backdropView setComputesColorSettings:YES]; 443 | } 444 | 445 | %new 446 | - (void)colorizeBackgroundForColor:(int)color alpha:(CGFloat)alpha preferringBlack:(BOOL)wantsBlack { 447 | // Remove background tint. 448 | _UIBackdropView *backdropView = MSHookIvar<_UIBackdropView *>(self, "_backdropView"); 449 | [backdropView setIsForBannerContextView:YES]; 450 | backdropView.colorSaturateFilter = nil; 451 | backdropView.tintFilter = nil; 452 | [backdropView _updateFilters]; 453 | 454 | // Hide background blur if needed. 455 | if ([CBRPrefsManager sharedInstance].removeBannersBlur) { 456 | backdropView.hidden = YES; 457 | } 458 | 459 | // Create/update gradient. 460 | CBRGradientView *gradientView = (CBRGradientView *)[self viewWithTag:VIEW_TAG]; 461 | UIColor *color1 = UIColorFromRGB(color); 462 | 463 | if (!gradientView) { 464 | gradientView = [[CBRGradientView alloc] initWithFrame:self.bounds]; 465 | gradientView.tag = VIEW_TAG; 466 | [self insertSubview:gradientView atIndex:1]; 467 | [gradientView release]; 468 | } 469 | gradientView.hidden = NO; 470 | gradientView.alpha = alpha; 471 | 472 | if ([CBRPrefsManager sharedInstance].useBannerGradient) { 473 | UIColor *color2 = (wantsBlack) ? [color1 cbr_darken:0.1] : [color1 cbr_lighten:0.1]; 474 | NSArray *colors = @[ (id)color1.CGColor, (id)color2.CGColor ]; 475 | [gradientView setColors:colors]; 476 | } else { 477 | [gradientView setSolidColor:color1]; 478 | } 479 | } 480 | 481 | %new 482 | - (void)colorizeTextForColor:(int)color alpha:(CGFloat)alpha preferringBlack:(BOOL)wantsBlack { 483 | SBDefaultBannerView *view = MSHookIvar(self, "_contentView"); 484 | SBDefaultBannerTextView *textView = MSHookIvar(view, "_textView"); 485 | 486 | UIColor *dateColor; 487 | UIColor *textColor; 488 | NSString *compositingFilter; 489 | 490 | if (wantsBlack) { 491 | dateColor = textColor = [UIColor darkGrayColor]; 492 | compositingFilter = nil; 493 | } else { 494 | dateColor = UIColorFromRGB(color); 495 | textColor = [UIColor whiteColor]; 496 | compositingFilter = @"colorDodgeBlendMode"; 497 | } 498 | 499 | // Auki 2 Support. 500 | if (textView.class == %c(KJUARRTextViewScrollContainerView)) { 501 | KJUARRTextViewScrollContainerView *aukiView = (KJUARRTextViewScrollContainerView *)textView; 502 | [aukiView setRelevanceDateLabelLayerCompositingFilter:compositingFilter]; 503 | [aukiView setRelevanceDateColor:dateColor]; 504 | } else { 505 | textView.relevanceDateLabel.layer.compositingFilter = compositingFilter; 506 | [view _setRelevanceDateColor:dateColor]; 507 | } 508 | [textView setPrimaryTextColor:textColor]; 509 | [textView setSecondaryTextColor:textColor]; 510 | 511 | [textView setNeedsDisplay]; 512 | } 513 | 514 | %new 515 | - (void)colorizeGrabberForColor:(int)color alpha:(CGFloat)alpha preferringBlack:(BOOL)wantsBlack { 516 | // Colorize/hide the grabber. 517 | UIView *grabberView = MSHookIvar(self, "_grabberView"); 518 | if ([CBRPrefsManager sharedInstance].hideGrabber) { 519 | grabberView.hidden = YES; 520 | } else { 521 | BOOL normallyWantsBlack = isWhitish(color); 522 | grabberView.layer.compositingFilter = nil; 523 | grabberView.opaque = NO; 524 | 525 | UIColor *grabberColor; 526 | if (normallyWantsBlack && !wantsBlack) { // Go with fully white because it's blurred darker. 527 | grabberColor = [UIColor whiteColor]; 528 | } else { 529 | grabberColor = (wantsBlack) ? [UIColor darkGrayColor] : [UIColorFromRGBWithAlpha(color, 0.6) cbr_darken:0.3]; 530 | } 531 | [self _setGrabberColor:grabberColor]; 532 | } 533 | } 534 | 535 | %new 536 | - (void)colorizePullDown:(UIView *)pullDownView forColor:(int)color 537 | alpha:(CGFloat)alpha preferringBlack:(BOOL)wantsBlack { 538 | // Colorize the buttons. 539 | if ([pullDownView isKindOfClass:%c(SBBannerButtonView)]) { 540 | SBBannerButtonView *buttonView = (SBBannerButtonView *)pullDownView; 541 | [buttonView colorizeWithColor:color alpha:alpha preferringBlack:wantsBlack]; 542 | } 543 | 544 | // Colorize Text View. 545 | if (IS_IOS9_OR_NEWER) { 546 | id viewController = [pullDownView _viewDelegate]; 547 | if ([viewController isKindOfClass:%c(NCNotificationActionTextInputViewController)]) { 548 | [(NCNotificationActionTextInputViewController *)viewController cbr_colorize:color 549 | alpha:alpha 550 | preferringBlack:wantsBlack]; 551 | } 552 | } 553 | } 554 | 555 | %new 556 | - (void)colorize:(int)color withBackground:(int)bg force:(BOOL)force { 557 | CGFloat alpha = [CBRPrefsManager sharedInstance].bannerAlpha; 558 | BOOL isWhite = (bg != -1) ? compositeIsWhitish(color, bg, alpha) : isWhitish(color); 559 | 560 | if (!force) { 561 | NSNumber *curColor = [self cbr_color]; 562 | NSNumber *curPrefersBlack = [self cbr_prefersBlack]; 563 | if (curColor && curPrefersBlack 564 | && [curColor intValue] == color && [curPrefersBlack boolValue] == isWhite) { 565 | return; 566 | } 567 | } 568 | [[CBRReadabilityManager sharedInstance] setShouldUseDarkTextAndSynchronize:isWhite]; 569 | 570 | [self cbr_setPrefersBlack:@(isWhite)]; 571 | 572 | [self colorizeBackgroundForColor:color alpha:alpha preferringBlack:isWhite]; 573 | [self colorizeTextForColor:color alpha:alpha preferringBlack:isWhite]; 574 | [self colorizeGrabberForColor:color alpha:alpha preferringBlack:isWhite]; 575 | [self colorizePullDown:self.pullDownView forColor:color alpha:alpha preferringBlack:isWhite]; 576 | } 577 | 578 | %new 579 | - (void)recolorizePullDown:(UIView *)pullDownView { 580 | NSNumber *curColor = [self cbr_color]; 581 | NSNumber *curPrefersBlack = [self cbr_prefersBlack]; 582 | if (curColor && curPrefersBlack) { 583 | [self colorizePullDown:pullDownView 584 | forColor:[curColor intValue] 585 | alpha:[CBRPrefsManager sharedInstance].bannerAlpha 586 | preferringBlack:[curPrefersBlack boolValue]]; 587 | } 588 | } 589 | 590 | %new 591 | - (NSNumber *)cbr_color { 592 | return objc_getAssociatedObject(self, @selector(cbr_color)); 593 | } 594 | 595 | %new 596 | - (void)cbr_setColor:(NSNumber *)color { 597 | objc_setAssociatedObject(self, @selector(cbr_color), color, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 598 | } 599 | 600 | - (void)setBannerContext:(SBUIBannerContext *)context withReplaceReason:(int)replaceReason { 601 | %orig; 602 | 603 | SBDefaultBannerView *view = MSHookIvar(self, "_contentView"); 604 | if ([view isMemberOfClass:%c(SBDefaultBannerView)]) { 605 | CBRPrefsManager *prefsManager = [CBRPrefsManager sharedInstance]; 606 | 607 | if (!prefsManager.bannersEnabled) { 608 | CBRGradientView *gradientView = (CBRGradientView *)[self viewWithTag:VIEW_TAG]; 609 | gradientView.hidden = YES; // Not sure if needed (probably isn't). 610 | } else { 611 | int color; 612 | if (prefsManager.bannersUseConstantColor) { 613 | color = prefsManager.bannerBackgroundColor; 614 | } else { 615 | id item = [context item]; 616 | NSString *identifier = nil; 617 | 618 | if ([item isKindOfClass:%c(SBBulletinBannerItem)]) { 619 | identifier = [item seedBulletin].sectionID; 620 | } else if ([item isKindOfClass:%c(SBLockScreenNotificationBannerItem)]) { 621 | SBAwayBulletinListItem *listItem = [item listItem]; 622 | identifier = listItem.activeBulletin.sectionID; 623 | } else { 624 | // Revert/don't color. 625 | CBRLOG(@"Unknown bulletin item %@", item); 626 | 627 | CBRGradientView *gradientView = (CBRGradientView *)[self viewWithTag:VIEW_TAG]; 628 | gradientView.hidden = YES; // Not sure if needed (probably isn't). 629 | return; 630 | } 631 | 632 | UIImage *image = [item iconImage]; 633 | color = [[CBRColorCache sharedInstance] colorForIdentifier:identifier image:image]; 634 | } 635 | 636 | if (prefsManager.roundCorners) { 637 | self.layer.cornerRadius = 5; 638 | self.layer.masksToBounds = YES; 639 | } 640 | 641 | [self colorize:color]; 642 | } 643 | } 644 | } 645 | 646 | %new 647 | - (NSNumber *)cbr_prefersBlack { 648 | return objc_getAssociatedObject(self, @selector(cbr_prefersBlack)); 649 | } 650 | 651 | %new 652 | - (void)cbr_setPrefersBlack:(NSNumber *)prefersBlack { 653 | objc_setAssociatedObject(self, 654 | @selector(cbr_prefersBlack), 655 | prefersBlack, 656 | OBJC_ASSOCIATION_RETAIN_NONATOMIC); 657 | } 658 | 659 | - (void)layoutSubviews { 660 | %orig; 661 | 662 | CBRGradientView *gradientView = (CBRGradientView *)[self viewWithTag:VIEW_TAG]; 663 | gradientView.frame = self.bounds; 664 | } 665 | 666 | %end 667 | 668 | %hook SBDefaultBannerTextView 669 | 670 | %new 671 | - (void)setPrimaryTextColor:(UIColor *)color { 672 | NSAttributedString *s = MSHookIvar(self, "_primaryTextAttributedString"); 673 | MSHookIvar(self, "_primaryTextAttributedString") = copyAttributedStringWithColor(s, color); 674 | [s release]; 675 | 676 | s = MSHookIvar(self, "_primaryTextAttributedStringComponent"); 677 | MSHookIvar(self, "_primaryTextAttributedStringComponent") = copyAttributedStringWithColor(s, color); 678 | [s release]; 679 | 680 | // Subtitle appears to have been added in 8.3. Still need to see where this is actually used. 681 | // It appears to be used in Group Chats, but I'm not sure. 682 | Ivar ivar = class_getInstanceVariable(object_getClass(self), "_subtitleTextAttributedString"); 683 | if (ivar) { 684 | s = MSHookIvar(self, "_subtitleTextAttributedString"); 685 | MSHookIvar(self, "_subtitleTextAttributedString") = copyAttributedStringWithColor(s, color); 686 | [s release]; 687 | } 688 | 689 | // TinyBar support (deferred colorizing). 690 | if ([self respondsToSelector:@selector(tb_titleLabel)]) { 691 | [self tb_titleLabel].textColor = color; 692 | } 693 | } 694 | 695 | %new 696 | - (void)setSecondaryTextColor:(UIColor *)color { 697 | NSAttributedString *s = MSHookIvar(self, "_secondaryTextAttributedString"); 698 | MSHookIvar(self, "_secondaryTextAttributedString") = copyAttributedStringWithColor(s, color); 699 | [s release]; 700 | 701 | s = MSHookIvar(self, "_alternateSecondaryTextAttributedString"); 702 | MSHookIvar(self, "_alternateSecondaryTextAttributedString") = copyAttributedStringWithColor(s, color); 703 | [s release]; 704 | 705 | // TinyBar support (deferred colorizing). 706 | if ([self respondsToSelector:@selector(tb_secondaryLabel)]) { 707 | [self tb_secondaryLabel].textColor = color; 708 | } 709 | 710 | // TinyBar support. 711 | objc_setAssociatedObject(self, @selector(secondaryTextColor), color, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 712 | } 713 | 714 | // TinyBar support. 715 | %new 716 | - (UIColor *)secondaryTextColor { 717 | return objc_getAssociatedObject(self, @selector(secondaryTextColor)); 718 | } 719 | 720 | // TinyBar support. 721 | - (id)_newAttributedStringForSecondaryText:(id)secondaryText italicized:(BOOL)italicized { 722 | NSAttributedString *str = %orig; 723 | UIColor *secondaryTextColor = [self secondaryTextColor]; 724 | 725 | if (secondaryTextColor) { 726 | NSAttributedString *newStr = copyAttributedStringWithColor(str, secondaryTextColor); 727 | [str release]; 728 | return newStr; 729 | } 730 | return str; 731 | } 732 | 733 | // TinyBar support (iOS 9.3+). 734 | - (id)_attributedStringForSecondaryText:(id)secondaryText italicized:(BOOL)italicized { 735 | NSAttributedString *str = %orig; 736 | UIColor *secondaryTextColor = [self secondaryTextColor]; 737 | 738 | if (secondaryTextColor) { 739 | NSAttributedString *newStr = copyAttributedStringWithColor(str, secondaryTextColor); 740 | return [newStr autorelease]; 741 | } 742 | return str; 743 | } 744 | 745 | %end 746 | 747 | %hook SBBannerButtonView 748 | 749 | %new 750 | - (void)colorizeWithColor:(int)color alpha:(CGFloat)alpha preferringBlack:(BOOL)wantsBlack { 751 | for (UIButton *button in self.buttons) { 752 | if ([button isKindOfClass:%c(SBNotificationVibrantButton)]) { 753 | SBNotificationVibrantButton *vibrantButton = (SBNotificationVibrantButton *)button; 754 | [vibrantButton colorizeWithColor:color alpha:alpha preferringBlack:wantsBlack]; 755 | } 756 | } 757 | } 758 | 759 | %end 760 | 761 | %hook SBNotificationVibrantButton 762 | 763 | %new 764 | - (void)configureButton:(UIButton *)button 765 | withTintColor:(UIColor *)tintColor 766 | selectedTintColor:(UIColor *)selectedTintColor 767 | textColor:(UIColor *)textColor 768 | selectedTextColor:(UIColor *)selectedTextColor { 769 | UIImage *buttonImage = [self _buttonImageForColor:tintColor selected:NO]; 770 | UIImage *selectedImage = [self _buttonImageForColor:selectedTintColor selected:YES]; 771 | [button setBackgroundImage:buttonImage forState:UIControlStateNormal]; 772 | [button setBackgroundImage:selectedImage forState:UIControlStateHighlighted]; 773 | [button setBackgroundImage:selectedImage forState:UIControlStateSelected]; 774 | [button setTitleColor:textColor forState:UIControlStateNormal]; 775 | [button setTitleColor:selectedTextColor forState:UIControlStateHighlighted]; 776 | [button setTitleColor:selectedTextColor forState:UIControlStateSelected]; 777 | } 778 | 779 | %new 780 | - (void)colorizeWithColor:(int)colorInt alpha:(CGFloat)alpha preferringBlack:(BOOL)wantsBlack { 781 | alpha = (alpha / 2) + 0.2; 782 | UIColor *color = UIColorFromRGBWithAlpha(colorInt, alpha); 783 | UIColor *darkerColor = [color cbr_darken:0.2]; 784 | UIColor *textColor = (wantsBlack) ? [UIColor darkGrayColor] : [UIColor whiteColor]; 785 | 786 | UIButton *overlayButton = MSHookIvar(self, "_overlayButton"); 787 | [self configureButton:overlayButton 788 | withTintColor:color 789 | selectedTintColor:darkerColor 790 | textColor:textColor 791 | selectedTextColor:textColor]; 792 | 793 | UIButton *vibrantButton = MSHookIvar(self, "_vibrantButton"); 794 | vibrantButton.hidden = YES; 795 | } 796 | 797 | %end 798 | 799 | // TODO(DavidGoldman): Make this less hacky. Would probably be better if we just set the tintFilter 800 | // to be white (hopefully that will work)/use a light filter instead of the dark one. 801 | %hook _UIBackdropView 802 | 803 | %new 804 | - (void)setIsForBannerContextView:(BOOL)flag { 805 | NSNumber *value = @(flag); 806 | objc_setAssociatedObject(self, @selector(isForBannerContextView), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 807 | } 808 | 809 | %new 810 | - (BOOL)isForBannerContextView { 811 | NSNumber *value = objc_getAssociatedObject(self, @selector(isForBannerContextView)); 812 | return [value boolValue]; 813 | } 814 | 815 | - (void)backdropLayerStatisticsDidChange:(CABackdropLayer *)layer { 816 | %orig; 817 | 818 | if ([self isForBannerContextView]) { 819 | NSDictionary *dict = [layer statisticsValues]; 820 | if (!dict) { 821 | return; 822 | } 823 | 824 | int r = (int)([dict[@"redAverage"] floatValue] * 255); 825 | int g = (int)([dict[@"greenAverage"] floatValue] * 255); 826 | int b = (int)([dict[@"blueAverage"] floatValue] * 255); 827 | 828 | UIView *superview = self.superview; 829 | if ([superview isMemberOfClass:%c(SBBannerContextView)]) { 830 | SBBannerContextView *bannerView = (SBBannerContextView *)superview; 831 | 832 | int color = [[bannerView cbr_color] intValue]; 833 | int bgColor = colorToRGBInt(r, g, b); 834 | [bannerView colorize:color withBackground:bgColor force:NO]; 835 | 836 | // Only do the analysis once if not "live". 837 | if (![CBRPrefsManager sharedInstance].wantsLiveAnalysis) { 838 | _UIBackdropView *backdropView = MSHookIvar<_UIBackdropView *>(bannerView, "_backdropView"); 839 | [backdropView setComputesColorSettings:NO]; 840 | } 841 | } 842 | } 843 | } 844 | 845 | - (void)setTintFilterForSettings:(id)settings { 846 | if ([self isForBannerContextView]) { 847 | return; 848 | } 849 | 850 | %orig; 851 | } 852 | 853 | - (void)setSaturationDeltaFactor:(CGFloat)factor { 854 | if ([self isForBannerContextView]) { 855 | return; 856 | } 857 | 858 | %orig; 859 | } 860 | 861 | %end 862 | %end 863 | 864 | %group RemoveUnderlay 865 | %hook SBLockScreenView 866 | 867 | - (void)_addLockContentUnderlayWithRequester:(id)requester { 868 | if ([CBRPrefsManager sharedInstance].removeLSBlur && [requester isEqual:@"NotificationList"]) { 869 | return; 870 | } 871 | 872 | %orig; 873 | } 874 | 875 | %end 876 | %end 877 | 878 | %group iOS9_NotificationCenter_Widgets 879 | %hook SBWidgetSectionInfo 880 | 881 | - (void)populateReusableView:(UIView *)view { 882 | %orig; 883 | 884 | if ([view isKindOfClass:%c(SBNotificationCenterHeaderView)]) { 885 | SBNotificationCenterHeaderView *headerView = (SBNotificationCenterHeaderView *)view; 886 | CBRPrefsManager *prefsManager = [CBRPrefsManager sharedInstance]; 887 | 888 | if (!prefsManager.ncEnabled) { 889 | [headerView cbr_setColor:nil]; 890 | return; 891 | } 892 | 893 | int color; 894 | 895 | if (prefsManager.ncUseConstantColor) { 896 | color = prefsManager.ncBackgroundColor; 897 | } else { 898 | SBWidgetRowInfo *widgetRowInfo = self.widgetRowInfo; 899 | NSString *identifier = [widgetRowInfo identifier]; 900 | UIImage *image = [widgetRowInfo icon]; 901 | 902 | if (!identifier) { 903 | CBRLOG(@"WARNING: No identifier for %@", self); 904 | } 905 | 906 | if (!image) { 907 | [headerView cbr_setColor:nil]; 908 | return; 909 | } 910 | 911 | color = [[CBRColorCache sharedInstance] colorForIdentifier:identifier image:image]; 912 | } 913 | 914 | [headerView cbr_setColor:@(color)]; 915 | [headerView cbr_colorizeIfNeeded]; 916 | } 917 | } 918 | 919 | %end 920 | %end 921 | 922 | %group NotificationCenter_BB 923 | %hook SBNotificationCenterSectionInfo 924 | 925 | - (void)populateReusableView:(UIView *)view { 926 | %orig; 927 | 928 | if ([view isKindOfClass:%c(SBNotificationCenterHeaderView)]) { 929 | SBNotificationCenterHeaderView *headerView = (SBNotificationCenterHeaderView *)view; 930 | CBRPrefsManager *prefsManager = [CBRPrefsManager sharedInstance]; 931 | 932 | if (!prefsManager.ncEnabled) { 933 | [headerView cbr_setColor:nil]; 934 | return; 935 | } 936 | 937 | int color; 938 | 939 | if (prefsManager.ncUseConstantColor) { 940 | color = prefsManager.ncBackgroundColor; 941 | } else { 942 | NSString *identifier = nil; 943 | if ([self respondsToSelector:@selector(listSectionIdentifier)]) { 944 | identifier = [self listSectionIdentifier]; 945 | } 946 | UIImage *image = nil; 947 | if ([self respondsToSelector:@selector(representedListSection)]) { 948 | image = [self representedListSection].iconImage; 949 | } 950 | 951 | if (!identifier) { 952 | CBRLOG(@"WARNING: No identifier for %@", self); 953 | } 954 | 955 | if (!image) { 956 | [headerView cbr_setColor:nil]; 957 | return; 958 | } 959 | 960 | color = [[CBRColorCache sharedInstance] colorForIdentifier:identifier image:image]; 961 | } 962 | 963 | [headerView cbr_setColor:@(color)]; 964 | // Need to manually colorize on iOS 9. 965 | if (IS_IOS9_OR_NEWER) { 966 | [headerView cbr_colorizeIfNeeded]; 967 | } 968 | } 969 | } 970 | 971 | %end 972 | %end 973 | 974 | %group NotificationCenter 975 | 976 | %hook SBNotificationCenterHeaderView 977 | 978 | - (void)setGraphicsQuality:(NSInteger)quality { 979 | %orig; 980 | 981 | [self cbr_colorizeIfNeeded]; 982 | } 983 | 984 | - (void)layoutSubviews { 985 | %orig; 986 | 987 | CBRGradientView *gradientView = (CBRGradientView *)[self.contentView viewWithTag:VIEW_TAG]; 988 | gradientView.frame = self.contentView.bounds; 989 | } 990 | 991 | %new 992 | - (void)cbr_colorizeIfNeeded { 993 | NSNumber *color = [self cbr_color]; 994 | NSNumber *activeColor = [self cbr_activeColor]; 995 | 996 | if (color == activeColor || [color isEqual:activeColor]) { 997 | return; 998 | } 999 | 1000 | if (color) { 1001 | [self cbr_colorize:[color intValue]]; 1002 | } else { 1003 | [self cbr_revert]; 1004 | } 1005 | } 1006 | 1007 | %new 1008 | - (void)cbr_colorize:(int)color { 1009 | [self cbr_setActiveColor:@(color)]; 1010 | 1011 | // Create/update gradient. 1012 | CBRGradientView *gradientView = (CBRGradientView *)[self.contentView viewWithTag:VIEW_TAG]; 1013 | UIColor *color1 = UIColorFromRGB(color); 1014 | 1015 | if (!gradientView) { 1016 | gradientView = [[CBRGradientView alloc] initWithFrame:self.contentView.bounds]; 1017 | gradientView.tag = VIEW_TAG; 1018 | [self.contentView insertSubview:gradientView atIndex:0]; 1019 | [gradientView autorelease]; 1020 | } 1021 | gradientView.hidden = NO; 1022 | gradientView.alpha = [CBRPrefsManager sharedInstance].ncAlpha; 1023 | 1024 | if ([CBRPrefsManager sharedInstance].useNCGradient) { 1025 | UIColor *color2 = (isWhitish(color)) ? [color1 cbr_darken:0.1] : [color1 cbr_lighten:0.1]; 1026 | NSArray *colors = @[ (id)color1.CGColor, (id)color2.CGColor ]; 1027 | [gradientView setColors:colors]; 1028 | } else { 1029 | [gradientView setSolidColor:color1]; 1030 | } 1031 | 1032 | // Remove the darkening view. 1033 | UIView *view = MSHookIvar(self, "_plusDView"); 1034 | view.hidden = YES; 1035 | 1036 | UILabel *label = self.titleLabel; 1037 | label.textColor = (isWhitish(color)) ? [UIColor darkGrayColor] : [UIColor whiteColor]; 1038 | } 1039 | 1040 | %new 1041 | - (void)cbr_revert { 1042 | [self cbr_setActiveColor:nil]; 1043 | CBRGradientView *gradientView = (CBRGradientView *)[self.contentView viewWithTag:VIEW_TAG]; 1044 | gradientView.hidden = YES; 1045 | 1046 | UIView *view = MSHookIvar(self, "_plusDView"); 1047 | view.hidden = NO; 1048 | 1049 | UILabel *label = self.titleLabel; 1050 | label.textColor = UIColorFromRGBWithAlpha(0xFFFFFF, 0.7); 1051 | } 1052 | 1053 | %new 1054 | - (NSNumber *)cbr_activeColor { 1055 | return objc_getAssociatedObject(self, @selector(cbr_activeColor)); 1056 | } 1057 | 1058 | %new 1059 | - (void)cbr_setActiveColor:(NSNumber *)color { 1060 | objc_setAssociatedObject(self, @selector(cbr_activeColor), color, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 1061 | } 1062 | 1063 | %new 1064 | - (NSNumber *)cbr_color { 1065 | return objc_getAssociatedObject(self, @selector(cbr_color)); 1066 | } 1067 | 1068 | %new 1069 | - (void)cbr_setColor:(NSNumber *)color { 1070 | objc_setAssociatedObject(self, @selector(cbr_color), color, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 1071 | } 1072 | 1073 | %end 1074 | %end 1075 | 1076 | static UIColor * getNormalColor(BOOL darker) { 1077 | return (darker) ? [UIColor darkGrayColor] : [UIColor whiteColor]; 1078 | } 1079 | 1080 | static UIColor * getMildColor(BOOL darker) { 1081 | return (darker) ? [UIColor grayColor] : 1082 | [UIColor colorWithRed:0.780392 green:0.780392 blue:0.8 alpha:1]; 1083 | } 1084 | 1085 | %group Messages_QuickReply 1086 | %hook CKMessageEntryView 1087 | 1088 | %new 1089 | - (void)cbr_setModal:(BOOL)modal { 1090 | objc_setAssociatedObject(self, @selector(cbr_isModal), @(modal), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 1091 | } 1092 | 1093 | %new 1094 | - (BOOL)cbr_isModal { 1095 | NSNumber *value = objc_getAssociatedObject(self, @selector(cbr_isModal)); 1096 | return [value boolValue]; 1097 | } 1098 | 1099 | // According to InspectiveC logging, they like to set colors in here. 1100 | - (void)updateEntryView { 1101 | %orig; 1102 | 1103 | if ([self cbr_isModal] || ![CBRPrefsManager sharedInstance].bannersEnabled) { 1104 | return; 1105 | } 1106 | 1107 | BOOL useDarkText = [CBRReadabilityManager sharedInstance].shouldUseDarkText; 1108 | UIColor *tintColor = getNormalColor(useDarkText); 1109 | 1110 | self.audioButton.tintColor = tintColor; 1111 | UIButton *button = self.sendButton; 1112 | [button setTitleColor:tintColor forState:UIControlStateNormal]; 1113 | [button setTitleColor:getMildColor(useDarkText) forState:UIControlStateDisabled]; 1114 | } 1115 | 1116 | %end 1117 | 1118 | %hook CKInlineReplyViewController 1119 | 1120 | - (void)updateSendButton { 1121 | %orig; 1122 | 1123 | if (self.modal || ![CBRPrefsManager sharedInstance].bannersEnabled) { 1124 | return; 1125 | } 1126 | 1127 | BOOL useDarkText = [CBRReadabilityManager sharedInstance].shouldUseDarkText; 1128 | UIButton *button = self.entryView.sendButton; 1129 | [button setTitleColor:getNormalColor(useDarkText) forState:UIControlStateNormal]; 1130 | [button setTitleColor:getMildColor(useDarkText) forState:UIControlStateDisabled]; 1131 | } 1132 | 1133 | - (void)setupView { 1134 | %orig; 1135 | 1136 | BOOL modal = self.modal; 1137 | [self.entryView cbr_setModal:modal]; 1138 | if (modal || ![CBRPrefsManager sharedInstance].bannersEnabled) { 1139 | return; 1140 | } 1141 | 1142 | [CBRReadabilityManager sharedInstance].delegate = (id)self; 1143 | 1144 | // To hide the rounded-rect altogether. 1145 | if ([CBRPrefsManager sharedInstance].hideQRRect) { 1146 | CKMessageEntryView *entryView = self.entryView; 1147 | _UITextFieldRoundedRectBackgroundViewNeue *view = MSHookIvar(entryView, "_coverView"); 1148 | view.hidden = YES; 1149 | } 1150 | 1151 | [self cbr_updateReadability:[CBRReadabilityManager sharedInstance].shouldUseDarkText]; 1152 | } 1153 | 1154 | %new 1155 | - (void)cbr_updateReadability:(BOOL)useDarkText { 1156 | if (self.modal) { 1157 | return; 1158 | } 1159 | UIColor *tintColor = getNormalColor(useDarkText); 1160 | UIColor *mildColor = getMildColor(useDarkText); 1161 | 1162 | UIButton *button = self.entryView.sendButton; 1163 | [button setTitleColor:tintColor forState:UIControlStateNormal]; 1164 | [button setTitleColor:mildColor forState:UIControlStateDisabled]; 1165 | 1166 | CKMessageEntryContentView *contentView = self.entryView.contentView; 1167 | CKMessageEntryRichTextView *textView = contentView.textView; 1168 | textView.textColor = tintColor; 1169 | 1170 | textView.tintColor = tintColor; 1171 | // Needed in order to get the UITextView to properly change the cursor color. 1172 | // See http://stackoverflow.com/questions/23725552/uitextview-cursor-color-not-changing-ios-7 1173 | if ([textView isFirstResponder]) { 1174 | [textView resignFirstResponder]; 1175 | [textView becomeFirstResponder]; 1176 | } 1177 | textView.placeholderLabel.textColor = mildColor; 1178 | 1179 | UIButton *audioButton = self.entryView.audioButton; 1180 | audioButton.tintColor = tintColor; 1181 | } 1182 | 1183 | %new 1184 | - (void)managersReadabilityStateDidChange:(CBRReadabilityManager *)manager { 1185 | [self cbr_updateReadability:manager.shouldUseDarkText]; 1186 | } 1187 | 1188 | - (void)dealloc { 1189 | [CBRReadabilityManager sharedInstance].delegate = nil; 1190 | %orig; 1191 | } 1192 | 1193 | %end 1194 | %end 1195 | 1196 | %group iOS9_QuickReply 1197 | %hook SBBannerContextView 1198 | - (void)replacePullDownViewWithView:(UIView *)view animated:(BOOL)animated { 1199 | [self recolorizePullDown:view]; 1200 | 1201 | %orig; 1202 | } 1203 | %end 1204 | %hook NCNotificationActionTextInputViewController 1205 | %new 1206 | - (void)cbr_colorize:(int)color alpha:(CGFloat)alpha preferringBlack:(BOOL)wantsBlack { 1207 | // TODO: Make sure this means what I think it means. 1208 | if (self.modal) { 1209 | return; 1210 | } 1211 | 1212 | // To hide the rounded-rect altogether. 1213 | if ([CBRPrefsManager sharedInstance].hideQRRect) { 1214 | self.coverView.hidden = YES; 1215 | } 1216 | 1217 | UIColor *tintColor = getNormalColor(wantsBlack); 1218 | 1219 | UIButton *sendButton = self.sendButton; 1220 | [sendButton setTitleColor:tintColor forState:UIControlStateNormal]; 1221 | [sendButton setTitleColor:getMildColor(wantsBlack) forState:UIControlStateDisabled]; 1222 | 1223 | UITextView *textView = self.textEntryView; 1224 | textView.textColor = tintColor; 1225 | textView.tintColor = tintColor; 1226 | // Needed in order to get the UITextView to properly change the cursor color. 1227 | // See http://stackoverflow.com/questions/23725552/uitextview-cursor-color-not-changing-ios-7 1228 | if ([textView isFirstResponder]) { 1229 | [textView resignFirstResponder]; 1230 | [textView becomeFirstResponder]; 1231 | } 1232 | } 1233 | %end 1234 | %end 1235 | 1236 | %ctor { 1237 | NSString *bundle = [NSBundle mainBundle].bundleIdentifier; 1238 | 1239 | if ([bundle isEqualToString:@"com.apple.springboard"]) { 1240 | %init(TestNotifications); 1241 | %init(LockScreen); 1242 | %init(Banners); 1243 | %init(NotificationCenter); 1244 | %init(RemoveUnderlay); 1245 | 1246 | // iOS 9 Notification Center stuff. 1247 | BOOL iOS9 = IS_IOS9_OR_NEWER; 1248 | Class SectionInfo_Class = %c(SBNotificationCenterSectionInfo); 1249 | if (iOS9) { 1250 | %init(iOS9_NotificationCenter_Widgets); 1251 | SectionInfo_Class = %c(SBBBSectionInfo); 1252 | } 1253 | %init(NotificationCenter_BB, SBNotificationCenterSectionInfo=SectionInfo_Class); 1254 | 1255 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), 1256 | NULL, 1257 | &showTestLockScreenNotification, 1258 | CFSTR(TEST_LS), 1259 | NULL, 1260 | 0); 1261 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), 1262 | NULL, 1263 | &showTestBanner, 1264 | CFSTR(TEST_BANNER), 1265 | NULL, 1266 | 0); 1267 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), 1268 | NULL, 1269 | &respring, 1270 | CFSTR(RESPRING), 1271 | NULL, 1272 | 0); 1273 | 1274 | // iOS 9 has some Quick Reply classes loaded in SpringBoard. 1275 | if (iOS9) { 1276 | %init(iOS9_QuickReply); 1277 | } 1278 | 1279 | [CBRReadabilityManager sharedInstance]; 1280 | } 1281 | else if ([bundle isEqualToString:@"com.apple.mobilesms.notification"]) { 1282 | %init(Messages_QuickReply); 1283 | [CBRReadabilityManager sharedInstance]; 1284 | } 1285 | } 1286 | --------------------------------------------------------------------------------