diff --git a/README.md b/README.md index 73b11eb..c2d771d 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/src/Downloader/Download.m b/src/Downloader/Download.m index c452333..26917dd 100644 --- a/src/Downloader/Download.m +++ b/src/Downloader/Download.m @@ -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]; + }); } }); } diff --git a/src/Features/General/CommentActions.xm b/src/Features/General/CommentActions.xm new file mode 100644 index 0000000..410f4fd --- /dev/null +++ b/src/Features/General/CommentActions.xm @@ -0,0 +1,102 @@ +// Copy comment text + download GIF from comment long-press menu +#import "../../Utils.h" +#import "../../Downloader/Download.h" +#import +#import +#import + +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 origIdent = [config valueForKey:@"identifier"]; + UIContextMenuContentPreviewProvider origPreview = [config valueForKey:@"previewProvider"]; + + UIContextMenuActionProvider wrapped = ^UIMenu *(NSArray *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); +} diff --git a/src/Settings/TweakSettings.m b/src/Settings/TweakSettings.m index 5b0ad77..ef44583 100644 --- a/src/Settings/TweakSettings.m +++ b/src/Settings/TweakSettings.m @@ -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": @[ diff --git a/src/Tweak.x b/src/Tweak.x index 5f404bc..a2041ff 100644 --- a/src/Tweak.x +++ b/src/Tweak.x @@ -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];