From 3693f3e93a017c2dabff5d0e14c4659fd9ebb7fc Mon Sep 17 00:00:00 2001 From: faroukbmiled Date: Fri, 10 Apr 2026 09:43:41 +0100 Subject: [PATCH] feat: Replace Domain in Instagram urls feat: Remove user param from copied links feat: Open links in External Browser feat: Strip Instagram tracking from browser links fix: Confirm reel refresh confirmation appears on app launch #2 --- README.md | 4 + src/Features/General/EmbedLinks.xm | 99 +++++++++++++++ src/Features/General/OpenInBrowser.x | 69 +++++++++++ src/Features/Reels/ReelsPlayback.xm | 47 ++++--- src/Settings/SCIEmbedDomainViewController.h | 4 + src/Settings/SCIEmbedDomainViewController.m | 130 ++++++++++++++++++++ src/Settings/SCISettingsBackup.m | 1 + src/Settings/TweakSettings.m | 47 ++++++- src/Tweak.x | 5 + 9 files changed, 388 insertions(+), 18 deletions(-) create mode 100644 src/Features/General/EmbedLinks.xm create mode 100644 src/Features/General/OpenInBrowser.x create mode 100644 src/Settings/SCIEmbedDomainViewController.h create mode 100644 src/Settings/SCIEmbedDomainViewController.m diff --git a/README.md b/README.md index ad29474..871a9a0 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,10 @@ A feature-rich iOS tweak for Instagram, forked from [SCInsta](https://github.com - Copy comment text from long-press menu **\*** - Download GIF comments **\*** - Profile copy button **\*** +- Replace domain in shared links — rewrite copied/shared links for embeds in Discord, Telegram, etc. with preset or custom domains **\*** +- Strip tracking params from shared links (igsh, utm) **\*** +- Open links in external browser **\*** +- Strip tracking from browser links **\*** - Do not save recent searches - Use detailed (native) color picker - Enable liquid glass buttons diff --git a/src/Features/General/EmbedLinks.xm b/src/Features/General/EmbedLinks.xm new file mode 100644 index 0000000..ae33d5a --- /dev/null +++ b/src/Features/General/EmbedLinks.xm @@ -0,0 +1,99 @@ +// Rewrite Instagram share links — replace domain + optionally strip tracking params. +// Waits for IG's async clipboard write via changeCount, then rewrites once. + +#import "../../Utils.h" +#import +#import +#import + +static NSString *sciRewriteIGURL(NSString *url) { + if (!url.length) return url; + + // Domain replacement + if ([SCIUtils getBoolPref:@"embed_links"]) { + NSString *domain = [SCIUtils getStringPref:@"embed_link_domain"]; + if (!domain.length) domain = @"kkinstagram.com"; + if (![url containsString:domain]) { + NSArray *igDomains = @[@"www.instagram.com", @"instagram.com", @"www.instagr.am", @"instagr.am"]; + for (NSString *d in igDomains) { + NSRange r = [url rangeOfString:d]; + if (r.location != NSNotFound) { + NSString *target = [d hasPrefix:@"www."] + ? [NSString stringWithFormat:@"www.%@", domain] : domain; + url = [url stringByReplacingCharactersInRange:r withString:target]; + break; + } + } + } + } + + // Strip tracking params + if ([SCIUtils getBoolPref:@"strip_tracking_params"]) { + NSURLComponents *comps = [NSURLComponents componentsWithString:url]; + if (comps.queryItems.count) { + NSArray *strip = @[@"igsh", @"ig_rid", @"utm_source", @"utm_medium", @"utm_campaign"]; + NSMutableArray *clean = [NSMutableArray array]; + for (NSURLQueryItem *q in comps.queryItems) { + if (![strip containsObject:q.name]) [clean addObject:q]; + } + comps.queryItems = clean.count ? clean : nil; + NSString *result = comps.string; + if (result) url = result; + } + } + + return url; +} + +static BOOL sciShouldRewrite(void) { + return [SCIUtils getBoolPref:@"embed_links"] || [SCIUtils getBoolPref:@"strip_tracking_params"]; +} + +// Rewrite clipboard once after IG writes +static void sciPollAndRewrite(NSInteger countBefore, int polls, double interval) { + __block BOOL done = NO; + for (int i = 0; i < polls; i++) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((interval + i * interval) * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + if (done) return; + if ([UIPasteboard generalPasteboard].changeCount == countBefore) return; + NSString *clip = [UIPasteboard generalPasteboard].string; + if (!clip || ![clip containsString:@"instagram"]) return; + NSString *rewritten = sciRewriteIGURL(clip); + if (![rewritten isEqualToString:clip]) { + [UIPasteboard generalPasteboard].string = rewritten; + done = YES; + } else { + done = YES; + } + }); + } +} + +// ============ Hooks ============ + +static void (*orig_copyLink)(id, SEL, id); +static void new_copyLink(id self, SEL _cmd, id vc) { + if (!sciShouldRewrite()) { orig_copyLink(self, _cmd, vc); return; } + NSInteger countBefore = [UIPasteboard generalPasteboard].changeCount; + orig_copyLink(self, _cmd, vc); + sciPollAndRewrite(countBefore, 30, 0.05); +} + +static void (*orig_shareMore)(id, SEL, id); +static void new_shareMore(id self, SEL _cmd, id vc) { + if (!sciShouldRewrite()) { orig_shareMore(self, _cmd, vc); return; } + NSInteger countBefore = [UIPasteboard generalPasteboard].changeCount; + orig_shareMore(self, _cmd, vc); + sciPollAndRewrite(countBefore, 120, 0.1); +} + +__attribute__((constructor)) static void _embedLinksInit(void) { + Class cls = NSClassFromString(@"IGExternalShareOptionsViewController"); + if (!cls) return; + SEL copy = NSSelectorFromString(@"_shareToClipboardFromVC:"); + if (class_getInstanceMethod(cls, copy)) + MSHookMessageEx(cls, copy, (IMP)new_copyLink, (IMP *)&orig_copyLink); + SEL more = NSSelectorFromString(@"_shareToMoreFromVC:"); + if (class_getInstanceMethod(cls, more)) + MSHookMessageEx(cls, more, (IMP)new_shareMore, (IMP *)&orig_shareMore); +} diff --git a/src/Features/General/OpenInBrowser.x b/src/Features/General/OpenInBrowser.x new file mode 100644 index 0000000..206ff8c --- /dev/null +++ b/src/Features/General/OpenInBrowser.x @@ -0,0 +1,69 @@ +// Open links in external browser + strip IG tracking from URLs +#import "../../Utils.h" +#import +#import + +// Extract the real URL from l.instagram.com redirects and strip tracking params +static NSURL *sciCleanBrowserURL(NSURL *url) { + if (![SCIUtils getBoolPref:@"strip_browser_tracking"]) return url; + if (!url) return url; + + NSString *urlStr = url.absoluteString; + + // Unwrap l.instagram.com/?u=ENCODED_URL&e=TRACKING redirects + if ([url.host isEqualToString:@"l.instagram.com"]) { + NSURLComponents *comps = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; + for (NSURLQueryItem *q in comps.queryItems) { + if ([q.name isEqualToString:@"u"] && q.value.length) { + NSString *decoded = [q.value stringByRemovingPercentEncoding]; + if (decoded) urlStr = decoded; + break; + } + } + } + + // Strip common tracking params from the destination URL + NSURLComponents *comps = [NSURLComponents componentsWithString:urlStr]; + if (comps.queryItems.count) { + NSSet *trackingParams = [NSSet setWithArray:@[ + @"utm_source", @"utm_medium", @"utm_campaign", @"utm_content", + @"utm_term", @"utm_id", @"fbclid", @"igshid", @"igsh", + @"ig_rid", @"campaign_id", @"ad_id", @"aem" + ]]; + NSMutableArray *clean = [NSMutableArray array]; + for (NSURLQueryItem *q in comps.queryItems) { + if (![trackingParams containsObject:q.name]) [clean addObject:q]; + } + comps.queryItems = clean.count ? clean : nil; + } + + NSURL *result = comps.URL; + return result ?: url; +} + +%hook IGBrowserNavigationController +- (void)viewWillAppear:(BOOL)animated { + id session = ((id(*)(id,SEL))objc_msgSend)(self, @selector(browserSession)); + Ivar urlIvar = session ? class_getInstanceVariable([session class], "_urlRequest") : nil; + NSURLRequest *req = urlIvar ? object_getIvar(session, urlIvar) : nil; + NSURL *url = req.URL; + + if (url && [SCIUtils getBoolPref:@"open_links_external"]) { + NSURL *cleaned = sciCleanBrowserURL(url); + [[UIApplication sharedApplication] openURL:cleaned options:@{} completionHandler:nil]; + [(UIViewController *)self dismissViewControllerAnimated:NO completion:nil]; + return; + } + + // For in-app browser: replace the URL request with the cleaned version + if (url && [SCIUtils getBoolPref:@"strip_browser_tracking"]) { + NSURL *cleaned = sciCleanBrowserURL(url); + if (![cleaned isEqual:url]) { + NSURLRequest *cleanReq = [NSURLRequest requestWithURL:cleaned]; + object_setIvar(session, urlIvar, cleanReq); + } + } + + %orig; +} +%end diff --git a/src/Features/Reels/ReelsPlayback.xm b/src/Features/Reels/ReelsPlayback.xm index 76df5e1..9e33bfc 100644 --- a/src/Features/Reels/ReelsPlayback.xm +++ b/src/Features/Reels/ReelsPlayback.xm @@ -28,27 +28,46 @@ } %end +static BOOL sciReelRefreshInFlight = NO; + %hook IGSundialFeedViewController - (void)_refreshReelsWithParamsForNetworkRequest:(NSInteger)arg1 userDidPullToRefresh:(BOOL)arg2 { if ([SCIUtils getBoolPref:@"prevent_doom_scrolling"]) { - IGRefreshControl *_refreshControl = MSHookIvar(self, "_refreshControl"); - [self refreshControlDidEndFinishLoadingAnimation:_refreshControl]; - + IGRefreshControl *rc = MSHookIvar(self, "_refreshControl"); + [self refreshControlDidEndFinishLoadingAnimation:rc]; return; } - if ([SCIUtils getBoolPref:@"refresh_reel_confirm"]) { - NSLog(@"[SCInsta] Reel refresh triggered"); - - [SCIUtils showConfirmation:^(void) { %orig(arg1, arg2); } - cancelHandler:^(void) { - IGRefreshControl *_refreshControl = MSHookIvar(self, "_refreshControl"); - [self refreshControlDidEndFinishLoadingAnimation:_refreshControl]; - } - title:@"Refresh Reels"]; - } else { - return %orig(arg1, arg2); + if (![(UIViewController *)self isViewLoaded] || sciReelRefreshInFlight || ![SCIUtils getBoolPref:@"refresh_reel_confirm"]) { + %orig(arg1, arg2); + return; } + + // Reset the refresh control state so pull-to-refresh can trigger again + IGRefreshControl *rc = MSHookIvar(self, "_refreshControl"); + Ivar stateIvar = class_getInstanceVariable([rc class], "_refreshState"); + if (stateIvar) { + ptrdiff_t off = ivar_getOffset(stateIvar); + *(NSInteger *)((char *)(__bridge void *)rc + off) = 0; + } + if ([rc respondsToSelector:@selector(endRefreshing)]) + ((void(*)(id,SEL))objc_msgSend)(rc, @selector(endRefreshing)); + [self refreshControlDidEndFinishLoadingAnimation:rc]; + + UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Refresh Reels?" + message:nil + preferredStyle:UIAlertControllerStyleAlert]; + __weak id weakSelf = self; + [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + [alert addAction:[UIAlertAction actionWithTitle:@"Refresh" style:UIAlertActionStyleDefault handler:^(UIAlertAction *_) { + sciReelRefreshInFlight = YES; + SEL rSel = @selector(_refreshReelsWithParamsForNetworkRequest:userDidPullToRefresh:); + ((void(*)(id,SEL,NSInteger,BOOL))objc_msgSend)(weakSelf, rSel, arg1, arg2); + sciReelRefreshInFlight = NO; + }]]; + + UIViewController *presenter = (UIViewController *)self; + [presenter presentViewController:alert animated:YES completion:nil]; } %end diff --git a/src/Settings/SCIEmbedDomainViewController.h b/src/Settings/SCIEmbedDomainViewController.h new file mode 100644 index 0000000..4737746 --- /dev/null +++ b/src/Settings/SCIEmbedDomainViewController.h @@ -0,0 +1,4 @@ +#import + +@interface SCIEmbedDomainViewController : UIViewController +@end diff --git a/src/Settings/SCIEmbedDomainViewController.m b/src/Settings/SCIEmbedDomainViewController.m new file mode 100644 index 0000000..080c1b7 --- /dev/null +++ b/src/Settings/SCIEmbedDomainViewController.m @@ -0,0 +1,130 @@ +#import "SCIEmbedDomainViewController.h" +#import "../Utils.h" + +#define SCI_CUSTOM_DOMAINS_KEY @"embed_custom_domains" + +static NSArray *sciPresetDomains(void) { + return @[@"kkinstagram.com", @"ddinstagram.com", @"d.ddinstagram.com", @"g.ddinstagram.com"]; +} + +@interface SCIEmbedDomainViewController () +@property (nonatomic, strong) UITableView *tableView; +@property (nonatomic, copy) NSArray *customDomains; +@end + +@implementation SCIEmbedDomainViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + self.title = @"Embed domain"; + 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; + [self.view addSubview:self.tableView]; + [NSLayoutConstraint activateConstraints:@[ + [self.tableView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor], + [self.tableView.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor], + [self.tableView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], + [self.tableView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], + ]]; + + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addCustom)]; + + [self reload]; +} + +- (void)reload { + NSArray *stored = [[NSUserDefaults standardUserDefaults] arrayForKey:SCI_CUSTOM_DOMAINS_KEY]; + self.customDomains = stored ?: @[]; + [self.tableView reloadData]; +} + +- (void)addCustom { + UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Add custom domain" + message:nil + preferredStyle:UIAlertControllerStyleAlert]; + [alert addTextFieldWithConfigurationHandler:^(UITextField *tf) { + tf.placeholder = @"example.com"; + tf.autocapitalizationType = UITextAutocapitalizationTypeNone; + tf.autocorrectionType = UITextAutocorrectionTypeNo; + tf.keyboardType = UIKeyboardTypeURL; + }]; + [alert addAction:[UIAlertAction actionWithTitle:@"Add" style:UIAlertActionStyleDefault handler:^(UIAlertAction *_) { + NSString *domain = alert.textFields.firstObject.text; + domain = [domain stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + domain = [domain stringByReplacingOccurrencesOfString:@"https://" withString:@""]; + domain = [domain stringByReplacingOccurrencesOfString:@"http://" withString:@""]; + while ([domain hasSuffix:@"/"]) domain = [domain substringToIndex:domain.length - 1]; + if (!domain.length || ![domain containsString:@"."]) return; + NSMutableArray *all = [self.customDomains mutableCopy]; + if (![all containsObject:domain]) [all addObject:domain]; + [[NSUserDefaults standardUserDefaults] setObject:all forKey:SCI_CUSTOM_DOMAINS_KEY]; + [[NSUserDefaults standardUserDefaults] setObject:domain forKey:@"embed_link_domain"]; + [self reload]; + }]]; + [alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + [self presentViewController:alert animated:YES completion:nil]; +} + +#pragma mark - Table + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tv { return 2; } + +- (NSString *)tableView:(UITableView *)tv titleForHeaderInSection:(NSInteger)section { + return section == 0 ? @"Presets" : @"Custom"; +} + +- (NSInteger)tableView:(UITableView *)tv numberOfRowsInSection:(NSInteger)section { + return section == 0 ? (NSInteger)sciPresetDomains().count : (NSInteger)self.customDomains.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:@"cell"]; + if (!cell) cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"]; + NSString *domain = indexPath.section == 0 + ? sciPresetDomains()[indexPath.row] + : self.customDomains[indexPath.row]; + cell.textLabel.text = domain; + NSString *current = [SCIUtils getStringPref:@"embed_link_domain"]; + if (!current.length) current = @"kkinstagram.com"; + cell.accessoryType = [domain isEqualToString:current] ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; + return cell; +} + +- (void)tableView:(UITableView *)tv didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tv deselectRowAtIndexPath:indexPath animated:YES]; + NSString *domain = indexPath.section == 0 + ? sciPresetDomains()[indexPath.row] + : self.customDomains[indexPath.row]; + [[NSUserDefaults standardUserDefaults] setObject:domain forKey:@"embed_link_domain"]; + [tv reloadData]; +} + +- (UISwipeActionsConfiguration *)tableView:(UITableView *)tv trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath { + if (indexPath.section == 0) return nil; + NSString *domain = self.customDomains[indexPath.row]; + UIContextualAction *del = [UIContextualAction + contextualActionWithStyle:UIContextualActionStyleDestructive title:@"Delete" + handler:^(UIContextualAction *_, UIView *__, void (^cb)(BOOL)) { + NSMutableArray *all = [self.customDomains mutableCopy]; + [all removeObject:domain]; + [[NSUserDefaults standardUserDefaults] setObject:all forKey:SCI_CUSTOM_DOMAINS_KEY]; + // Reset to default if deleted domain was selected + NSString *current = [SCIUtils getStringPref:@"embed_link_domain"]; + if ([current isEqualToString:domain]) + [[NSUserDefaults standardUserDefaults] setObject:@"kkinstagram.com" forKey:@"embed_link_domain"]; + [self reload]; + cb(YES); + }]; + return [UISwipeActionsConfiguration configurationWithActions:@[del]]; +} + +- (BOOL)tableView:(UITableView *)tv canEditRowAtIndexPath:(NSIndexPath *)indexPath { + return indexPath.section == 1; +} + +@end diff --git a/src/Settings/SCISettingsBackup.m b/src/Settings/SCISettingsBackup.m index a236847..6c5e7fc 100644 --- a/src/Settings/SCISettingsBackup.m +++ b/src/Settings/SCISettingsBackup.m @@ -405,6 +405,7 @@ typedef NS_ENUM(NSInteger, SCIBackupPreviewRowKind) { return @[ @"excluded_threads", @"excluded_story_users", + @"embed_custom_domains", ]; } diff --git a/src/Settings/TweakSettings.m b/src/Settings/TweakSettings.m index 7000a98..cc840a2 100644 --- a/src/Settings/TweakSettings.m +++ b/src/Settings/TweakSettings.m @@ -4,6 +4,7 @@ #import "../Features/StoriesAndMessages/SCIExcludedThreads.h" #import "../Features/StoriesAndMessages/SCIExcludedStoryUsers.h" #import "SCIExcludedStoryUsersViewController.h" +#import "SCIEmbedDomainViewController.h" @implementation SCITweakSettings @@ -37,13 +38,42 @@ @"rows": @[ [SCISetting switchCellWithTitle:@"Hide ads" subtitle:@"Removes all ads from the Instagram app" defaultsKey:@"hide_ads"], [SCISetting switchCellWithTitle:@"Hide Meta AI" subtitle:@"Hides the meta ai buttons/functionality within the app" defaultsKey:@"hide_meta_ai"], + [SCISetting switchCellWithTitle:@"Do not save recent searches" subtitle:@"Search bars will no longer save your recent searches" defaultsKey:@"no_recent_searches"], [SCISetting switchCellWithTitle:@"Copy description" subtitle:@"Copy description text fields by long-pressing on them" defaultsKey:@"copy_description"], [SCISetting switchCellWithTitle:@"Profile copy button" subtitle:@"Adds a button next to the burger menu on profiles to copy username, name or bio" defaultsKey:@"profile_copy_button"], - [SCISetting switchCellWithTitle:@"Do not save recent searches" subtitle:@"Search bars will no longer save your recent searches" defaultsKey:@"no_recent_searches"], [SCISetting switchCellWithTitle:@"Use detailed color picker" subtitle:@"Long press on the eyedropper tool in stories to customize the text color more precisely" defaultsKey:@"detailed_color_picker"], - [SCISetting switchCellWithTitle:@"Enable liquid glass buttons" subtitle:@"Enables experimental liquid glass buttons within the app" defaultsKey:@"liquid_glass_buttons" requiresRestart:YES], - [SCISetting switchCellWithTitle:@"Enable liquid glass surfaces" subtitle:@"Enables liquid glass for other elements, such as menus" defaultsKey:@"liquid_glass_surfaces" requiresRestart:YES], - [SCISetting switchCellWithTitle:@"Enable teen app icons" subtitle:@"When enabled, hold down on the Instagram logo to change the app icon" defaultsKey:@"teen_app_icons" requiresRestart:YES] + ] + }, + @{ + @"header": @"Browser", + @"rows": @[ + [SCISetting switchCellWithTitle:@"Open links in external browser" subtitle:@"Opens links in Safari instead of Instagram's in-app browser" defaultsKey:@"open_links_external"], + [SCISetting switchCellWithTitle:@"Strip tracking from links" subtitle:@"Removes Instagram tracking wrappers (l.instagram.com) and UTM/fbclid params from URLs" defaultsKey:@"strip_browser_tracking"], + ] + }, + @{ + @"header": @"Sharing", + @"rows": @[ + [SCISetting switchCellWithTitle:@"Replace domain in shared links" subtitle:@"Rewrites copied/shared links to use an embed-friendly domain for previews in Discord, Telegram, etc." defaultsKey:@"embed_links"], + ({ + SCISetting *s = [SCISetting buttonCellWithTitle:@"Embed domain" + subtitle:@"" + icon:[SCISymbol symbolWithName:@"globe"] + action:^(void) { + UIWindow *win = nil; + for (UIWindow *w in [UIApplication sharedApplication].windows) + if (w.isKeyWindow) { win = w; break; } + UIViewController *top = win.rootViewController; + while (top.presentedViewController) top = top.presentedViewController; + if ([top isKindOfClass:[UINavigationController class]]) + [(UINavigationController *)top pushViewController:[SCIEmbedDomainViewController new] animated:YES]; + else if (top.navigationController) + [top.navigationController pushViewController:[SCIEmbedDomainViewController new] animated:YES]; + }]; + s.dynamicTitle = ^{ return [NSString stringWithFormat:@"Embed domain: %@", [SCIUtils getStringPref:@"embed_link_domain"] ?: @"kkinstagram.com"]; }; + s; + }), + [SCISetting switchCellWithTitle:@"Strip tracking params" subtitle:@"Removes igsh, utm_source, and other tracking parameters from shared links" defaultsKey:@"strip_tracking_params"], ] }, @{ @@ -70,6 +100,15 @@ [SCISetting switchCellWithTitle:@"Hide explore posts grid" subtitle:@"Hides the grid of suggested posts on the explore/search tab" defaultsKey:@"hide_explore_grid"], [SCISetting switchCellWithTitle:@"Hide trending searches" subtitle:@"Hides the trending searches under the explore search bar" defaultsKey:@"hide_trending_searches"], ] + }, + @{ + @"header": @"Experimental features", + @"footer": @"These features rely on hidden Instagram flags and may not work on all accounts or versions.", + @"rows": @[ + [SCISetting switchCellWithTitle:@"Enable liquid glass buttons" subtitle:@"Enables experimental liquid glass buttons" defaultsKey:@"liquid_glass_buttons" requiresRestart:YES], + [SCISetting switchCellWithTitle:@"Enable liquid glass surfaces" subtitle:@"Enables liquid glass for other elements" defaultsKey:@"liquid_glass_surfaces" requiresRestart:YES], + [SCISetting switchCellWithTitle:@"Enable teen app icons" subtitle:@"Hold down on the Instagram logo to change the app icon" defaultsKey:@"teen_app_icons" requiresRestart:YES] + ] }] ], [SCISetting navigationCellWithTitle:@"Feed" diff --git a/src/Tweak.x b/src/Tweak.x index 34685c5..f2872d1 100644 --- a/src/Tweak.x +++ b/src/Tweak.x @@ -68,6 +68,11 @@ BOOL dmVisualMsgsViewedButtonEnabled = false; @"story_seen_mode": @"button", @"story_audio_toggle": @(NO), @"settings_pause_playback": @(YES), + @"embed_links": @(NO), + @"embed_link_domain": @"kkinstagram.com", + @"strip_tracking_params": @(NO), + @"open_links_external": @(NO), + @"strip_browser_tracking": @(NO), @"hide_feed_repost": @(NO), @"copy_comment": @(YES), @"download_gif_comment": @(YES)