├── NotificationsGroupCount.plist ├── control ├── README.md ├── notificationsgroupcount ├── Makefile ├── NGCRootListController.h ├── NGCColorPickerCell.h ├── layout │ └── Library │ │ └── PreferenceLoader │ │ └── Preferences │ │ └── NotificationsGroupCount.plist ├── Resources │ ├── Info.plist │ └── Root.plist ├── NGCColorPickerCell.m └── NGCRootListController.m ├── Makefile ├── NGCBadgeView.h ├── Tweak.h ├── NGCBadgeView.m └── Tweak.xm /NotificationsGroupCount.plist: -------------------------------------------------------------------------------- 1 | { Filter = { Bundles = ( "com.apple.springboard" ); }; } 2 | -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | Package: com.0xkuj.notificationsgroupcount 2 | Name: NotificationsGroupCount 3 | Version: 1.0.6 4 | Architecture: iphoneos-arm 5 | Description: Count those notifications inside Apple notifications grouping! 6 | Maintainer: 0xkuj 7 | Author: 0xkuj 8 | Section: Tweaks 9 | Depends: mobilesubstrate (>= 0.9.5000) 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NotificationsGroupCount 2 | NotificationsGroupCount - count your grouped notifications on your lockscreen! 3 | 4 | This tweak original idea came from iOS 18.1, by Apple, and brought to your nearest jailbroken phone by me ❤️ 5 | 6 | ![for_reddit](https://github.com/user-attachments/assets/020041d8-439e-4b5c-a9f9-f7f3dd292084) 7 | -------------------------------------------------------------------------------- /notificationsgroupcount/Makefile: -------------------------------------------------------------------------------- 1 | TARGET := iphone:clang:16.5:16.0 2 | ARCHS = arm64 arm64e 3 | 4 | include $(THEOS)/makefiles/common.mk 5 | 6 | BUNDLE_NAME = NotificationsGroupCount 7 | 8 | NotificationsGroupCount_FILES = $(wildcard NGC*.*m) 9 | NotificationsGroupCount_FRAMEWORKS = UIKit 10 | NotificationsGroupCount_PRIVATE_FRAMEWORKS = Preferences 11 | NotificationsGroupCount_INSTALL_PATH = /Library/PreferenceBundles 12 | NotificationsGroupCount_CFLAGS = -fobjc-arc 13 | 14 | include $(THEOS_MAKE_PATH)/bundle.mk 15 | -------------------------------------------------------------------------------- /notificationsgroupcount/NGCRootListController.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | #define GENERAL_PREFS ROOT_PATH_NS(@"/var/mobile/Library/Preferences/com.0xkuj.notificationsgroupcountprefs.plist") 6 | 7 | @interface NGCRootListController : PSListController 8 | { 9 | UILabel* _label; 10 | UILabel* underLabel; 11 | NSArray* _allSpecifiers; 12 | } 13 | - (void)headerCell; 14 | - (void)defaultsettings:(PSSpecifier*)specifier; 15 | - (void)openTwitter; 16 | - (void)donationLink; 17 | @end 18 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | export TARGET = iphone:clang:16.5:16.0 2 | export THEOS_DEVICE_IP = 192.168.86.47 3 | export THEOS_PACKAGE_SCHEME=rootless 4 | export FINALPACKAGE=1 5 | INSTALL_TARGET_PROCESSES = SpringBoard 6 | GO_EASY_ON_ME = 1 7 | ARCHS = arm64 arm64e 8 | 9 | include $(THEOS)/makefiles/common.mk 10 | 11 | TWEAK_NAME = NotificationsGroupCount 12 | 13 | NotificationsGroupCount_FILES = Tweak.xm NGCBadgeView.m 14 | NotificationsGroupCount_CFLAGS = -fobjc-arc 15 | include $(THEOS_MAKE_PATH)/tweak.mk 16 | SUBPROJECTS += notificationsgroupcount 17 | include $(THEOS_MAKE_PATH)/aggregate.mk 18 | -------------------------------------------------------------------------------- /notificationsgroupcount/NGCColorPickerCell.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #define GENERAL_PREFS ROOT_PATH_NS(@"/var/mobile/Library/Preferences/com.0xkuj.notificationsgroupcountprefs.plist") 5 | 6 | @interface PSTableCell (PrivateColourPicker) 7 | - (UIViewController *)_viewControllerForAncestor; 8 | @end 9 | 10 | @interface NGCColorPickerCell : PSTableCell 11 | @property (nonatomic, retain) UILabel *headerLabel; 12 | @property (nonatomic, retain) UIView *colorPreview; 13 | @property (nonatomic, retain) UIColor *tintColour; 14 | @end -------------------------------------------------------------------------------- /notificationsgroupcount/layout/Library/PreferenceLoader/Preferences/NotificationsGroupCount.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | entry 6 | 7 | bundle 8 | NotificationsGroupCount 9 | cell 10 | PSLinkCell 11 | detail 12 | NGCRootListController 13 | icon 14 | icon.png 15 | isController 16 | 17 | label 18 | NotificationsGroupCount 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /notificationsgroupcount/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | NotificationsGroupCount 9 | CFBundleIdentifier 10 | com.0xkuj.notificationsgroupcountprefs 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 | NGCRootListController 23 | 24 | 25 | -------------------------------------------------------------------------------- /NGCBadgeView.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | typedef NS_ENUM(NSInteger, MTMaterialRecipe) { 4 | MTMaterialRecipeNone, 5 | MTMaterialRecipeNotifications, 6 | MTMaterialRecipeWidgetHosts, 7 | MTMaterialRecipeWidgets, 8 | MTMaterialRecipeControlCenterModules, 9 | MTMaterialRecipeSwitcherContinuityItem, 10 | MTMaterialRecipePreviewBackground, 11 | MTMaterialRecipeNotificationsDark, 12 | MTMaterialRecipeControlCenterModulesSheer 13 | }; 14 | 15 | @interface MTMaterialView : UIView 16 | @property (assign,nonatomic) BOOL shouldCrossfade; 17 | @property (assign, nonatomic) BOOL recipeDynamic; 18 | @property (nonatomic, assign, readwrite) NSUInteger recipe; 19 | @property (assign,nonatomic) double weighting; 20 | @property (assign,getter=isBlurEnabled,nonatomic) BOOL blurEnabled; 21 | @property (assign,getter=isZoomEnabled,nonatomic) BOOL zoomEnabled; 22 | @property (assign,getter=isCaptureOnly,nonatomic) BOOL captureOnly; 23 | @property (assign,getter=isHighlighted,nonatomic) BOOL highlighted; 24 | @property (assign,nonatomic) BOOL useBuiltInAlphaTransformerAndBackdropScaleAdjustment; 25 | @property (assign,nonatomic) BOOL useBuiltInAlphaTransformerAndBackdropScaleAdjustmentIfNecessary; 26 | +(instancetype)materialViewWithRecipeNamed:(NSString *)arg1 inBundle:(NSBundle *)arg2 configuration:(NSInteger)arg3 initialWeighting:(float)arg4 scaleAdjustment:(id)arg5; 27 | +(instancetype)materialViewWithRecipe:(NSInteger)arg1 configuration:(NSInteger)arg2; 28 | +(instancetype)materialViewWithRecipe:(NSInteger)arg1 options:(NSInteger)arg2; 29 | +(id)materialViewWithRecipeNamed:(id)arg1 ; 30 | -(void)setBlurEnabled:(BOOL)arg1 ; 31 | -(BOOL)isHighlighted; 32 | -(void)setHighlighted:(BOOL)arg1 ; 33 | + (id)materialViewWithRecipe:(long long)arg1 configuration:(long long)arg2 initialWeighting:(double)arg3 ; 34 | @end 35 | 36 | typedef NS_ENUM(NSInteger, BadgeStyle) { 37 | BadgeStyleIconColors, 38 | BadgeStyleDynamicBackgroundColor, 39 | BadgeStyleCustomColors 40 | }; 41 | 42 | @interface NGCBadgeView : UIView 43 | - (instancetype)initWithBadgeText:(NSString *)text badgeColor:(UIColor *)badgeColor textColor:(UIColor *)textColor style:(NSUInteger)style shadowOpacity:(CGFloat)shadowOpacity; 44 | - (void)setBadgeText:(NSString *)text; 45 | - (NSString *)getBadgeText; 46 | @end -------------------------------------------------------------------------------- /Tweak.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | #include "NGCBadgeView.h" 5 | 6 | #define GENERAL_PREFS ROOT_PATH_NS(@"/var/mobile/Library/Preferences/com.0xkuj.notificationsgroupcountprefs.plist") 7 | 8 | CGFloat ngcBadgeSize = 20; 9 | int badgeStyle; 10 | CGFloat shadowOpacity; 11 | BOOL isTweakEnabled, isCustomColors; 12 | UIColor *badgeBackgroundColor, *badgeTextColor; 13 | 14 | @interface SBWallpaperController 15 | + (id)sharedInstance; 16 | - (id)averageColorForVariant:(NSInteger)arg1; 17 | @end 18 | 19 | @interface NCNotificationRequest 20 | - (id)notificationIdentifier; 21 | @end 22 | 23 | @interface NCNotificationShortLookView : UIView 24 | @property (nonatomic, copy, readwrite) NSString *primaryText; 25 | @property (nonatomic, copy, readwrite) UIView *prominentIconView; 26 | @property (nonatomic, retain) NGCBadgeView *badgeView; 27 | - (id)_notificationContentView; 28 | - (BOOL)isNotificationContentViewHidden; 29 | - (CGRect)getBadgePosByFrame:(CGRect)destFrame; 30 | @end 31 | 32 | @interface NCNotificationShortLookViewController : NSObject 33 | - (id)_notificationShortLookViewIfLoaded; 34 | @end 35 | 36 | @interface CSNotificationViewController : NCNotificationShortLookViewController 37 | - (id)notificationRequest; 38 | @end 39 | 40 | // ios 15 41 | @interface NCNotificationViewController : UIViewController 42 | @end 43 | 44 | @interface NCNotificationListCell : UIView 45 | //ios 15 46 | @property (nonatomic, strong, readwrite) CSNotificationViewController *contentViewController; 47 | - (id)notificationViewController; 48 | @end 49 | 50 | // @interface NCNotificationGroupList 51 | 52 | // @end 53 | 54 | @interface NCNotificationListView : UIView 55 | @property (nonatomic, strong, readwrite) NSMutableDictionary *visibleViews; 56 | - (BOOL)isGrouped; 57 | - (NSUInteger)count; 58 | // %new 59 | - (void)updateNotificationCountBadge; 60 | - (void)deleteBadgesFromCurrentListView; 61 | - (CGRect)getBadgePosByFrame:(CGRect)destFrame; 62 | @end 63 | 64 | @interface NCNotificationGroupList 65 | @property (nonatomic, strong, readwrite) NCNotificationListView *groupListView; 66 | @property (nonatomic, strong, readwrite) NSMutableArray *orderedRequests; 67 | - (NSUInteger)notificationCount; 68 | - (NSUInteger)count; 69 | - (BOOL)isGrouped; 70 | @end 71 | 72 | // ios 15 73 | @interface NCNotificationViewControllerView 74 | - (id)contentView; 75 | @end 76 | 77 | // ios 16 78 | @interface NCDimmableView 79 | - (id)contentView; 80 | @end 81 | 82 | @interface NCNotificationSeamlessContentView : UIView 83 | @end 84 | 85 | @interface NCBadgedIconView : UIView 86 | - (CSNotificationViewController *)badgeViewController; 87 | @end 88 | -------------------------------------------------------------------------------- /NGCBadgeView.m: -------------------------------------------------------------------------------- 1 | #import "NGCBadgeView.h" 2 | 3 | CGFloat ngcBadgeSizeLowerThan10 = 20; 4 | CGFloat ngcBadgeSizeHigherThan10 = 30; 5 | 6 | @interface NCNotificationShortLookView : UIView 7 | - (BOOL)isNotificationContentViewHidden; 8 | @end 9 | 10 | @interface NGCBadgeView () 11 | @property (nonatomic, strong) UILabel *badgeLabel; 12 | @property (nonatomic, retain) MTMaterialView *blurView; 13 | @property (nonatomic, copy) NSString *badgeText; 14 | @property (nonatomic) CGRect origFrame; 15 | @end 16 | 17 | @implementation NGCBadgeView 18 | - (instancetype)initWithBadgeText:(NSString *)text badgeColor:(UIColor *)badgeColor textColor:(UIColor *)textColor style:(NSUInteger)style shadowOpacity:(CGFloat)shadowOpacity { 19 | self = [super init]; 20 | if (self) { 21 | if (style == BadgeStyleIconColors) { 22 | self.clipsToBounds = YES; 23 | self.blurView = [NSClassFromString(@"MTMaterialView") materialViewWithRecipe:6 configuration:1]; 24 | self.blurView.weighting = 1; 25 | self.blurView.recipeDynamic = YES; 26 | self.blurView.zoomEnabled = YES; 27 | [self addSubview:self.blurView]; 28 | 29 | self.blurView.translatesAutoresizingMaskIntoConstraints = NO; 30 | [self.blurView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor].active = YES; 31 | [self.blurView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor].active = YES; 32 | [self.blurView.topAnchor constraintEqualToAnchor:self.topAnchor].active = YES; 33 | [self.blurView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor].active = YES; 34 | } 35 | else 36 | self.backgroundColor = badgeColor; 37 | 38 | self.badgeLabel = [[UILabel alloc] initWithFrame:self.bounds]; 39 | self.badgeLabel.textAlignment = NSTextAlignmentCenter; 40 | self.badgeLabel.textColor = textColor == nil ? [UIColor whiteColor] : textColor; 41 | self.badgeLabel.font = [UIFont boldSystemFontOfSize:13.0]; 42 | self.badgeLabel.adjustsFontSizeToFitWidth = YES; 43 | self.badgeLabel.minimumScaleFactor = 0.5; 44 | self.badgeLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 45 | [self addSubview:self.badgeLabel]; 46 | [self setBadgeText:text]; 47 | 48 | self.layer.shadowColor = [UIColor blackColor].CGColor; 49 | self.layer.shadowOffset = CGSizeMake(0, 2); 50 | self.layer.shadowRadius = 3.0; 51 | self.layer.shadowOpacity = shadowOpacity; 52 | self.clipsToBounds = NO; 53 | } 54 | return self; 55 | } 56 | 57 | - (void)layoutSubviews { 58 | [super layoutSubviews]; 59 | 60 | if (self.blurView) 61 | self.blurView.layer.cornerRadius = self.frame.size.height / 2; 62 | else 63 | self.layer.cornerRadius = self.frame.size.height / 2; 64 | 65 | // fix ghosting badge (hopefully) 66 | if ([((NCNotificationShortLookView*)self.superview) isNotificationContentViewHidden]) { 67 | self.badgeLabel.text = @"0"; 68 | } 69 | } 70 | 71 | - (void)setBadgeText:(NSString *)text { 72 | _badgeText = [text copy]; 73 | self.badgeLabel.text = text; 74 | // Hide if text is empty or zero 75 | self.hidden = (text == nil || [text isEqualToString:@""] || [text isEqualToString:@"0"]); 76 | if ([text integerValue] > 9) { 77 | self.badgeLabel.font = [UIFont boldSystemFontOfSize:11.5]; 78 | } else { 79 | self.badgeLabel.font = [UIFont boldSystemFontOfSize:13.0]; 80 | } 81 | } 82 | 83 | - (NSString *)getBadgeText { 84 | return self.badgeLabel.text; 85 | } 86 | @end 87 | -------------------------------------------------------------------------------- /notificationsgroupcount/Resources/Root.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | items 6 | 7 | 8 | cell 9 | PSGroupCell 10 | label 11 | Tweak Activation 12 | 13 | 14 | cell 15 | PSSwitchCell 16 | default 17 | 18 | defaults 19 | com.0xkuj.notificationsgroupcountprefs 20 | key 21 | isTweakEnabled 22 | label 23 | Tweak Enabled 24 | 25 | 26 | cell 27 | PSGroupCell 28 | label 29 | BADGE STYLE 30 | 31 | 32 | cell 33 | PSSwitchCell 34 | default 35 | 36 | defaults 37 | com.0xkuj.notificationsgroupcountprefs 38 | key 39 | isCustomColors 40 | label 41 | Custom Colors 42 | nestedEntryCount 43 | 2 44 | 45 | 46 | cell 47 | PSLinkCell 48 | cellClass 49 | NGCColorPickerCell 50 | fallback 51 | FFFFFF 52 | key 53 | badgeBackgroundColor 54 | supportAlpha 55 | 56 | defaults 57 | com.0xkuj.notificationsgroupcountprefs 58 | label 59 | Badge Background Color 60 | 61 | 62 | cell 63 | PSLinkCell 64 | cellClass 65 | NGCColorPickerCell 66 | fallback 67 | FFFFFF 68 | key 69 | badgeTextColor 70 | supportAlpha 71 | 72 | defaults 73 | com.0xkuj.notificationsgroupcountprefs 74 | label 75 | Badge Text Color 76 | 77 | 78 | cell 79 | PSSegmentCell 80 | default 81 | 0 82 | defaults 83 | com.0xkuj.notificationsgroupcountprefs 84 | key 85 | badgeStyle 86 | validTitles 87 | 88 | Dynamic Icon Colors 89 | Dynamic Wallpaper Colors 90 | 91 | validValues 92 | 93 | 0 94 | 1 95 | 96 | 97 | 98 | cell 99 | PSGroupCell 100 | label 101 | BADGE SHADOW OPACITY 102 | 103 | 104 | cell 105 | PSStaticTextCell 106 | label 107 | Badge Shadow (Default: 0.8) 108 | 109 | 110 | cell 111 | PSSliderCell 112 | default 113 | 0.8 114 | min 115 | 0.0 116 | max 117 | 1.0 118 | showValue 119 | 120 | isSegmented 121 | 122 | segmentCount 123 | 10 124 | defaults 125 | com.0xkuj.notificationsgroupcountprefs 126 | key 127 | shadowOpacity 128 | 129 | 130 | cell 131 | PSGroupCell 132 | label 133 | MISCELLANEOUS 134 | footerText 135 | Restore to default settings - will restore your tweak preferences back to first-time configuration 136 | 137 | 138 | action 139 | defaultsettings: 140 | cell 141 | PSButtonCell 142 | icon 143 | respring.png 144 | label 145 | Restore to default settings 146 | 147 | 148 | action 149 | respring: 150 | cell 151 | PSButtonCell 152 | icon 153 | respring.png 154 | label 155 | Respring 156 | 157 | 158 | cell 159 | PSGroupCell 160 | label 161 | ABOUT ME 162 | 163 | 164 | action 165 | donationLink 166 | cell 167 | PSButtonCell 168 | icon 169 | donate.png 170 | label 171 | Buy me a beer ;) 172 | 173 | 174 | action 175 | openTwitter 176 | cell 177 | PSButtonCell 178 | icon 179 | Twitter.png 180 | label 181 | Follow me on Twitter 182 | 183 | 184 | cell 185 | PSGroupCell 186 | footerText 187 | Made by: 0xkuj | v1.0.5 188 | 189 | 190 | title 191 | NotificationsGroupCount 192 | 193 | 194 | -------------------------------------------------------------------------------- /notificationsgroupcount/NGCColorPickerCell.m: -------------------------------------------------------------------------------- 1 | #import "NGCColorPickerCell.h" 2 | #pragma clang diagnostic ignored "-Wunused-variable" 3 | 4 | @implementation NGCColorPickerCell 5 | 6 | - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier specifier:(PSSpecifier *)specifier { 7 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier specifier:specifier]; 8 | 9 | if (self) { 10 | 11 | self.tintColour = UIColor.systemIndigoColor; 12 | 13 | self.headerLabel = [[UILabel alloc] init]; 14 | self.headerLabel.textColor = self.tintColour; 15 | self.headerLabel.text = specifier.properties[@"title"]; 16 | self.headerLabel.font = [UIFont systemFontOfSize:17 weight:UIFontWeightRegular]; 17 | [self addSubview:self.headerLabel]; 18 | 19 | self.headerLabel.translatesAutoresizingMaskIntoConstraints = NO; 20 | [[self.headerLabel centerYAnchor] constraintEqualToAnchor:self.centerYAnchor constant:0].active = true; 21 | [self.headerLabel.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:10].active = YES; 22 | [self.headerLabel.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-10].active = YES; 23 | 24 | } 25 | 26 | return self; 27 | } 28 | 29 | 30 | - (id)target { 31 | return self; 32 | } 33 | 34 | 35 | - (id)cellTarget { 36 | return self; 37 | } 38 | 39 | 40 | - (SEL)action { 41 | return @selector(openColorPicker); 42 | } 43 | 44 | 45 | - (SEL)cellAction { 46 | return @selector(openColorPicker); 47 | } 48 | 49 | 50 | - (void)openColorPicker { 51 | UIViewController *prefsController = [self _viewControllerForAncestor]; 52 | if (@available(iOS 14.0, *)) { 53 | UIColorPickerViewController *colourPickerVC = [[UIColorPickerViewController alloc] init]; 54 | colourPickerVC.view.tintColor = self.tintColour; 55 | colourPickerVC.delegate = self; 56 | NSDictionary* dict = [NSDictionary dictionaryWithContentsOfFile:GENERAL_PREFS]; 57 | if ([dict objectForKey:self.specifier.properties[@"key"]]) { 58 | colourPickerVC.selectedColor = [self colorWithHexString:[dict objectForKey:self.specifier.properties[@"key"]]]; 59 | } else { 60 | colourPickerVC.selectedColor = [self colorWithHexString:self.specifier.properties[@"fallback"]]; 61 | } 62 | 63 | colourPickerVC.supportsAlpha = [self.specifier.properties[@"supportAlpha"] boolValue] ?: NO; 64 | [prefsController presentViewController:colourPickerVC animated:YES completion:nil]; 65 | } 66 | } 67 | 68 | - (void)updatePreview { 69 | self.colorPreview = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 29, 29)]; 70 | self.colorPreview.layer.borderWidth = 1.2; 71 | self.colorPreview.layer.borderColor = self.tintColour.CGColor; 72 | self.colorPreview.layer.cornerRadius = 14.5; 73 | NSDictionary* dict = [NSDictionary dictionaryWithContentsOfFile:GENERAL_PREFS]; 74 | if ([dict objectForKey:self.specifier.properties[@"key"]]) { 75 | self.colorPreview.backgroundColor = [self colorWithHexString:[dict objectForKey:self.specifier.properties[@"key"]]]; 76 | } else { 77 | self.colorPreview.backgroundColor = [self colorWithHexString:self.specifier.properties[@"fallback"]]; 78 | } 79 | 80 | [self setAccessoryView:self.colorPreview]; 81 | } 82 | 83 | - (void)didMoveToSuperview { 84 | [super didMoveToSuperview]; 85 | [self updatePreview]; 86 | [self.specifier setTarget:self]; 87 | [self.specifier setButtonAction:@selector(openColorPicker)]; 88 | } 89 | 90 | 91 | - (void)colorPickerViewControllerDidSelectColor:(UIColorPickerViewController *)viewController API_AVAILABLE(ios(14.0)){ 92 | 93 | UIColor *selectedColour = viewController.selectedColor; 94 | NSMutableDictionary *settings = [NSMutableDictionary dictionaryWithContentsOfFile:GENERAL_PREFS]; 95 | if (!settings) { 96 | settings = [NSMutableDictionary dictionary]; 97 | } 98 | [settings setObject:[self hexStringFromColor:selectedColour] forKey:self.specifier.properties[@"key"]]; 99 | [settings writeToFile:GENERAL_PREFS atomically:YES]; 100 | [self updatePreview]; 101 | } 102 | 103 | 104 | - (void)colorPickerViewControllerDidFinish:(UIColorPickerViewController *)viewController API_AVAILABLE(ios(14.0)){ 105 | 106 | UIColor *selectedColour = viewController.selectedColor; 107 | NSMutableDictionary *settings = [NSMutableDictionary dictionaryWithContentsOfFile:GENERAL_PREFS]; 108 | if (!settings) { 109 | settings = [NSMutableDictionary dictionary]; 110 | } 111 | [settings setObject:[self hexStringFromColor:selectedColour] forKey:self.specifier.properties[@"key"]]; 112 | [settings writeToFile:GENERAL_PREFS atomically:YES]; 113 | [self updatePreview]; 114 | } 115 | 116 | 117 | -(UIColor*)colorWithHexString:(NSString*)hex { 118 | 119 | if ([hex isEqualToString:@"red"]) { 120 | return UIColor.systemRedColor; 121 | } else if ([hex isEqualToString:@"orange"]) { 122 | return UIColor.systemOrangeColor; 123 | } else if ([hex isEqualToString:@"yellow"]) { 124 | return UIColor.systemYellowColor; 125 | } else if ([hex isEqualToString:@"green"]) { 126 | return UIColor.systemGreenColor; 127 | } else if ([hex isEqualToString:@"blue"]) { 128 | return UIColor.systemBlueColor; 129 | } else if ([hex isEqualToString:@"teal"]) { 130 | return UIColor.systemTealColor; 131 | } else if ([hex isEqualToString:@"indigo"]) { 132 | return UIColor.systemIndigoColor; 133 | } else if ([hex isEqualToString:@"purple"]) { 134 | return UIColor.systemPurpleColor; 135 | } else if ([hex isEqualToString:@"pink"]) { 136 | return UIColor.systemPinkColor; 137 | } else if ([hex isEqualToString:@"default"]) { 138 | return UIColor.labelColor; 139 | } else if ([hex isEqualToString:@"tertiary"]) { 140 | return UIColor.tertiaryLabelColor; 141 | } else { 142 | 143 | NSString *cleanString = [hex stringByReplacingOccurrencesOfString:@"#" withString:@""]; 144 | if([cleanString length] == 3) { 145 | cleanString = [NSString stringWithFormat:@"%@%@%@%@%@%@", 146 | [cleanString substringWithRange:NSMakeRange(0, 1)],[cleanString substringWithRange:NSMakeRange(0, 1)], 147 | [cleanString substringWithRange:NSMakeRange(1, 1)],[cleanString substringWithRange:NSMakeRange(1, 1)], 148 | [cleanString substringWithRange:NSMakeRange(2, 1)],[cleanString substringWithRange:NSMakeRange(2, 1)]]; 149 | } 150 | if([cleanString length] == 6) { 151 | cleanString = [cleanString stringByAppendingString:@"ff"]; 152 | } 153 | 154 | unsigned int baseValue; 155 | [[NSScanner scannerWithString:cleanString] scanHexInt:&baseValue]; 156 | 157 | float red = ((baseValue >> 24) & 0xFF)/255.0f; 158 | float green = ((baseValue >> 16) & 0xFF)/255.0f; 159 | float blue = ((baseValue >> 8) & 0xFF)/255.0f; 160 | float alpha = ((baseValue >> 0) & 0xFF)/255.0f; 161 | 162 | return [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; 163 | } 164 | } 165 | 166 | 167 | - (NSString *)hexStringFromColor:(UIColor *)color { 168 | const CGFloat *components = CGColorGetComponents(color.CGColor); 169 | 170 | CGFloat r = components[0]; 171 | CGFloat g = components[1]; 172 | CGFloat b = components[2]; 173 | CGFloat a = components[3]; 174 | 175 | return [NSString stringWithFormat:@"%02lX%02lX%02lX%02lX", lroundf(r * 255), lroundf(g * 255), lroundf(b * 255), lroundf(a * 255)]; 176 | } 177 | 178 | 179 | @end -------------------------------------------------------------------------------- /notificationsgroupcount/NGCRootListController.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import "NGCRootListController.h" 3 | #include 4 | 5 | @implementation NGCRootListController 6 | 7 | /* load all specifiers from plist file */ 8 | - (NSMutableArray*)specifiers { 9 | if (!_specifiers) { 10 | _specifiers = [self loadSpecifiersFromPlistName:@"Root" target:self]; 11 | [self applyModificationsToSpecifiers:(NSMutableArray*)_specifiers]; 12 | } 13 | 14 | return (NSMutableArray*)_specifiers; 15 | } 16 | 17 | - (void)headerCell 18 | { 19 | @autoreleasepool { 20 | UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 140)]; 21 | int width = [[UIScreen mainScreen] bounds].size.width; 22 | CGRect frame = CGRectMake(0, 20, width, 60); 23 | CGRect botFrame = CGRectMake(0, 55, width, 60); 24 | 25 | _label = [[UILabel alloc] initWithFrame:frame]; 26 | [_label setNumberOfLines:1]; 27 | _label.font = [UIFont fontWithName:@"HelveticaNeue-UltraLight" size:35]; 28 | [_label setText:@"Notifications Group Count"]; 29 | [_label setBackgroundColor:[UIColor clearColor]]; 30 | _label.textAlignment = NSTextAlignmentCenter; 31 | _label.alpha = 0; 32 | 33 | underLabel = [[UILabel alloc] initWithFrame:botFrame]; 34 | [underLabel setNumberOfLines:4]; 35 | underLabel.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:14]; 36 | [underLabel setText:@"\nCount Those Notifications Groups!\n\n Created by 0xkuj"]; 37 | [underLabel setBackgroundColor:[UIColor clearColor]]; 38 | underLabel.textColor = [UIColor grayColor]; 39 | underLabel.textAlignment = NSTextAlignmentCenter; 40 | underLabel.alpha = 0; 41 | 42 | [headerView addSubview:_label]; 43 | [headerView addSubview:underLabel]; 44 | 45 | [[self table] setTableHeaderView:headerView]; 46 | 47 | [NSTimer scheduledTimerWithTimeInterval:0.5 48 | target:self 49 | selector:@selector(increaseAlpha) 50 | userInfo:nil 51 | repeats:NO]; 52 | } 53 | } 54 | 55 | /* provides the animation */ 56 | - (void)increaseAlpha 57 | { 58 | [UIView animateWithDuration:0.5 animations:^{ 59 | _label.alpha = 1; 60 | }completion:^(BOOL finished) { 61 | [UIView animateWithDuration:0.5 animations:^{ 62 | underLabel.alpha = 1; 63 | }completion:nil]; 64 | }]; 65 | } 66 | 67 | /* what happens when the setting pane is shown */ 68 | - (void)loadView { 69 | [super loadView]; 70 | [self headerCell]; 71 | } 72 | 73 | /* read values from preferences */ 74 | - (id)readPreferenceValue:(PSSpecifier*)specifier { 75 | NSDictionary* dict = [NSDictionary dictionaryWithContentsOfFile:GENERAL_PREFS]; 76 | id obj = [dict objectForKey:[[specifier properties] objectForKey:@"key"]]; 77 | if(!obj) 78 | { 79 | obj = [[specifier properties] objectForKey:@"default"]; 80 | } 81 | return obj; 82 | } 83 | 84 | /* set the value immediately when needed */ 85 | - (void)setPreferenceValue:(id)value specifier:(PSSpecifier*)specifier { 86 | NSMutableDictionary *settings = [NSMutableDictionary dictionaryWithContentsOfFile:GENERAL_PREFS]; 87 | if (!settings) { 88 | settings = [NSMutableDictionary dictionary]; 89 | } 90 | [settings setObject:value forKey:specifier.properties[@"key"]]; 91 | [settings writeToFile:GENERAL_PREFS atomically:YES]; 92 | 93 | if(specifier.cellType == PSSwitchCell) { 94 | NSNumber* numValue = (NSNumber*)value; 95 | NSNumber* nestedEntryCount = [[specifier properties] objectForKey:@"nestedEntryCount"]; 96 | if(nestedEntryCount) { 97 | NSInteger index = [_allSpecifiers indexOfObject:specifier]; 98 | NSMutableArray* nestedEntries = [[_allSpecifiers subarrayWithRange:NSMakeRange(index + 1, [nestedEntryCount intValue])] mutableCopy]; 99 | //[self removeDisabledGroups:nestedEntries]; 100 | 101 | if([numValue boolValue]) { 102 | [self insertContiguousSpecifiers:nestedEntries afterSpecifier:specifier animated:YES]; 103 | } 104 | else { 105 | [self removeContiguousSpecifiers:nestedEntries animated:YES]; 106 | } 107 | } 108 | } 109 | } 110 | 111 | /* actually remove them when disabled */ 112 | - (void)removeDisabledGroups:(NSMutableArray*)specifiers; 113 | { 114 | for(PSSpecifier* specifier in [specifiers reverseObjectEnumerator]) 115 | { 116 | NSNumber* nestedEntryCount = [[specifier properties] objectForKey:@"nestedEntryCount"]; 117 | if(nestedEntryCount) 118 | { 119 | BOOL enabled = [[self readPreferenceValue:specifier] boolValue]; 120 | if(!enabled) 121 | { 122 | NSMutableArray* nestedEntries = [[_allSpecifiers subarrayWithRange:NSMakeRange([_allSpecifiers indexOfObject:specifier]+1, [nestedEntryCount intValue])] mutableCopy]; 123 | 124 | BOOL containsNestedEntries = NO; 125 | 126 | for(PSSpecifier* nestedEntry in nestedEntries) { 127 | NSNumber* nestedNestedEntryCount = [[nestedEntry properties] objectForKey:@"nestedEntryCount"]; 128 | if(nestedNestedEntryCount) { 129 | containsNestedEntries = YES; 130 | break; 131 | } 132 | } 133 | 134 | if(containsNestedEntries) { 135 | [self removeDisabledGroups:nestedEntries]; 136 | } 137 | 138 | [specifiers removeObjectsInArray:nestedEntries]; 139 | } 140 | } 141 | } 142 | } 143 | 144 | /* save a copy of those specifications so we can retrieve them later */ 145 | - (void)applyModificationsToSpecifiers:(NSMutableArray*)specifiers 146 | { 147 | _allSpecifiers = [specifiers copy]; 148 | [self removeDisabledGroups:specifiers]; 149 | } 150 | 151 | 152 | /* default settings and repsring right after. files to be deleted are specified in this function */ 153 | -(void)defaultsettings:(PSSpecifier*)specifier { 154 | UIAlertController* alertController = [UIAlertController alertControllerWithTitle:@"Confirmation" 155 | message:@"This will restore NotificationsGroupCount Settings to default\nAre you sure?" 156 | preferredStyle:UIAlertControllerStyleAlert]; 157 | /* prepare function for "yes" button */ 158 | UIAlertAction* OKAction = [UIAlertAction actionWithTitle:@"Yes" style:UIAlertActionStyleDefault 159 | handler:^(UIAlertAction * action) { 160 | [[NSFileManager defaultManager] removeItemAtURL: [NSURL fileURLWithPath:GENERAL_PREFS] error: nil]; 161 | [self reload]; 162 | UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Notice" 163 | message:@"Settings restored to default\nPlease respring your device" 164 | preferredStyle:UIAlertControllerStyleAlert]; 165 | UIAlertAction* DoneAction = [UIAlertAction actionWithTitle:@"Respring" style:UIAlertActionStyleDefault 166 | handler:^(UIAlertAction * action) { 167 | [self respring:nil]; 168 | }]; 169 | [alert addAction:DoneAction]; 170 | [self presentViewController:alert animated:YES completion:nil]; 171 | }]; 172 | /* prepare function for "no" button" */ 173 | UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"No" style: UIAlertActionStyleCancel handler:^(UIAlertAction * action) { return; }]; 174 | /* actually assign those actions to the buttons */ 175 | [alertController addAction:OKAction]; 176 | [alertController addAction:cancelAction]; 177 | /* present the dialog and wait for an answer */ 178 | [self presentViewController:alertController animated:YES completion:nil]; 179 | return; 180 | } 181 | 182 | - (void)respring:(id)sender { 183 | pid_t pid; 184 | const char* args[] = {"killall", "backboardd", NULL}; 185 | posix_spawn(&pid, "/var/jb/usr/bin/killall", NULL, NULL, (char* const*)args, NULL); 186 | posix_spawn(&pid, "/usr/bin/killall", NULL, NULL, (char* const*)args, NULL); 187 | } 188 | 189 | /* iOS 13 deprecated these functions */ 190 | -(void)openTwitter { 191 | UIApplication *application = [UIApplication sharedApplication]; 192 | NSURL *URL = [NSURL URLWithString:@"https://www.x.com/0xkuj"]; 193 | [application openURL:URL options:@{} completionHandler:^(BOOL success) {return;}]; 194 | } 195 | 196 | -(void)donationLink { 197 | UIApplication *application = [UIApplication sharedApplication]; 198 | NSURL *URL = [NSURL URLWithString:@"https://www.paypal.me/0xkuj"]; 199 | [application openURL:URL options:@{} completionHandler:^(BOOL success) {return;}]; 200 | } 201 | @end 202 | -------------------------------------------------------------------------------- /Tweak.xm: -------------------------------------------------------------------------------- 1 | #include "Tweak.h" 2 | 3 | @interface NSMutableDictionary (NGC) 4 | -(UIColor *)colorWithHexString:(NSString*)hex; 5 | @end 6 | 7 | @implementation NSMutableDictionary (NGC) 8 | -(UIColor *)colorWithHexString:(NSString*)hex { 9 | if ([hex isEqualToString:@"red"]) { 10 | return UIColor.systemRedColor; 11 | } else if ([hex isEqualToString:@"orange"]) { 12 | return UIColor.systemOrangeColor; 13 | } else if ([hex isEqualToString:@"yellow"]) { 14 | return UIColor.systemYellowColor; 15 | } else if ([hex isEqualToString:@"green"]) { 16 | return UIColor.systemGreenColor; 17 | } else if ([hex isEqualToString:@"blue"]) { 18 | return UIColor.systemBlueColor; 19 | } else if ([hex isEqualToString:@"teal"]) { 20 | return UIColor.systemTealColor; 21 | } else if ([hex isEqualToString:@"indigo"]) { 22 | return UIColor.systemIndigoColor; 23 | } else if ([hex isEqualToString:@"purple"]) { 24 | return UIColor.systemPurpleColor; 25 | } else if ([hex isEqualToString:@"pink"]) { 26 | return UIColor.systemPinkColor; 27 | } else if ([hex isEqualToString:@"default"]) { 28 | return UIColor.labelColor; 29 | } else if ([hex isEqualToString:@"tertiary"]) { 30 | return UIColor.tertiaryLabelColor; 31 | } else { 32 | 33 | NSString *cleanString = [hex stringByReplacingOccurrencesOfString:@"#" withString:@""]; 34 | if([cleanString length] == 3) { 35 | cleanString = [NSString stringWithFormat:@"%@%@%@%@%@%@", 36 | [cleanString substringWithRange:NSMakeRange(0, 1)],[cleanString substringWithRange:NSMakeRange(0, 1)], 37 | [cleanString substringWithRange:NSMakeRange(1, 1)],[cleanString substringWithRange:NSMakeRange(1, 1)], 38 | [cleanString substringWithRange:NSMakeRange(2, 1)],[cleanString substringWithRange:NSMakeRange(2, 1)]]; 39 | } 40 | if([cleanString length] == 6) { 41 | cleanString = [cleanString stringByAppendingString:@"ff"]; 42 | } 43 | 44 | unsigned int baseValue; 45 | [[NSScanner scannerWithString:cleanString] scanHexInt:&baseValue]; 46 | 47 | float red = ((baseValue >> 24) & 0xFF)/255.0f; 48 | float green = ((baseValue >> 16) & 0xFF)/255.0f; 49 | float blue = ((baseValue >> 8) & 0xFF)/255.0f; 50 | float alpha = ((baseValue >> 0) & 0xFF)/255.0f; 51 | 52 | return [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; 53 | } 54 | } 55 | @end 56 | 57 | static void loadPrefs() { 58 | NSMutableDictionary* mainPreferenceDict = [[NSMutableDictionary alloc] initWithContentsOfFile:GENERAL_PREFS]; 59 | isTweakEnabled = [mainPreferenceDict objectForKey:@"isTweakEnabled"] ? [[mainPreferenceDict objectForKey:@"isTweakEnabled"] boolValue] : YES; 60 | isCustomColors = [mainPreferenceDict objectForKey:@"isCustomColors"] ? [[mainPreferenceDict objectForKey:@"isCustomColors"] boolValue] : NO; 61 | shadowOpacity = [mainPreferenceDict objectForKey:@"shadowOpacity"] ? [[mainPreferenceDict objectForKey:@"shadowOpacity"] floatValue] : 0.8f; 62 | 63 | if ([mainPreferenceDict objectForKey:@"badgeBackgroundColor"] != nil) { 64 | badgeBackgroundColor = [mainPreferenceDict colorWithHexString:[mainPreferenceDict objectForKey:@"badgeBackgroundColor"]]; 65 | } else { 66 | badgeBackgroundColor = [UIColor blackColor]; 67 | } 68 | 69 | if ([mainPreferenceDict objectForKey:@"badgeTextColor"] != nil) { 70 | badgeTextColor = [mainPreferenceDict colorWithHexString:[mainPreferenceDict objectForKey:@"badgeTextColor"]]; 71 | } else { 72 | badgeTextColor = [UIColor whiteColor]; 73 | } 74 | 75 | if ([mainPreferenceDict objectForKey:@"badgeStyle"] != nil) { 76 | badgeStyle = [[mainPreferenceDict objectForKey:@"badgeStyle"] intValue]; 77 | } else { 78 | badgeStyle = 0; 79 | } 80 | } 81 | 82 | %group groupNotifications 83 | %hook NCNotificationGroupList 84 | - (void)insertNotificationRequest:(id)arg1 { 85 | %orig; 86 | [self.groupListView updateNotificationCountBadge]; 87 | } 88 | 89 | // ios 15 90 | - (void)_toggleGroupedState { 91 | %orig; 92 | [self.groupListView updateNotificationCountBadge]; 93 | } 94 | 95 | // ios 16 96 | - (void)toggleGroupedState { 97 | %orig; 98 | [self.groupListView updateNotificationCountBadge]; 99 | } 100 | 101 | //for the first notification after lockscreen is loaded 102 | - (void)_reloadNotificationViewForNotificationRequest:(id)arg1 { 103 | %orig; 104 | [self.groupListView updateNotificationCountBadge]; 105 | } 106 | 107 | // ios 15 badge misalign 108 | - (NCNotificationRequest *)leadingNotificationRequest { 109 | if (@available(iOS 15.0, *)) { 110 | [self.groupListView updateNotificationCountBadge]; 111 | } 112 | return %orig; 113 | } 114 | %end 115 | 116 | %hook NCNotificationListView 117 | 118 | - (void)layoutSubviews { 119 | %orig; 120 | [self updateNotificationCountBadge]; 121 | } 122 | 123 | - (void)_setVisibleView:(id)arg1 atIndex:(NSUInteger)arg2 { 124 | %orig; 125 | [self updateNotificationCountBadge]; 126 | } 127 | 128 | %new 129 | - (void)updateNotificationCountBadge { 130 | if ([self isGrouped] && [self count] > 1) { 131 | if (self.visibleViews.count <= 0 || ![self.visibleViews[@(0)] isKindOfClass:NSClassFromString(@"NCNotificationListCell")]) { 132 | return; 133 | } 134 | 135 | NCNotificationListCell *shownCell = self.visibleViews[@(0)]; 136 | if (![shownCell isKindOfClass:NSClassFromString(@"NCNotificationListCell")] || ![shownCell respondsToSelector:@selector(contentViewController)]) { 137 | return; 138 | } 139 | 140 | CSNotificationViewController *csnv = [shownCell contentViewController]; 141 | if (![csnv respondsToSelector:@selector(_notificationShortLookViewIfLoaded)]) { 142 | return; 143 | } 144 | NCNotificationShortLookView *shortLookView = [csnv _notificationShortLookViewIfLoaded]; 145 | NSString *numberString = [NSString stringWithFormat:@"%lu",[self count]]; 146 | [shortLookView.badgeView setBadgeText:numberString]; 147 | } else if ([self isGrouped] == NO || [self count] == 1) { 148 | [self deleteBadgesFromCurrentListView]; 149 | } 150 | } 151 | 152 | %new 153 | - (void)deleteBadgesFromCurrentListView { 154 | NSMutableDictionary *visibleViewsFromCurrentList = self.visibleViews; 155 | for (NCNotificationListCell *cell in [visibleViewsFromCurrentList allValues]) { 156 | if (![cell isKindOfClass:NSClassFromString(@"NCNotificationListCell")] || ![cell respondsToSelector:@selector(contentViewController)]) { 157 | continue; 158 | } 159 | CSNotificationViewController *csnv = [cell contentViewController]; 160 | if (![csnv respondsToSelector:@selector(_notificationShortLookViewIfLoaded)]) { 161 | continue; 162 | } 163 | 164 | NCNotificationShortLookView *shortLookView = [csnv _notificationShortLookViewIfLoaded]; 165 | [shortLookView.badgeView setBadgeText:@"0"]; 166 | } 167 | } 168 | 169 | %end 170 | 171 | %hook NCNotificationShortLookView 172 | 173 | %property (nonatomic, retain) NGCBadgeView *badgeView; 174 | 175 | -(void)_layoutNotificationContentView { 176 | %orig; 177 | if (!self.badgeView) { 178 | UIColor *badgeBackgroundColorInit = nil; 179 | UIColor *badgeTextColorInit = nil; 180 | if (isCustomColors == YES) { 181 | badgeBackgroundColorInit = badgeBackgroundColor; 182 | badgeTextColorInit = badgeTextColor; 183 | badgeStyle = BadgeStyleCustomColors; 184 | } else if (badgeStyle == BadgeStyleDynamicBackgroundColor) { 185 | badgeBackgroundColorInit = [[%c(SBWallpaperController) sharedInstance] averageColorForVariant:0]; 186 | CGFloat r, g, b, alpha; 187 | [badgeBackgroundColorInit getRed:&r green:&g blue:&b alpha:&alpha]; 188 | CGFloat brightness = (r * 0.299 + g * 0.587 + b * 0.114); 189 | badgeTextColorInit = brightness < 0.5 ? [UIColor whiteColor] : [UIColor blackColor]; 190 | } 191 | 192 | NCNotificationSeamlessContentView *nsc = [self _notificationContentView]; 193 | NCBadgedIconView *badgeIcon = MSHookIvar(nsc, "_badgedIconView"); 194 | 195 | if (badgeIcon) { 196 | self.badgeView = [[NGCBadgeView alloc] initWithBadgeText:@"0" badgeColor:badgeBackgroundColorInit textColor:badgeTextColorInit style:badgeStyle shadowOpacity:shadowOpacity]; 197 | [self addSubview:self.badgeView]; 198 | self.badgeView.translatesAutoresizingMaskIntoConstraints = NO; 199 | [self.badgeView.widthAnchor constraintEqualToConstant:ngcBadgeSize].active = YES; 200 | [self.badgeView.heightAnchor constraintEqualToConstant:ngcBadgeSize].active = YES; 201 | 202 | if (@available(iOS 16.0, *)) { 203 | [self.badgeView.trailingAnchor constraintEqualToAnchor:badgeIcon.trailingAnchor constant:5].active = YES; 204 | [self.badgeView.topAnchor constraintEqualToAnchor:badgeIcon.topAnchor constant:-8].active = YES; 205 | } else { 206 | [self.badgeView.trailingAnchor constraintEqualToAnchor:badgeIcon.trailingAnchor constant:4].active = YES; 207 | [self.badgeView.topAnchor constraintEqualToAnchor:badgeIcon.topAnchor constant:-6].active = YES; 208 | } 209 | } 210 | } 211 | } 212 | 213 | // fix ghosting badges in 0 alpha setups 214 | - (void)setNotificationContentViewHidden:(BOOL)arg1 { 215 | %orig; 216 | if (arg1 == YES) 217 | [self.badgeView setBadgeText:@"0"]; 218 | } 219 | 220 | // if we ever decide to push text.. start here 221 | // %hook NCNotificationSeamlessContentView 222 | // - (void)layoutSubviews { 223 | // %orig; 224 | // UILabel *primaryTextLabel = MSHookIvar(self, "_primaryTextLabel"); 225 | // primaryTextLabel.frame = CGRectMake(70, primaryTextLabel.frame.origin.y, primaryTextLabel.frame.size.width, primaryTextLabel.frame.size.height); 226 | // } 227 | // %end 228 | %end 229 | 230 | %end 231 | 232 | %ctor { 233 | loadPrefs(); 234 | if (isTweakEnabled) { 235 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 236 | %init(groupNotifications); 237 | }); 238 | } 239 | } 240 | --------------------------------------------------------------------------------