#import "AppIconOptionsController.h" #import static NSString *const kPrefDomain = @"com.arichornlover.uYouEnhanced"; static NSString *const kPrefEnableIconOverride = @"appIconCustomization_enabled"; static NSString *const kPrefIconName = @"customAppIcon_name"; static NSString *const kPrefNotifyName = @"com.arichornlover.uYouEnhanced.prefschanged"; static NSString *BundlePath(void) { NSString *path = [[NSBundle mainBundle] pathForResource:@"uYouPlus" ofType:@"bundle"]; if (path) return path; return @"/Library/Application Support/uYouEnhanced"; } @interface AppIconOptionsController () @property (strong, nonatomic) UITableView *tableView; @property (strong, nonatomic) NSArray *appIcons; @property (assign, nonatomic) NSInteger selectedIconIndex; @end @implementation UIImage (CustomImages) + (UIImage *)customBackButtonImage { NSBundle *bundle = [NSBundle bundleWithPath:BundlePath()]; return [UIImage imageNamed:@"Back.png" inBundle:bundle compatibleWithTraitCollection:nil]; } @end @implementation AppIconOptionsController - (void)viewDidLoad { [super viewDidLoad]; self.title = @"Change App Icon"; self.selectedIconIndex = -1; self.view.backgroundColor = [UIColor systemBackgroundColor]; self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleInsetGrouped]; self.tableView.dataSource = self; self.tableView.delegate = self; self.tableView.translatesAutoresizingMaskIntoConstraints = NO; if (@available(iOS 15.0, *)) { self.tableView.sectionHeaderTopPadding = 0; } [self.view addSubview:self.tableView]; [NSLayoutConstraint activateConstraints:@[ [self.tableView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor], [self.tableView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor], [self.tableView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], [self.tableView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor] ]]; self.navigationItem.hidesBackButton = YES; if (@available(iOS 14.0, *)) { self.navigationItem.backButtonDisplayMode = UINavigationItemBackButtonDisplayModeMinimal; } self.backButton = [UIButton buttonWithType:UIButtonTypeSystem]; [self.backButton setImage:[UIImage customBackButtonImage] forState:UIControlStateNormal]; [self.backButton addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside]; UIBarButtonItem *customBackButton = [[UIBarButtonItem alloc] initWithCustomView:self.backButton]; self.navigationItem.leftBarButtonItem = customBackButton; NSMutableSet *iconNames = [NSMutableSet set]; NSFileManager *fm = [NSFileManager defaultManager]; NSString *bundlePath = BundlePath(); NSBundle *bundle = [NSBundle bundleWithPath:bundlePath]; if (bundle) { NSString *appIconsDir = [bundle.bundlePath stringByAppendingPathComponent:@"AppIcons"]; BOOL isDir = NO; if ([fm fileExistsAtPath:appIconsDir isDirectory:&isDir] && isDir) { NSArray *contents = [fm contentsOfDirectoryAtPath:appIconsDir error:nil] ?: @[]; for (NSString *entry in contents) { NSString *full = [appIconsDir stringByAppendingPathComponent:entry]; BOOL entryIsDir = NO; if ([fm fileExistsAtPath:full isDirectory:&entryIsDir]) { if (entryIsDir) { [iconNames addObject:entry]; } else { NSString *ext = entry.pathExtension.lowercaseString; if ([ext isEqualToString:@"png"]) { NSString *name = [entry stringByDeletingPathExtension]; if (name.length > 0) { [iconNames addObject:name]; } } } } } } } NSString *supportBase = @"/Library/Application Support/uYouEnhanced/AppIcons"; BOOL supportIsDir = NO; if ([fm fileExistsAtPath:supportBase isDirectory:&supportIsDir] && supportIsDir) { NSArray *contents = [fm contentsOfDirectoryAtPath:supportBase error:nil] ?: @[]; for (NSString *entry in contents) { NSString *full = [supportBase stringByAppendingPathComponent:entry]; BOOL isDir = NO; if ([fm fileExistsAtPath:full isDirectory:&isDir]) { if (isDir) { [iconNames addObject:entry]; } else { NSString *ext = entry.pathExtension.lowercaseString; if ([ext isEqualToString:@"png"]) { NSString *name = [entry stringByDeletingPathExtension]; if (name.length > 0) { [iconNames addObject:name]; } } } } } } self.appIcons = [[iconNames allObjects] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; NSDictionary *prefs = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"/var/mobile/Library/Preferences/%@.plist", kPrefDomain]] ?: @{}; NSString *savedIcon = prefs[kPrefIconName]; if (savedIcon) { NSInteger idx = [self.appIcons indexOfObject:savedIcon]; if (idx != NSNotFound) self.selectedIconIndex = idx; } if (self.appIcons.count == 0) { UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectInset(self.view.bounds, 20, 20)]; lbl.text = @"No custom icons found. Place PNGs or icon folders in uYouPlus.bundle/AppIcons/ or /Library/Application Support/uYouEnhanced/AppIcons/"; lbl.numberOfLines = 0; lbl.textAlignment = NSTextAlignmentCenter; lbl.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self.view addSubview:lbl]; } } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.appIcons.count + 1; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 80.0; } - (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellId = @"AppIconCell"; UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:CellId]; if (!cell) cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellId]; if (indexPath.row == 0) { cell.textLabel.text = @"Reset to default"; cell.detailTextLabel.text = @"Restore the original app icon"; cell.imageView.image = nil; cell.accessoryType = (self.selectedIconIndex == -1) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; return cell; } NSString *iconName = self.appIcons[indexPath.row - 1]; cell.textLabel.text = iconName; cell.detailTextLabel.text = @"Tap to apply this icon"; UIImage *preview = nil; NSArray *candidates = @[ @"AppIcon60x60@3x.png", @"AppIcon60x60@2x.png", @"Icon@3x.png", @"Icon@2x.png", @"Icon.png" ]; NSString *bundlePath = BundlePath(); NSBundle *bundle = [NSBundle bundleWithPath:bundlePath]; NSString *supportBase = @"/Library/Application Support/uYouEnhanced/AppIcons"; NSFileManager *fm = [NSFileManager defaultManager]; BOOL found = NO; if (bundle) { NSString *dir = [bundle.bundlePath stringByAppendingPathComponent:[NSString stringWithFormat:@"AppIcons/%@", iconName]]; BOOL isDir = NO; if ([fm fileExistsAtPath:dir isDirectory:&isDir] && isDir) { for (NSString *c in candidates) { NSString *imagePath = [dir stringByAppendingPathComponent:c]; if ([fm fileExistsAtPath:imagePath]) { preview = [UIImage imageWithContentsOfFile:imagePath]; found = YES; break; } } if (!found) { NSArray *files = [fm contentsOfDirectoryAtPath:dir error:nil]; for (NSString *file in files) { NSString *ext = file.pathExtension.lowercaseString; if ([ext isEqualToString:@"png"]) { NSString *path = [dir stringByAppendingPathComponent:file]; preview = [UIImage imageWithContentsOfFile:path]; found = YES; break; } } } } else { NSString *pngPath = [[bundle.bundlePath stringByAppendingPathComponent:@"AppIcons"] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png", iconName]]; if ([fm fileExistsAtPath:pngPath]) { preview = [UIImage imageWithContentsOfFile:pngPath]; found = YES; } } } if (!found) { NSString *dir = [supportBase stringByAppendingPathComponent:iconName]; BOOL isDir = NO; if ([fm fileExistsAtPath:dir isDirectory:&isDir] && isDir) { for (NSString *c in candidates) { NSString *imagePath = [dir stringByAppendingPathComponent:c]; if ([fm fileExistsAtPath:imagePath]) { preview = [UIImage imageWithContentsOfFile:imagePath]; found = YES; break; } } if (!found) { NSArray *files = [fm contentsOfDirectoryAtPath:dir error:nil]; for (NSString *file in files) { NSString *ext = file.pathExtension.lowercaseString; if ([ext isEqualToString:@"png"]) { NSString *path = [dir stringByAppendingPathComponent:file]; preview = [UIImage imageWithContentsOfFile:path]; found = YES; break; } } } } else { NSString *pngPath = [supportBase stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png", iconName]]; if ([fm fileExistsAtPath:pngPath]) { preview = [UIImage imageWithContentsOfFile:pngPath]; found = YES; } } } cell.imageView.image = preview; cell.imageView.layer.cornerRadius = 12.0; cell.imageView.clipsToBounds = YES; cell.imageView.contentMode = UIViewContentModeScaleAspectFit; cell.accessoryType = ((indexPath.row - 1) == self.selectedIconIndex) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; return cell; } - (void)tableView:(UITableView *)tv didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tv deselectRowAtIndexPath:indexPath animated:YES]; NSString *prefsPath = [NSString stringWithFormat:@"/var/mobile/Library/Preferences/%@.plist", kPrefDomain]; NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:prefsPath] ?: [NSMutableDictionary dictionary]; if (indexPath.row == 0) { self.selectedIconIndex = -1; prefs[kPrefEnableIconOverride] = @NO; [prefs writeToFile:prefsPath atomically:YES]; notify_post([kPrefNotifyName UTF8String]); [self.tableView reloadData]; [self showAlertWithTitle:@"Requested" message:@"Icon reset requested."]; return; } self.selectedIconIndex = indexPath.row - 1; NSString *iconName = self.appIcons[self.selectedIconIndex]; prefs[kPrefEnableIconOverride] = @YES; prefs[kPrefIconName] = iconName; BOOL ok = [prefs writeToFile:prefsPath atomically:YES]; if (!ok) { [self showAlertWithTitle:@"Error" message:@"Failed to save preference"]; return; } notify_post([kPrefNotifyName UTF8String]); [self.tableView reloadData]; [self showAlertWithTitle:@"Requested" message:@"Icon change requested."]; } - (void)showAlertWithTitle:(NSString *)title message:(NSString *)message { UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]; [alert addAction:ok]; [self presentViewController:alert animated:YES completion:nil]; } - (void)back { [self.navigationController popViewControllerAnimated:YES]; } @end