feat: Copy comment text from long-press menu

feat: Download GIF comments
This commit is contained in:
faroukbmiled
2026-04-10 02:48:50 +01:00
parent 89c5a25512
commit d8a8b6c0fe
5 changed files with 121 additions and 3 deletions
+2
View File
@@ -22,6 +22,8 @@ A feature-rich iOS tweak for Instagram, forked from [SCInsta](https://github.com
- Hide ads
- Hide Meta AI
- Copy description
- Copy comment text from long-press menu **\***
- Download GIF comments **\***
- Profile copy button **\***
- Do not save recent searches
- Use detailed (native) color picker
+7 -2
View File
@@ -187,9 +187,14 @@
if (error && error.code != NSURLErrorCancelled) {
NSLog(@"[SCInsta] Download: Download failed with error: \"%@\"", error);
[self.pill setText:@"Download failed"];
self.pill.subtitleLabel.text = nil;
self.pill.subtitleLabel.text = error.localizedDescription;
self.pill.progressRing.hidden = YES;
[self.pill dismissAfterDelay:2.0];
[self.pill dismissAfterDelay:3.0];
} else if (!error) {
// nil error without fileURL callback — dismiss stale pill
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (self.pill.superview) [self.pill dismissAfterDelay:0];
});
}
});
}
+102
View File
@@ -0,0 +1,102 @@
// Copy comment text + download GIF from comment long-press menu
#import "../../Utils.h"
#import "../../Downloader/Download.h"
#import <objc/runtime.h>
#import <objc/message.h>
#import <substrate.h>
static SCIDownloadDelegate *sciGifDl = nil;
static DownloadAction sciGifDownloadAction(void) {
NSString *method = [SCIUtils getStringPref:@"dw_save_action"];
return [method isEqualToString:@"photos"] ? saveToPhotos : share;
}
static id (*orig_commentCtxMenu)(id, SEL, id, id, CGPoint);
static id new_commentCtxMenu(id self, SEL _cmd, id cv, id indexPath, CGPoint point) {
UIContextMenuConfiguration *config = orig_commentCtxMenu(self, _cmd, cv, indexPath, point);
if (!config) return config;
Ivar commentIvar = class_getInstanceVariable([self class], "_longPressedComment");
id comment = commentIvar ? object_getIvar(self, commentIvar) : nil;
if (!comment) return config;
NSString *text = nil;
@try { text = ((id(*)(id,SEL))objc_msgSend)(comment, @selector(text)); } @catch (__unused id e) {}
NSString *gifId = nil;
@try {
SEL sel = NSSelectorFromString(@"gifMediaId");
if ([comment respondsToSelector:sel])
gifId = ((id(*)(id,SEL))objc_msgSend)(comment, sel);
} @catch (__unused id e) {}
NSString *gifURL = nil;
if (gifId.length) {
Ivar attIvar = class_getInstanceVariable([comment class], "_commentAttachment");
id att = attIvar ? object_getIvar(comment, attIvar) : nil;
if (att) {
Ivar urlIvar = class_getInstanceVariable([att class], "_image_imageURL");
if (urlIvar) {
id url = object_getIvar(att, urlIvar);
if ([url isKindOfClass:[NSString class]]) gifURL = url;
else if ([url isKindOfClass:[NSURL class]]) gifURL = [(NSURL *)url absoluteString];
}
}
}
BOOL hasText = text.length > 0;
BOOL hasGif = gifURL.length > 0;
if (!hasText && !hasGif) return config;
id origProvider = [config valueForKey:@"actionProvider"];
id<NSCopying> origIdent = [config valueForKey:@"identifier"];
UIContextMenuContentPreviewProvider origPreview = [config valueForKey:@"previewProvider"];
UIContextMenuActionProvider wrapped = ^UIMenu *(NSArray<UIMenuElement *> *suggested) {
UIMenu *base = origProvider ? ((UIMenu *(^)(NSArray *))origProvider)(suggested)
: [UIMenu menuWithChildren:suggested];
NSMutableArray *extra = [NSMutableArray array];
if (hasText && [SCIUtils getBoolPref:@"copy_comment"]) {
[extra addObject:[UIAction actionWithTitle:@"Copy"
image:[UIImage systemImageNamed:@"doc.on.doc"]
identifier:nil
handler:^(__kindof UIAction *_) {
[UIPasteboard generalPasteboard].string = text;
}]];
}
if (hasGif && [SCIUtils getBoolPref:@"download_gif_comment"]) {
[extra addObject:[UIAction actionWithTitle:@"Download GIF"
image:[UIImage systemImageNamed:@"arrow.down.circle"]
identifier:nil
handler:^(__kindof UIAction *_) {
NSURL *url = [NSURL URLWithString:gifURL];
if (!url) return;
sciGifDl = [[SCIDownloadDelegate alloc] initWithAction:sciGifDownloadAction() showProgress:YES];
[sciGifDl downloadFileWithURL:url fileExtension:@"gif" hudLabel:nil];
}]];
}
if (!extra.count) return base;
NSMutableArray *kids = [base.children mutableCopy] ?: [NSMutableArray array];
NSUInteger insertIdx = kids.count > 0 ? kids.count - 1 : 0;
UIMenu *ourMenu = [UIMenu menuWithTitle:@"" image:nil identifier:nil
options:UIMenuOptionsDisplayInline children:extra];
[kids insertObject:ourMenu atIndex:insertIdx];
return [base menuByReplacingChildren:kids];
};
return [UIContextMenuConfiguration configurationWithIdentifier:origIdent
previewProvider:origPreview
actionProvider:wrapped];
}
__attribute__((constructor)) static void _commentActionsInit(void) {
Class cls = NSClassFromString(@"IGCommentThreadViewController");
if (!cls) return;
SEL s = @selector(collectionView:contextMenuConfigurationForItemAtIndexPath:point:);
if (class_getInstanceMethod(cls, s))
MSHookMessageEx(cls, s, (IMP)new_commentCtxMenu, (IMP *)&orig_commentCtxMenu);
}
+7
View File
@@ -46,6 +46,13 @@
[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": @"Comments",
@"rows": @[
[SCISetting switchCellWithTitle:@"Copy comment text" subtitle:@"Adds a copy option to the comment long-press menu" defaultsKey:@"copy_comment"],
[SCISetting switchCellWithTitle:@"Download GIF comments" subtitle:@"Adds a download option for GIF comments" defaultsKey:@"download_gif_comment"],
]
},
@{
@"header": @"Notes",
@"rows": @[
+3 -1
View File
@@ -67,7 +67,9 @@ BOOL dmVisualMsgsViewedButtonEnabled = false;
@"story_excluded_show_unexclude_eye": @(YES),
@"story_seen_mode": @"button",
@"story_audio_toggle": @(NO),
@"settings_pause_playback": @(YES)
@"settings_pause_playback": @(YES),
@"copy_comment": @(YES),
@"download_gif_comment": @(YES)
};
[[NSUserDefaults standardUserDefaults] registerDefaults:sciDefaults];