modded scinsta with additional features and fixes for recent instagram version

This commit is contained in:
faroukbmiled
2026-03-28 23:57:15 +01:00
commit 3d133ac333
105 changed files with 11916 additions and 0 deletions
+356
View File
@@ -0,0 +1,356 @@
#import "SCISettingsViewController.h"
static char rowStaticRef[] = "row";
@interface SCISettingsViewController () <UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, copy) NSArray *sections;
@property (nonatomic) BOOL reduceMargin;
@end
///
@implementation SCISettingsViewController
- (instancetype)initWithTitle:(NSString *)title sections:(NSArray *)sections reduceMargin:(BOOL)reduceMargin {
self = [super init];
if (self) {
self.title = title;
self.reduceMargin = reduceMargin;
// Exclude development cells from release builds
NSMutableArray *mutableSections = [sections mutableCopy];
[mutableSections enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSDictionary *section, NSUInteger index, BOOL *stop) {
if ([section[@"header"] hasPrefix:@"_"] && [section[@"footer"] hasPrefix:@"_"]) {
if (![[SCIUtils IGVersionString] isEqualToString:@"0.0.0"]) {
[mutableSections removeObjectAtIndex:index];
}
}
else if ([section[@"header"] isEqualToString:@"Experimental"]) {
if (![[SCIUtils IGVersionString] hasSuffix:@"-dev"]) {
[mutableSections removeObjectAtIndex:index];
}
}
}];
self.sections = [mutableSections copy];
}
return self;
}
- (instancetype)init {
return [self initWithTitle:[SCITweakSettings title] sections:[SCITweakSettings sections] reduceMargin:YES];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationController.navigationBar.prefersLargeTitles = NO;
self.view.backgroundColor = UIColor.systemBackgroundColor;
self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleInsetGrouped];
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.tableView.dataSource = self;
self.tableView.contentInset = UIEdgeInsetsMake(self.reduceMargin ? -30 : -10, 0, 0, 0);
self.tableView.delegate = self;
[self.view addSubview:self.tableView];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if (![[[NSUserDefaults standardUserDefaults] objectForKey:@"SCInstaFirstRun"] isEqualToString:SCIVersionString]) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"SCInsta Settings Info"
message:@"In the future: Hold down on the three lines at the top right of your profile page, to re-open SCInsta settings."
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"I understand!"
style:UIAlertActionStyleDefault
handler:nil]];
UIViewController *presenter = self.presentingViewController;
[presenter presentViewController:alert animated:YES completion:nil];
// Done with first-time setup for this version
[[NSUserDefaults standardUserDefaults] setValue:SCIVersionString forKey:@"SCInstaFirstRun"];
}
}
// MARK: - UITableViewDataSource
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
SCISetting *row = self.sections[indexPath.section][@"rows"][indexPath.row];
if (!row) return nil;
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
UIListContentConfiguration *cellContentConfig = cell.defaultContentConfiguration;
cellContentConfig.text = row.title;
// Subtitle
if (row.subtitle.length) {
cellContentConfig.secondaryText = row.subtitle;
cellContentConfig.textToSecondaryTextVerticalPadding = 4.5;
}
// Icon
if (row.icon != nil) {
cellContentConfig.image = [row.icon image];
cellContentConfig.imageProperties.tintColor = row.icon.color;
}
// Image url
if (row.imageUrl != nil) {
[self loadImageFromURL:row.imageUrl atIndexPath:indexPath forTableView:tableView];
cellContentConfig.imageToTextPadding = 14;
}
switch (row.type) {
case SCITableCellStatic: {
cell.selectionStyle = UITableViewCellSelectionStyleNone;
break;
}
case SCITableCellLink: {
cellContentConfig.textProperties.color = [UIColor systemBlueColor];
cellContentConfig.textProperties.font = [UIFont systemFontOfSize:[UIFont preferredFontForTextStyle:UIFontTextStyleBody].pointSize
weight:UIFontWeightMedium];
cell.selectionStyle = UITableViewCellSelectionStyleDefault;
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage systemImageNamed:@"safari"]];
imageView.tintColor = [UIColor systemGray3Color];
cell.accessoryView = imageView;
break;
}
case SCITableCellSwitch: {
UISwitch *toggle = [UISwitch new];
toggle.on = [[NSUserDefaults standardUserDefaults] boolForKey:row.defaultsKey];
toggle.onTintColor = [SCIUtils SCIColor_Primary];
objc_setAssociatedObject(toggle, rowStaticRef, row, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[toggle addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
cell.accessoryView = toggle;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
break;
}
case SCITableCellStepper: {
UIStepper *stepper = [UIStepper new];
stepper.minimumValue = row.min;
stepper.maximumValue = row.max;
stepper.stepValue = row.step;
stepper.value = [[NSUserDefaults standardUserDefaults] doubleForKey:row.defaultsKey];
objc_setAssociatedObject(stepper, rowStaticRef, row, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[stepper addTarget:self
action:@selector(stepperChanged:)
forControlEvents:UIControlEventValueChanged];
// Template subtitle
if (row.subtitle.length) {
cellContentConfig.secondaryText = [self formatString:row.subtitle withValue:stepper.value label:row.label singularLabel:row.singularLabel];
}
cell.accessoryView = stepper;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
break;
}
case SCITableCellButton: {
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
break;
}
case SCITableCellMenu: {
UIButton *menuButton = [UIButton buttonWithType:UIButtonTypeSystem];
[menuButton setTitle:@"•••" forState:UIControlStateNormal];
menuButton.menu = [row menuForButton:menuButton];
menuButton.showsMenuAsPrimaryAction = YES;
menuButton.titleLabel.font = [UIFont systemFontOfSize:[UIFont preferredFontForTextStyle:UIFontTextStyleBody].pointSize
weight:UIFontWeightMedium];
UIButtonConfiguration *config = menuButton.configuration ?: [UIButtonConfiguration plainButtonConfiguration];
menuButton.configuration.contentInsets = NSDirectionalEdgeInsetsMake(8, 8, 8, 8);
menuButton.configuration = config;
[menuButton sizeToFit];
cell.accessoryView = menuButton;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
break;
}
case SCITableCellNavigation: {
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
break;
}
}
cell.contentConfiguration = cellContentConfig;
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.sections[section][@"rows"] count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return self.sections[section][@"header"];
}
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
return self.sections[section][@"footer"];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.sections.count;
}
// MARK: - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
SCISetting *row = self.sections[indexPath.section][@"rows"][indexPath.row];
if (!row) return;
if (row.type == SCITableCellLink) {
[[UIApplication sharedApplication] openURL:row.url options:@{} completionHandler:nil];
}
else if (row.type == SCITableCellButton) {
if (row.action != nil) {
row.action();
}
}
else if (row.type == SCITableCellNavigation) {
if (row.navSections.count > 0) {
UIViewController *vc = [[SCISettingsViewController alloc] initWithTitle:row.title sections:row.navSections reduceMargin:NO];
vc.title = row.title;
[self.navigationController pushViewController:vc animated:YES];
}
else if (row.navViewController) {
[self.navigationController pushViewController:row.navViewController animated:YES];
}
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
// MARK: - Actions
- (void)switchChanged:(UISwitch *)sender {
SCISetting *row = objc_getAssociatedObject(sender, rowStaticRef);
[[NSUserDefaults standardUserDefaults] setBool:sender.isOn forKey:row.defaultsKey];
NSLog(@"Switch changed: %@", sender.isOn ? @"ON" : @"OFF");
if (row.requiresRestart) {
[SCIUtils showRestartConfirmation];
}
}
- (void)stepperChanged:(UIStepper *)sender {
SCISetting *row = objc_getAssociatedObject(sender, rowStaticRef);
[[NSUserDefaults standardUserDefaults] setDouble:sender.value forKey:row.defaultsKey];
NSLog(@"Stepper changed: %f", sender.value);
[self reloadCellForView:sender];
}
- (void)menuChanged:(UICommand *)command {
NSDictionary *properties = command.propertyList;
[[NSUserDefaults standardUserDefaults] setValue:properties[@"value"] forKey:properties[@"defaultsKey"]];
NSLog(@"Menu changed: %@", command.propertyList[@"value"]);
[self reloadCellForView:command.sender animated:YES];
if (properties[@"requiresRestart"]) {
[SCIUtils showRestartConfirmation];
}
}
// MARK: - Helper
- (NSString *)formatString:(NSString *)template withValue:(double)value label:(NSString *)label singularLabel:(NSString *)singularLabel {
// Singular or plural labels
NSString *applicableLabel = fabs(value - 1.0) < 0.00001 ? singularLabel : label;
// Force value to 0 to prevent it being -0
if (fabs(value) < 0.00001) {
value = 0.0;
}
// Get correct decimal value based on step value
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterDecimalStyle;
formatter.minimumFractionDigits = 0;
formatter.maximumFractionDigits = [SCIUtils decimalPlacesInDouble:value];
NSString *stringValue = [formatter stringFromNumber:@(value)];
return [NSString stringWithFormat:template, stringValue, applicableLabel];
}
- (void)reloadCellForView:(UIView *)view animated:(BOOL)animated {
UITableViewCell *cell = (UITableViewCell *)view.superview;
while (cell && ![cell isKindOfClass:[UITableViewCell class]]) {
cell = (UITableViewCell *)cell.superview;
}
if (!cell) return;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
if (!indexPath) return;
[self.tableView reloadRowsAtIndexPaths:@[indexPath]
withRowAnimation:animated ? UITableViewRowAnimationAutomatic : UITableViewRowAnimationNone];
}
- (void)reloadCellForView:(UIView *)view {
[self reloadCellForView:view animated:NO];
}
- (void)loadImageFromURL:(NSURL *)url atIndexPath:(NSIndexPath *)indexPath forTableView:(UITableView *)tableView
{
if (!url) return;
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
if (!data || error) return;
UIImage *image = [UIImage imageWithData:data];
if (!image) return;
dispatch_async(dispatch_get_main_queue(), ^{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (!cell) return;
UIListContentConfiguration *config = (UIListContentConfiguration *)cell.contentConfiguration;
config.image = image;
config.imageProperties.maximumSize = CGSizeMake(45, 45);
cell.contentConfiguration = config;
});
}];
[task resume];
}
@end