feat: Add ability to download highlight cover images from the profile page via long press menu

This commit is contained in:
faroukbmiled
2026-04-10 16:06:25 +01:00
parent 06b2626714
commit d17fba5778
4 changed files with 124 additions and 1 deletions
+1
View File
@@ -79,6 +79,7 @@ A feature-rich iOS tweak for Instagram, forked from [SCInsta](https://github.com
- Save profile picture
- Download buttons on media — tap a button directly on feed posts, reels sidebar, and story overlay **\***
- Download method — choose between download button or long-press gesture **\***
- Download highlight cover from profile long-press menu **\***
- Save action — choose between share sheet or save directly to Photos **\***
- Save to RyukGram album — optional toggle that routes downloads (and share-sheet "Save to Photos" picks) into a dedicated "RyukGram" album in Photos **\***
- Download confirmation — optional confirmation dialog before downloading **\***
@@ -0,0 +1,120 @@
// Download highlight cover image from the profile long-press menu.
// Captures the long-pressed IGStoryTrayCell, finds the IGImageView inside it,
// and saves the cover using the user's download settings.
#import "../../Utils.h"
#import "../../Downloader/Download.h"
#import <objc/runtime.h>
#import <objc/message.h>
#import <substrate.h>
static SCIDownloadDelegate *sciHighlightDl = nil;
// Find the IGStoryTrayCell with an active long-press gesture
static UIView *sciFindLongPressedCell(UIView *root) {
Class cellCls = NSClassFromString(@"IGStoryTrayCell");
if (!cellCls) return nil;
NSMutableArray *stack = [NSMutableArray arrayWithObject:root];
while (stack.count) {
UIView *v = stack.lastObject; [stack removeLastObject];
if ([v isKindOfClass:cellCls]) {
for (UIGestureRecognizer *gr in v.gestureRecognizers) {
if ([gr isKindOfClass:[UILongPressGestureRecognizer class]] &&
(gr.state == UIGestureRecognizerStateBegan || gr.state == UIGestureRecognizerStateChanged))
return v;
}
}
for (UIView *sub in v.subviews) [stack addObject:sub];
}
return nil;
}
// Find the IGImageView inside a specific cell
static UIImage *sciCoverImageFromCell(UIView *cell) {
if (!cell) return nil;
Class igImageView = NSClassFromString(@"IGImageView");
if (!igImageView) igImageView = [UIImageView class];
NSMutableArray *stack = [NSMutableArray arrayWithObject:cell];
while (stack.count) {
UIView *v = stack.lastObject; [stack removeLastObject];
if ([v isKindOfClass:igImageView] && [v isKindOfClass:[UIImageView class]]) {
UIImage *img = [(UIImageView *)v image];
if (img && img.size.width > 10) return img;
}
for (UIView *sub in v.subviews) [stack addObject:sub];
}
return nil;
}
static void sciSaveCoverImage(UIImage *image, UIViewController *presenter) {
if (!image) {
[SCIUtils showErrorHUDWithDescription:@"Could not find cover image"];
return;
}
NSString *method = [SCIUtils getStringPref:@"dw_save_action"];
if ([method isEqualToString:@"photos"]) {
// Save to Photos (respects RyukGram album pref)
NSData *data = UIImageJPEGRepresentation(image, 1.0);
if (!data) return;
NSString *tmpPath = [NSTemporaryDirectory() stringByAppendingPathComponent:
[NSString stringWithFormat:@"%@.jpg", [[NSUUID UUID] UUIDString]]];
[data writeToFile:tmpPath atomically:YES];
NSURL *tmpURL = [NSURL fileURLWithPath:tmpPath];
sciHighlightDl = [[SCIDownloadDelegate alloc] initWithAction:saveToPhotos showProgress:NO];
[sciHighlightDl downloadDidFinishWithFileURL:tmpURL];
} else {
// Share sheet
UIActivityViewController *activityVC = [[UIActivityViewController alloc]
initWithActivityItems:@[image] applicationActivities:nil];
if (presenter) [presenter presentViewController:activityVC animated:YES completion:nil];
}
}
// Stored reference to the long-pressed cell (captured at presentation time)
static __weak UIView *sciLongPressedHighlightCell = nil;
static void (*orig_present)(id, SEL, id, BOOL, id);
static void new_present(id self, SEL _cmd, id vc, BOOL animated, id completion) {
if ([SCIUtils getBoolPref:@"download_highlight_cover"] &&
[NSStringFromClass([vc class]) containsString:@"ActionSheet"] &&
[NSStringFromClass([self class]) containsString:@"Profile"]) {
// Capture the long-pressed cell NOW while the gesture is still active
UIView *cell = sciFindLongPressedCell([(UIViewController *)self view]);
sciLongPressedHighlightCell = cell;
if (cell) {
Ivar actIvar = class_getInstanceVariable([vc class], "_actions");
NSArray *actions = actIvar ? object_getIvar(vc, actIvar) : nil;
if (actions && actions.count >= 2 && actions.count <= 6) {
Class actionCls = NSClassFromString(@"IGActionSheetControllerAction");
if (actionCls) {
__weak UIViewController *weakSelf = (UIViewController *)self;
void (^handler)(void) = ^{
UIImage *cover = sciCoverImageFromCell(sciLongPressedHighlightCell);
sciSaveCoverImage(cover, weakSelf);
};
SEL initSel = @selector(initWithTitle:subtitle:style:handler:accessibilityIdentifier:accessibilityLabel:);
typedef id (*InitFn)(id, SEL, id, id, NSInteger, id, id, id);
id newAction = ((InitFn)objc_msgSend)([actionCls alloc], initSel,
@"Download cover", nil, 0, handler, nil, nil);
if (newAction) {
NSMutableArray *newActions = [actions mutableCopy];
[newActions addObject:newAction];
object_setIvar(vc, actIvar, [newActions copy]);
}
}
}
}
}
orig_present(self, _cmd, vc, animated, completion);
}
__attribute__((constructor)) static void _highlightInit(void) {
MSHookMessageEx([UIViewController class], @selector(presentViewController:animated:completion:),
(IMP)new_present, (IMP *)&orig_present);
}
+2 -1
View File
@@ -166,7 +166,8 @@
[SCISetting switchCellWithTitle:@"Download feed posts" subtitle:@"Long-press with finger(s) to download posts in the home tab" defaultsKey:@"dw_feed_posts"],
[SCISetting switchCellWithTitle:@"Download reels" subtitle:@"Long-press with finger(s) on a reel to download" defaultsKey:@"dw_reels"],
[SCISetting switchCellWithTitle:@"Download stories" subtitle:@"Long-press with finger(s) while viewing someone's story to download" defaultsKey:@"dw_story"],
[SCISetting switchCellWithTitle:@"Save profile picture" subtitle:@"On someone's profile, click their profile picture to enlarge it, then hold to download" defaultsKey:@"save_profile"]
[SCISetting switchCellWithTitle:@"Save profile picture" subtitle:@"On someone's profile, click their profile picture to enlarge it, then hold to download" defaultsKey:@"save_profile"],
[SCISetting switchCellWithTitle:@"Download highlight cover" subtitle:@"Adds a download option to the highlight long-press menu on profiles" defaultsKey:@"download_highlight_cover"]
]
},
@{
+1
View File
@@ -74,6 +74,7 @@ BOOL dmVisualMsgsViewedButtonEnabled = false;
@"embed_links": @(NO),
@"embed_link_domain": @"kkinstagram.com",
@"strip_tracking_params": @(NO),
@"download_highlight_cover": @(YES),
@"open_links_external": @(NO),
@"strip_browser_tracking": @(NO),
@"hide_feed_repost": @(NO),