├── .gitignore ├── LICENSE ├── Makefile ├── Prefs ├── CCURootListController.h ├── CCURootListController.m ├── CCUSubListController.h ├── CCUSubListController.m ├── Makefile ├── Resources │ ├── CustomizeFill.plist │ ├── CustomizeTimer.plist │ ├── Info.plist │ ├── Root.plist │ ├── icon.png │ └── icon@2x.png └── entry.plist ├── README.md ├── Tweak ├── Cucu.plist ├── CucuTimer.m ├── Makefile ├── Tweak.h └── Tweak.x └── control /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .theos 3 | packages -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Diego Barría 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | export ARCHS = arm64 arm64e 2 | export SYSROOT = $(THEOS)/sdks/iPhoneOS13.0.sdk 3 | export PREFIX=$(THEOS)/toolchain/Xcode.xctoolchain/usr/bin/ 4 | export TARGET = iphone:clang:14.5:13.0 5 | 6 | INSTALL_TARGET_PROCESSES = SpringBoard 7 | 8 | SUBPROJECTS += Tweak 9 | SUBPROJECTS += Prefs 10 | 11 | include $(THEOS)/makefiles/common.mk 12 | include $(THEOS_MAKE_PATH)/aggregate.mk -------------------------------------------------------------------------------- /Prefs/CCURootListController.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | #import 5 | 6 | @interface CCURootListController : HBRootListController 7 | @end 8 | -------------------------------------------------------------------------------- /Prefs/CCURootListController.m: -------------------------------------------------------------------------------- 1 | #import "CCURootListController.h" 2 | 3 | @implementation CCURootListController 4 | 5 | - (instancetype) init { 6 | self = [super init]; 7 | 8 | if (self) { 9 | HBAppearanceSettings *appearanceSettings = [[HBAppearanceSettings alloc] init]; 10 | appearanceSettings.tintColor = [UIColor colorWithRed:(36.0/255.0) green:(132.0/255.0) blue:(128.0/255.0) alpha:1.0]; 11 | appearanceSettings.tableViewCellSeparatorColor = [UIColor colorWithWhite:0.0 alpha:0.0]; 12 | 13 | self.hb_appearanceSettings = appearanceSettings; 14 | } 15 | 16 | return self; 17 | } 18 | 19 | - (void) viewDidLoad { 20 | [super viewDidLoad]; 21 | 22 | // Add respring at right 23 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Test banner" style:UIBarButtonItemStyleDone target:self action:@selector(testBanner:)]; 24 | self.navigationItem.rightBarButtonItem.tintColor = [UIColor colorWithRed:(36.0/255.0) green:(132.0/255.0) blue:(128.0/255.0) alpha:1.0];; 25 | } 26 | 27 | - (void) setPreferenceValue:(id)value specifier:(PSSpecifier *)specifier { 28 | [super setPreferenceValue:value specifier:specifier]; 29 | 30 | if([[specifier propertyForKey:@"key"] isEqualToString:@"isEnabled"]) [self respringPrompt]; 31 | } 32 | 33 | - (void) respringPrompt { 34 | 35 | UIAlertController* resetAlert = [UIAlertController alertControllerWithTitle:@"Respring required" message:@"Changing this options requires a respring. Do you want to respring now?" preferredStyle:UIAlertControllerStyleActionSheet]; 36 | 37 | UIAlertAction* confirmAction = [UIAlertAction actionWithTitle:@"Yes" style:UIAlertActionStyleDestructive handler:^(UIAlertAction * action) { 38 | [self respring:nil]; 39 | }]; 40 | 41 | UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"No" style:UIAlertActionStyleCancel handler:nil]; 42 | 43 | [resetAlert addAction:confirmAction]; 44 | [resetAlert addAction:cancelAction]; 45 | 46 | [self presentViewController:resetAlert animated:YES completion:nil]; 47 | 48 | } 49 | 50 | - (UITableViewStyle)tableViewStyle { 51 | return UITableViewStyleInsetGrouped; 52 | } 53 | 54 | - (NSArray *)specifiers { 55 | if (!_specifiers) { 56 | _specifiers = [self loadSpecifiersFromPlistName:@"Root" target:self]; 57 | } 58 | 59 | return _specifiers; 60 | } 61 | 62 | - (void)testBanner:(id)sender { 63 | CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (CFStringRef)@"com.xyaman.cucupreferences/TestBanner", nil, nil, true); 64 | } 65 | 66 | - (void)respring:(id)sender { 67 | if ([[NSFileManager defaultManager] fileExistsAtPath:@"/Library/MobileSubstrate/DynamicLibraries/shuffle.dylib"]) { 68 | [HBRespringController respringAndReturnTo:[NSURL URLWithString:@"prefs:root=Tweaks&path=Cucu"]]; 69 | } else { 70 | [HBRespringController respringAndReturnTo:[NSURL URLWithString:@"prefs:root=Cucu"]]; 71 | } 72 | } 73 | @end 74 | -------------------------------------------------------------------------------- /Prefs/CCUSubListController.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | @interface CCUSubListController : HBListController 6 | @end -------------------------------------------------------------------------------- /Prefs/CCUSubListController.m: -------------------------------------------------------------------------------- 1 | #include "CCUSubListController.h" 2 | 3 | @implementation CCUSubListController 4 | 5 | - (void) viewDidLoad { 6 | [super viewDidLoad]; 7 | 8 | HBAppearanceSettings *appearanceSettings = [[HBAppearanceSettings alloc] init]; 9 | appearanceSettings.tintColor = [UIColor colorWithRed:(36.0/255.0) green:(132.0/255.0) blue:(128.0/255.0) alpha:1.0]; 10 | appearanceSettings.tableViewCellSeparatorColor = [UIColor colorWithWhite:0.0 alpha:0.0]; 11 | 12 | self.hb_appearanceSettings = appearanceSettings; 13 | } 14 | 15 | - (NSArray *) specifiers { 16 | return _specifiers; 17 | } 18 | 19 | - (void) loadFromSpecifier:(PSSpecifier *)specifier { 20 | 21 | NSString* sub = [specifier propertyForKey:@"VDESub"]; 22 | _specifiers = [self loadSpecifiersFromPlistName:sub target:self]; 23 | } 24 | 25 | - (void) setSpecifier:(PSSpecifier *)specifier { 26 | [self loadFromSpecifier:specifier]; 27 | [super setSpecifier:specifier]; 28 | } 29 | 30 | - (BOOL) shouldReloadSpecifiersOnResume { 31 | return false; 32 | } 33 | 34 | - (UITableViewStyle) tableViewStyle { 35 | return UITableViewStyleInsetGrouped; 36 | } 37 | 38 | @end -------------------------------------------------------------------------------- /Prefs/Makefile: -------------------------------------------------------------------------------- 1 | BUNDLE_NAME = CucuPreferences 2 | 3 | $(BUNDLE_NAME)_FILES = CCURootListController.m CCUSubListController.m 4 | $(BUNDLE_NAME)_FRAMEWORKS = UIKit 5 | $(BUNDLE_NAME)_LIBRARIES = gcuniversal 6 | $(BUNDLE_NAME)_PRIVATE_FRAMEWORKS = Preferences 7 | $(BUNDLE_NAME)_EXTRA_FRAMEWORKS = CepheiPrefs Cephei 8 | $(BUNDLE_NAME)_INSTALL_PATH = /Library/PreferenceBundles 9 | $(BUNDLE_NAME)_CFLAGS = -fobjc-arc 10 | 11 | include $(THEOS)/makefiles/common.mk 12 | include $(THEOS_MAKE_PATH)/bundle.mk 13 | 14 | internal-stage:: 15 | $(ECHO_NOTHING)mkdir -p "$(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences"$(ECHO_END) 16 | $(ECHO_NOTHING)cp entry.plist "$(THEOS_STAGING_DIR)/Library/PreferenceLoader/Preferences/$(BUNDLE_NAME).plist"$(ECHO_END) 17 | -------------------------------------------------------------------------------- /Prefs/Resources/CustomizeFill.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | cell 9 | PSGroupCell 10 | label 11 | Coloring style 12 | 13 | 14 | cell 15 | PSSegmentCell 16 | validValues 17 | 18 | 1 19 | 2 20 | 21 | validTitles 22 | 23 | Adaptative 24 | Custom 25 | 26 | default 27 | 1 28 | key 29 | fillColorStyle 30 | defaults 31 | com.xyaman.cucupreferences 32 | PostNotification 33 | com.xyaman.cucupreferences/ReloadPrefs 34 | 35 | 36 | cell 37 | PSLinkCell 38 | cellClass 39 | GcColorPickerCell 40 | label 41 | Custom color 42 | fallback 43 | 000000 44 | key 45 | fillCustomColor 46 | defaults 47 | com.xyaman.cucupreferences 48 | PostNotification 49 | com.xyaman.cucupreferences/ReloadPrefs 50 | 51 | 52 | title 53 | Customize Fill 54 | 55 | -------------------------------------------------------------------------------- /Prefs/Resources/CustomizeTimer.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | cell 9 | PSGroupCell 10 | label 11 | Circle Coloring Style 12 | 13 | 14 | cell 15 | PSSegmentCell 16 | validValues 17 | 18 | 1 19 | 2 20 | 21 | validTitles 22 | 23 | Adaptive 24 | Custom 25 | 26 | default 27 | 1 28 | key 29 | timerColorStyle 30 | defaults 31 | com.xyaman.cucupreferences 32 | PostNotification 33 | com.xyaman.cucupreferences/ReloadPrefs 34 | 35 | 36 | cell 37 | PSLinkCell 38 | cellClass 39 | GcColorPickerCell 40 | label 41 | Custom color 42 | fallback 43 | 000000 44 | key 45 | timerCustomColor 46 | defaults 47 | com.xyaman.cucupreferences 48 | PostNotification 49 | com.xyaman.cucupreferences/ReloadPrefs 50 | 51 | 52 | 53 | 54 | cell 55 | PSGroupCell 56 | label 57 | Text Coloring Style 58 | 59 | 60 | cell 61 | PSSegmentCell 62 | validValues 63 | 64 | 1 65 | 2 66 | 67 | validTitles 68 | 69 | Adaptive 70 | Custom 71 | 72 | default 73 | 1 74 | key 75 | timerTextColorStyle 76 | defaults 77 | com.xyaman.cucupreferences 78 | PostNotification 79 | com.xyaman.cucupreferences/ReloadPrefs 80 | 81 | 82 | cell 83 | PSLinkCell 84 | cellClass 85 | GcColorPickerCell 86 | label 87 | Custom color 88 | fallback 89 | 000000 90 | key 91 | timerTextCustomColor 92 | defaults 93 | com.xyaman.cucupreferences 94 | PostNotification 95 | com.xyaman.cucupreferences/ReloadPrefs 96 | 97 | 98 | 99 | 100 | cell 101 | PSGroupCell 102 | label 103 | Positioning 104 | 105 | 106 | cell 107 | PSStaticTextCell 108 | label 109 | Y Offset 110 | 111 | 112 | cell 113 | PSSliderCell 114 | default 115 | 0 116 | min 117 | -25 118 | max 119 | 25 120 | isSegmented 121 | 122 | segmentCount 123 | 50 124 | showValue 125 | 126 | key 127 | timerYOffset 128 | defaults 129 | com.xyaman.cucupreferences 130 | PostNotification 131 | com.xyaman.cucupreferences/ReloadPrefs 132 | 133 | 134 | cell 135 | PSStaticTextCell 136 | label 137 | X Offset 138 | 139 | 140 | cell 141 | PSSliderCell 142 | default 143 | 0 144 | min 145 | -25 146 | max 147 | 25 148 | isSegmented 149 | 150 | segmentCount 151 | 50 152 | showValue 153 | 154 | key 155 | timerXOffset 156 | defaults 157 | com.xyaman.cucupreferences 158 | PostNotification 159 | com.xyaman.cucupreferences/ReloadPrefs 160 | 161 | 162 | 163 | 164 | 165 | cell 166 | PSGroupCell 167 | label 168 | Sizing 169 | 170 | 171 | cellClass 172 | HBStepperTableCell 173 | default 174 | 20 175 | defaults 176 | com.xyaman.cucupreferences 177 | key 178 | timerSize 179 | label 180 | Timer Size: %i px 181 | max 182 | 60 183 | min 184 | 1 185 | singularLabel 186 | Timer Size: %i px 187 | PostNotification 188 | com.xyaman.cucupreferences/ReloadPrefs 189 | 190 | 191 | cellClass 192 | HBStepperTableCell 193 | default 194 | 8 195 | defaults 196 | com.xyaman.cucupreferences 197 | key 198 | timerFontSize 199 | label 200 | Font Size: %i px 201 | max 202 | 20 203 | min 204 | 1 205 | singularLabel 206 | Font Size: %i px 207 | PostNotification 208 | com.xyaman.cucupreferences/ReloadPrefs 209 | 210 | 211 | cellClass 212 | HBStepperTableCell 213 | default 214 | 3 215 | defaults 216 | com.xyaman.cucupreferences 217 | key 218 | timerLineWidth 219 | label 220 | Line Width: %i px 221 | max 222 | 20 223 | min 224 | 1 225 | singularLabel 226 | Line Width: %i px 227 | PostNotification 228 | com.xyaman.cucupreferences/ReloadPrefs 229 | 230 | 231 | title 232 | Customize Timer 233 | 234 | -------------------------------------------------------------------------------- /Prefs/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | CucuPreferences 9 | CFBundleIdentifier 10 | com.xyaman.cucupreferences 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1.0 21 | NSPrincipalClass 22 | CCURootListController 23 | 24 | 25 | -------------------------------------------------------------------------------- /Prefs/Resources/Root.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | cell 9 | PSGroupCell 10 | headerCellClass 11 | HBPackageNameHeaderCell 12 | condensed 13 | 14 | icon 15 | icon.png 16 | packageIdentifier 17 | com.xyaman.cucu 18 | footerText 19 | Customize your notifications banners 20 | footerAlignment 21 | 1 22 | 23 | 24 | cell 25 | PSGroupCell 26 | footerText 27 | Respring required 28 | 29 | 30 | cell 31 | PSSwitchCell 32 | default 33 | 34 | label 35 | Enabled 36 | key 37 | isEnabled 38 | defaults 39 | com.xyaman.cucupreferences 40 | id 41 | EnableButton 42 | 43 | 44 | 45 | cell 46 | PSGroupCell 47 | label 48 | Disable tap action for X seconds 49 | footerText 50 | Mainly to avoid accidentally touches. This does not have effect on iOS 13. 51 | 52 | 53 | cell 54 | PSSliderCell 55 | default 56 | 0 57 | min 58 | 0 59 | max 60 | 5 61 | showValue 62 | 63 | key 64 | preventActionTime 65 | defaults 66 | com.xyaman.cucupreferences 67 | PostNotification 68 | com.xyaman.cucupreferences/ReloadPrefs 69 | 70 | 71 | 72 | 73 | cell 74 | PSGroupCell 75 | label 76 | Dismiss notification banner after 77 | 78 | 79 | cellClass 80 | HBStepperTableCell 81 | default 82 | 6 83 | defaults 84 | com.xyaman.cucupreferences 85 | key 86 | dismissDelay 87 | label 88 | %i Seconds 89 | max 90 | 15 91 | min 92 | 1 93 | singularLabel 94 | 1 Second 95 | PostNotification 96 | com.xyaman.cucupreferences/ReloadPrefs 97 | 98 | 99 | 100 | 101 | cell 102 | PSGroupCell 103 | label 104 | Dismiss visualization style 105 | 106 | 107 | cell 108 | PSSegmentCell 109 | validValues 110 | 111 | 0 112 | 1 113 | 2 114 | 115 | validTitles 116 | 117 | None 118 | Timer 119 | Fill 120 | 121 | default 122 | 0 123 | key 124 | dismissStyle 125 | defaults 126 | com.xyaman.cucupreferences 127 | PostNotification 128 | com.xyaman.cucupreferences/ReloadPrefs 129 | 130 | 131 | cell 132 | PSLinkCell 133 | label 134 | Customize Timer 135 | detail 136 | CCUSubListController 137 | VDESub 138 | CustomizeTimer 139 | 140 | 141 | cell 142 | PSLinkCell 143 | label 144 | Customize Fill 145 | detail 146 | CCUSubListController 147 | VDESub 148 | CustomizeFill 149 | 150 | 151 | 152 | 153 | cell 154 | PSGroupCell 155 | label 156 | Other 157 | 158 | 159 | cellClass 160 | HBTwitterCell 161 | label 162 | Xyaman 163 | user 164 | xyaman_ 165 | 166 | 167 | cellClass 168 | HBLinkTableCell 169 | label 170 | Donate me️ 171 | subtitle 172 | Support my work. 173 | url 174 | https://paypal.me/xyamandev 175 | 176 | 177 | cellClass 178 | HBLinkTableCell 179 | label 180 | Source Code 181 | subtitle 182 | Github 183 | url 184 | https://github.com/xyaman/cucu 185 | 186 | 187 | title 188 | Cucu 189 | 190 | -------------------------------------------------------------------------------- /Prefs/Resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyaman/cucu/e134c4ea09d97e5acce316f150e8a3a5417df982/Prefs/Resources/icon.png -------------------------------------------------------------------------------- /Prefs/Resources/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyaman/cucu/e134c4ea09d97e5acce316f150e8a3a5417df982/Prefs/Resources/icon@2x.png -------------------------------------------------------------------------------- /Prefs/entry.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | entry 6 | 7 | 8 | cell 9 | PSLinkCell 10 | 11 | 12 | label 13 | Cucu 14 | 15 | 16 | icon 17 | icon.png 18 | 19 | 20 | detail 21 | CCURootListController 22 | isController 23 | 24 | 25 | 26 | bundle 27 | CucuPreferences 28 | 29 | 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cucu 2 | 3 | Customize your notifications banners -------------------------------------------------------------------------------- /Tweak/Cucu.plist: -------------------------------------------------------------------------------- 1 | { Filter = { Bundles = ( "com.apple.springboard" ); }; } 2 | -------------------------------------------------------------------------------- /Tweak/CucuTimer.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyaman/cucu/e134c4ea09d97e5acce316f150e8a3a5417df982/Tweak/CucuTimer.m -------------------------------------------------------------------------------- /Tweak/Makefile: -------------------------------------------------------------------------------- 1 | TWEAK_NAME = Cucu 2 | 3 | $(TWEAK_NAME)_FILES = Tweak.x 4 | $(TWEAK_NAME)_CFLAGS = -DTHEOS_LEAN_AND_MEAN -fobjc-arc 5 | $(TWEAK_NAME)_FRAMEWORKS = UIKit 6 | $(TWEAK_NAME)_LIBRARIES = kuro gcuniversal 7 | $(TWEAK_NAME)_EXTRA_FRAMEWORKS = Cephei 8 | 9 | 10 | include $(THEOS)/makefiles/common.mk 11 | include $(THEOS_MAKE_PATH)/tweak.mk 12 | -------------------------------------------------------------------------------- /Tweak/Tweak.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | #import 6 | #import 7 | 8 | 9 | // Preferences 10 | HBPreferences *preferences = nil; 11 | BOOL isEnabled = NO; 12 | 13 | NSNumber *prefDismissStyle = nil; 14 | 15 | // Delay 16 | NSNumber *prefPreventActionTime = nil; 17 | NSNumber *prefDismissDelay = nil; 18 | 19 | // Fill preferences 20 | NSNumber *prefFillColorStyle = nil; 21 | NSString *prefFillCustomColor = nil; 22 | 23 | // Fill preferences 24 | NSNumber *prefTimerColorStyle = nil; 25 | NSString *prefTimerCustomColor = nil; 26 | 27 | NSNumber *prefTimerTextColorStyle = nil; 28 | NSString *prefTimerTextCustomColor = nil; 29 | NSNumber *prefTimerSize = nil; 30 | NSNumber *prefTimerFontSize = nil; 31 | NSNumber *prefTimerLineWidth = nil; 32 | NSNumber *prefTimerYOffset = nil; 33 | NSNumber *prefTimerXOffset = nil; 34 | 35 | @interface UIView (Private) 36 | - (id)_viewControllerForAncestor; 37 | @end 38 | 39 | @interface VelvetBackgroundView : UIView 40 | @end 41 | 42 | @interface PLPlatterHeaderContentView : UIView 43 | -(UIView *)backgroundView; 44 | @end 45 | 46 | @interface SBNotificationBannerDestination : NSObject 47 | @property(nonatomic) BOOL canExecuteAction; 48 | -(id)_startTimerWithDelay:(unsigned long long)arg1 eventHandler:(id)arg2; 49 | @end 50 | 51 | @interface NCNotificationShortLookView : UIView 52 | @property(nonatomic) BOOL isBanner; 53 | @property(nonatomic, retain) UILabel *cucuCountLabel; 54 | @property(nonatomic) int cucuCount; 55 | 56 | // Compatibility 57 | @property(nonatomic, retain) UIView *liddellView; // Liddell 58 | @property(nonatomic, retain) UIView *baseView; // 59 | @property(nonatomic, retain, readwrite) VelvetBackgroundView *velvetBackground; // Velvet 60 | 61 | @property (nonatomic,copy) NSArray *icons; 62 | 63 | // Timer 64 | - (UIView *) createTimerViewWithSuperview:(UIView *)superview andConstraintsFrom:(UIView *)sibling; 65 | 66 | // Fill 67 | - (UIView *) createFillViewWithSuperview:(UIView *)superview; 68 | @end 69 | 70 | @interface BBAction : NSObject 71 | + (id)actionWithLaunchBundleID:(id)arg1 callblock:(id)arg2; 72 | @end 73 | 74 | @interface BBBulletin : NSObject 75 | @property(nonatomic, copy)NSString* sectionID; 76 | @property(nonatomic, copy)NSString* recordID; 77 | @property(nonatomic, copy)NSString* publisherBulletinID; 78 | @property(nonatomic, copy)NSString* title; 79 | @property(nonatomic, copy)NSString* message; 80 | @property(nonatomic, retain)NSDate* date; 81 | @property(assign, nonatomic)BOOL clearable; 82 | @property(nonatomic)BOOL showsMessagePreview; 83 | @property(nonatomic, copy)BBAction* defaultAction; 84 | @property(nonatomic, copy)NSString* bulletinID; 85 | @property(nonatomic, retain)NSDate* lastInterruptDate; 86 | @property(nonatomic, retain)NSDate* publicationDate; 87 | @end 88 | 89 | @interface BBServer : NSObject 90 | - (void)publishBulletin:(BBBulletin *)arg1 destinations:(NSUInteger)arg2 alwaysToLockScreen:(BOOL)arg3; 91 | - (void)publishBulletin:(id)arg1 destinations:(unsigned long long)arg2; 92 | @end 93 | 94 | @interface BBObserver : NSObject 95 | @end 96 | 97 | @interface NCBulletinNotificationSource : NSObject 98 | - (BBObserver *)observer; 99 | @end 100 | 101 | @interface CucuTimerView : UIView 102 | @property(nonatomic, retain) CAShapeLayer *shapeLayer; 103 | @property(nonatomic, retain) UILabel *countLabel; 104 | @property(nonatomic) int count; 105 | @property(nonatomic) UIColor *strokeColor; 106 | @property(nonatomic) int lineWidth; 107 | 108 | - (void) startCountTimer; 109 | @end -------------------------------------------------------------------------------- /Tweak/Tweak.x: -------------------------------------------------------------------------------- 1 | #import "Tweak.h" 2 | 3 | #define RESPONDS_TO(item) [self respondsToSelector:@selector(item)] 4 | #define ANCESTOR_RESPONDS_TO(item) [[self _viewControllerForAncestor] respondsToSelector:@selector(item)] 5 | 6 | #define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) 7 | 8 | /*---------------------- 9 | / Banner notification 10 | -----------------------*/ 11 | static BBServer* bbServer = nil; 12 | // From litten lisa 13 | static dispatch_queue_t getBBServerQueue() { 14 | 15 | static dispatch_queue_t queue; 16 | static dispatch_once_t predicate; 17 | 18 | dispatch_once(&predicate, ^{ 19 | void* handle = dlopen(NULL, RTLD_GLOBAL); 20 | if (handle) { 21 | dispatch_queue_t __weak* pointer = (__weak dispatch_queue_t *) dlsym(handle, "__BBServerQueue"); 22 | if (pointer) queue = *pointer; 23 | dlclose(handle); 24 | } 25 | }); 26 | 27 | return queue; 28 | 29 | } 30 | 31 | %hook BBServer 32 | - (id)initWithQueue:(id)arg1 { 33 | bbServer = %orig; 34 | return bbServer; 35 | 36 | } 37 | 38 | - (id)initWithQueue:(id)arg1 dataProviderManager:(id)arg2 syncService:(id)arg3 dismissalSyncCache:(id)arg4 observerListener:(id)arg5 utilitiesListener:(id)arg6 conduitListener:(id)arg7 systemStateListener:(id)arg8 settingsListener:(id)arg9 { 39 | 40 | bbServer = %orig; 41 | return bbServer; 42 | 43 | } 44 | 45 | - (void)dealloc { 46 | 47 | if (bbServer == self) bbServer = nil; 48 | %orig; 49 | } 50 | %end 51 | 52 | static void fakeBanner() { 53 | 54 | BBBulletin* bulletin = [[%c(BBBulletin) alloc] init]; 55 | 56 | bulletin.title = @"Cucu"; 57 | bulletin.message = @"This is a test banner"; 58 | bulletin.sectionID = @"com.apple.MobileSMS"; 59 | bulletin.bulletinID = [[NSProcessInfo processInfo] globallyUniqueString]; 60 | bulletin.recordID = [[NSProcessInfo processInfo] globallyUniqueString]; 61 | bulletin.publisherBulletinID = [[NSProcessInfo processInfo] globallyUniqueString]; 62 | bulletin.date = [NSDate date]; 63 | bulletin.defaultAction = [%c(BBAction) actionWithLaunchBundleID:@"com.apple.MobileSMS" callblock:nil]; 64 | bulletin.clearable = YES; 65 | bulletin.showsMessagePreview = YES; 66 | bulletin.publicationDate = [NSDate date]; 67 | bulletin.lastInterruptDate = [NSDate date]; 68 | 69 | if ([bbServer respondsToSelector:@selector(publishBulletin:destinations:)]) { 70 | dispatch_sync(getBBServerQueue(), ^{ 71 | [bbServer publishBulletin:bulletin destinations:15]; 72 | }); 73 | } 74 | } 75 | 76 | @implementation CucuTimerView : UIView 77 | - (id) init { 78 | self = [super init]; 79 | 80 | self.backgroundColor = [UIColor clearColor]; 81 | 82 | self.count = [prefDismissDelay intValue] + 1; // lol 83 | 84 | self.countLabel = [UILabel new]; 85 | self.countLabel.backgroundColor = [UIColor clearColor]; 86 | self.countLabel.textColor = [UIColor labelColor]; 87 | self.countLabel.font = [UIFont systemFontOfSize:8]; 88 | self.countLabel.textAlignment = NSTextAlignmentCenter; 89 | [self addSubview:self.countLabel]; 90 | 91 | return self; 92 | } 93 | 94 | - (void) layoutSubviews { 95 | [super layoutSubviews]; 96 | 97 | if(self.frame.origin.y > 0 && !self.shapeLayer) { 98 | 99 | // TODO: change this 100 | self.countLabel.bounds = self.bounds; 101 | 102 | // Shape layer 103 | self.shapeLayer = [CAShapeLayer layer]; 104 | self.shapeLayer.fillColor = [UIColor clearColor].CGColor; 105 | self.shapeLayer.strokeColor = self.strokeColor.CGColor; 106 | self.shapeLayer.lineCap = kCALineCapRound; 107 | 108 | self.shapeLayer.lineWidth = self.lineWidth; 109 | self.shapeLayer.strokeEnd = 0; 110 | 111 | self.shapeLayer.path = [UIBezierPath bezierPathWithArcCenter:self.countLabel.center radius:self.frame.size.width/2 startAngle:-M_PI/2 endAngle:2* M_PI clockwise:YES].CGPath; 112 | 113 | [self.layer addSublayer:self.shapeLayer]; 114 | 115 | CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; 116 | anim.toValue = @(1); 117 | anim.duration = self.count + 0.3; 118 | [self.shapeLayer addAnimation:anim forKey:@"loli"]; 119 | 120 | // Start count timer 121 | [self startCountTimer]; 122 | } 123 | } 124 | 125 | - (void) startCountTimer { 126 | self.count -= 1; 127 | self.countLabel.text = [NSString stringWithFormat:@"%d", self.count]; 128 | 129 | if(self.count > 0) [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(startCountTimer) userInfo:nil repeats:NO]; 130 | } 131 | @end 132 | 133 | /*---------------------- 134 | / Cucu 135 | -----------------------*/ 136 | %group Cucu 137 | 138 | // Change notification banner dismiss delay 139 | %hook SBNotificationBannerDestination 140 | %property (nonatomic) BOOL canExecuteAction; 141 | // Change dismiss delay (default is 6) 142 | - (id) _startTimerWithDelay:(unsigned long long)arg1 eventHandler:(id)arg2 { 143 | return %orig([prefDismissDelay intValue], arg2); 144 | } 145 | 146 | // Every time a banner will appear, we set execute action to false 147 | -(void)presentableWillAppearAsBanner:(id)arg0 { 148 | %orig; 149 | 150 | // We only initialize timer if there if prevent action time, this way we reduce memory usage 151 | if([prefPreventActionTime floatValue] == 0) { 152 | self.canExecuteAction = YES; 153 | 154 | } else { 155 | self.canExecuteAction = NO; 156 | [NSTimer scheduledTimerWithTimeInterval:[prefPreventActionTime floatValue] repeats:NO block:^(NSTimer *timer) { 157 | self.canExecuteAction = YES; 158 | }]; 159 | } 160 | } 161 | 162 | // Tap or click 163 | - (void) notificationViewController:(id)arg0 executeAction:(id)arg1 withParameters:(id)arg2 completion:(id)arg3 { 164 | if(self.canExecuteAction || SYSTEM_VERSION_LESS_THAN(@"14.0")) %orig; 165 | } 166 | %end 167 | 168 | %hook NCNotificationShortLookView 169 | %property(nonatomic, retain) UILabel *cucuCountLabel; 170 | %property(nonatomic) int cucuCount; 171 | 172 | - (void) didMoveToWindow { 173 | %orig; 174 | 175 | if (!ANCESTOR_RESPONDS_TO(delegate)) return; 176 | if (![[[self _viewControllerForAncestor] delegate] isKindOfClass:%c(SBNotificationBannerDestination)]) return; 177 | 178 | if([prefDismissStyle intValue] == 0) return; 179 | self.clipsToBounds = YES; 180 | self.layer.cornerRadius = 13; 181 | 182 | if((RESPONDS_TO(baseView) || RESPONDS_TO(liddellView))) return; 183 | 184 | if([prefDismissStyle intValue] == 1) [self createTimerViewWithSuperview:self andConstraintsFrom:self]; 185 | else if([prefDismissStyle intValue] == 2) [self createFillViewWithSuperview:self]; 186 | 187 | } 188 | 189 | // Used to make it compatible with other tweaks >.< 190 | - (void) didAddSubview:(UIView *)subview { 191 | %orig; 192 | 193 | if (!ANCESTOR_RESPONDS_TO(delegate)) return; 194 | if (![[[self _viewControllerForAncestor] delegate] isKindOfClass:%c(SBNotificationBannerDestination)]) return; 195 | 196 | if(RESPONDS_TO(liddellView) && subview == self.liddellView) { 197 | if([prefDismissStyle intValue] == 1) { 198 | [self createTimerViewWithSuperview:self andConstraintsFrom:self.liddellView]; 199 | 200 | } else if([prefDismissStyle intValue] == 2) { 201 | [self createFillViewWithSuperview:self.liddellView]; 202 | } 203 | 204 | } else if(RESPONDS_TO(baseView) && subview == self.baseView) { 205 | if([prefDismissStyle intValue] == 1) { 206 | [self createTimerViewWithSuperview:self andConstraintsFrom:self.baseView]; 207 | 208 | } else if([prefDismissStyle intValue] == 2) { 209 | [self createFillViewWithSuperview:self.baseView]; 210 | } 211 | 212 | } 213 | // } else if(RESPONDS_TO(velvetBackground) && [subview isKindOfClass:%c(VelvetBackgroundView)]) { 214 | // self.velvetBackground = (id)subview; 215 | // if([prefDismissStyle intValue] == 2) [self createFillViewWithSuperview:self.velvetBackground]; 216 | // } 217 | 218 | } 219 | 220 | %new 221 | -(UIView *) createTimerViewWithSuperview:(UIView *)superview andConstraintsFrom:(UIView *)sibling { 222 | 223 | CucuTimerView *timer = [CucuTimerView new]; 224 | timer.userInteractionEnabled = NO; 225 | 226 | // Settings 227 | timer.countLabel.font = [UIFont systemFontOfSize:[prefTimerFontSize intValue]]; 228 | timer.lineWidth = [prefTimerLineWidth floatValue]; 229 | 230 | // Coloring 231 | if([prefTimerColorStyle intValue] == 1) timer.strokeColor = [Kuro getPrimaryColor:self.icons[0]]; 232 | else if([prefTimerColorStyle intValue] == 2) timer.strokeColor = [GcColorPickerUtils colorWithHex:prefTimerCustomColor]; 233 | 234 | // Font coloring 235 | if([prefTimerTextColorStyle intValue] == 1) timer.countLabel.textColor = [Kuro getPrimaryColor:self.icons[0]]; 236 | else if([prefTimerTextColorStyle intValue] == 2) timer.countLabel.textColor = [GcColorPickerUtils colorWithHex:prefTimerTextCustomColor]; 237 | 238 | // Add to superview 239 | [superview addSubview:timer]; 240 | 241 | timer.translatesAutoresizingMaskIntoConstraints = NO; 242 | [timer.centerYAnchor constraintEqualToAnchor:sibling.centerYAnchor constant:[prefTimerSize floatValue]/2 + [prefTimerYOffset floatValue]].active = YES; 243 | [timer.rightAnchor constraintEqualToAnchor:sibling.rightAnchor constant:-5 + [prefTimerXOffset floatValue]].active = YES; 244 | [timer.widthAnchor constraintEqualToConstant:[prefTimerSize floatValue]].active = YES; 245 | [timer.heightAnchor constraintEqualToConstant:[prefTimerSize floatValue]].active = YES; 246 | 247 | return timer; 248 | } 249 | 250 | %new 251 | - (UIView *) createFillViewWithSuperview:(UIView *)superview { 252 | UIView *fill = [UIView new]; 253 | fill.userInteractionEnabled = NO; 254 | 255 | // Coloring 256 | if([prefFillColorStyle intValue] == 1) fill.backgroundColor = [Kuro getPrimaryColor:self.icons[0]]; 257 | else if([prefFillColorStyle intValue] == 2) fill.backgroundColor = [GcColorPickerUtils colorWithHex:prefFillCustomColor]; 258 | 259 | // Add to superview 260 | [superview insertSubview:fill atIndex:0]; 261 | 262 | // Animation 263 | fill.translatesAutoresizingMaskIntoConstraints = NO; 264 | [fill.topAnchor constraintEqualToAnchor:superview.topAnchor].active = YES; 265 | [fill.bottomAnchor constraintEqualToAnchor:superview.bottomAnchor].active = YES; 266 | [fill.leftAnchor constraintEqualToAnchor:superview.leftAnchor].active = YES; 267 | // [superview layoutIfNeeded]; 268 | 269 | [UIView animateWithDuration:[prefDismissDelay intValue] + 0.3 270 | delay:0 271 | options:UIViewAnimationOptionCurveLinear 272 | animations:^{ 273 | [fill.widthAnchor constraintEqualToConstant:359].active = YES; 274 | [superview layoutIfNeeded]; 275 | } 276 | completion:nil 277 | ]; 278 | 279 | 280 | return fill; 281 | } 282 | 283 | %new 284 | - (void) startCountTimer { 285 | self.cucuCount -= 1; 286 | self.cucuCountLabel.text = [NSString stringWithFormat:@"%d", self.cucuCount]; 287 | 288 | if(self.cucuCount > 0) [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(startCountTimer) userInfo:nil repeats:NO]; 289 | } 290 | %end 291 | 292 | %end 293 | 294 | %ctor { 295 | CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)fakeBanner, (CFStringRef)@"com.xyaman.cucupreferences/TestBanner", NULL, (CFNotificationSuspensionBehavior)kNilOptions); 296 | %init; 297 | 298 | preferences = [[HBPreferences alloc] initWithIdentifier:@"com.xyaman.cucupreferences"]; 299 | 300 | [preferences registerBool:&isEnabled default:NO forKey:@"isEnabled"]; 301 | if(!isEnabled) return; 302 | 303 | // Dismiss 304 | [preferences registerObject:&prefPreventActionTime default:@(0) forKey:@"preventActionTime"]; 305 | 306 | [preferences registerObject:&prefDismissDelay default:@(6) forKey:@"dismissDelay"]; 307 | [preferences registerObject:&prefDismissStyle default:@(0) forKey:@"dismissStyle"]; 308 | 309 | // Fill preferences 310 | [preferences registerObject:&prefFillColorStyle default:@(1) forKey:@"fillColorStyle"]; 311 | [preferences registerObject:&prefFillCustomColor default:@"000000" forKey:@"fillCustomColor"]; 312 | 313 | // Timer preferences 314 | [preferences registerObject:&prefTimerColorStyle default:@(1) forKey:@"timerColorStyle"]; 315 | [preferences registerObject:&prefTimerCustomColor default:@"000000" forKey:@"timerCustomColor"]; 316 | [preferences registerObject:&prefTimerTextColorStyle default:@(1) forKey:@"timerTextColorStyle"]; 317 | [preferences registerObject:&prefTimerTextCustomColor default:@"000000" forKey:@"timerTextCustomColor"]; 318 | [preferences registerObject:&prefTimerSize default:@(20) forKey:@"timerSize"]; 319 | [preferences registerObject:&prefTimerFontSize default:@(8) forKey:@"timerFontSize"]; 320 | [preferences registerObject:&prefTimerLineWidth default:@(3) forKey:@"timerLineWidth"]; 321 | [preferences registerObject:&prefTimerYOffset default:@(0) forKey:@"timerYOffset"]; 322 | [preferences registerObject:&prefTimerXOffset default:@(0) forKey:@"timerXOffset"]; 323 | 324 | %init(Cucu); 325 | } -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: com.xyaman.cucu 2 | Name: Cucu 3 | Version: 0.0.3 4 | Architecture: iphoneos-arm 5 | Description: Customize your notifications banners 6 | Maintainer: Xyaman 7 | Author: Xyaman 8 | Section: Tweaks 9 | Depends: mobilesubstrate, preferenceloader, com.xyaman.libkuro, com.mrgcgamer.libgcuniversal, ws.hbang.common (>= 1.17) 10 | Depiction: https://repo.xyaman.xyz/depictions/index.html?p=cucu 11 | SileoDepiction: https://repo.xyaman.xyz/depictions/cucu/depiction.json 12 | Icon: https://repo.xyaman.xyz/depictions/cucu/assets/icon.png 13 | --------------------------------------------------------------------------------