diff --git a/control b/control index 68dc019..c96ec87 100644 --- a/control +++ b/control @@ -1,7 +1,7 @@ Package: com.lint.undelete Name: TFDidThatSay? Depends: mobilesubstrate -Version: 1.2.4 +Version: 1.2.5 Architecture: iphoneos-arm Description: See "[deleted]" comments and posts without leaving Reddit! Maintainer: lint diff --git a/tweak/Reddit.h b/tweak/Reddit.h index f5905a0..831446e 100644 --- a/tweak/Reddit.h +++ b/tweak/Reddit.h @@ -1,3 +1,34 @@ +/* ---- Reddit v3 & v4 ---- */ + +/* -- Comment Interfaces -- */ + +@interface Comment +//v4 +@property(strong,nonatomic) id pk; +@property(strong, nonatomic) NSString *bodyText; +@property(strong, nonatomic) NSString *author; +@property(strong, nonatomic) id bodyRichTextAttributed; +@property(strong, nonatomic) id bodyAttributedText; + +//v3 +-(id)pkWithoutPrefix; +@end + +@interface CommentsViewController : NSObject +-(void) reloadCommentsWithNewCommentsHighlight:(BOOL) arg1 autoScroll:(BOOL) arg2 animated:(BOOL) arg3; +-(void) reloadCommentsSection:(BOOL) arg1; +-(void) reloadPostSection:(BOOL) arg1; +-(void) feedPostViewDidUpdatePost:(id) arg1 shouldReloadFeed:(BOOL) arg2; +-(void) updateFloatingViews; +@end + +@interface CommentActionSheetViewController : UIViewController +@property(strong,nonatomic) Comment *comment; +@property(strong,nonatomic) id commentTreeNode; +@property(strong,nonatomic) CommentsViewController *commentActionSheetDelegate; +-(id)animationControllerForDismissedController:(id) arg1; +@end + /* ---- Reddit v4 ---- */ @@ -5,98 +36,100 @@ /* -- Comment Interfaces -- */ @interface CommentTreeNode -@property(assign,nonatomic) id comment; +@property(strong,nonatomic) Comment *comment; //custom elements -@property(assign,nonatomic) id commentTreeHeaderNode; -@property(assign,nonatomic) id commentTreeCommandBarNode; +@property(strong,nonatomic) id commentTreeHeaderNode; +@property(strong,nonatomic) id commentTreeCommandBarNode; @end @interface CommentTreeDisplayNode -@property(assign,nonatomic) id commentNode; +@property(strong,nonatomic) id commentNode; @end @interface CommentTreeHeaderNode -@property(assign,nonatomic) id commentTreeNode; +@property(strong,nonatomic) id commentTreeNode; -(void) updateContentViewsForData:(id)arg1; @end @interface CommentTreeCommandBarNode -@property(assign,nonatomic) id commentTreeNode; -@property(assign,nonatomic) id delegate; -@property(assign,nonatomic) UIView* view; -@property(assign,nonatomic) id overflowButtonNode; +@property(strong,nonatomic) id commentTreeNode; +@property(strong,nonatomic) id delegate; +@property(strong,nonatomic) UIView* view; +@property(strong,nonatomic) id overflowButtonNode; @property(assign,nonatomic) CGRect frame; - -//custom elements -@property(assign,nonatomic) id activityIndicator; -@property(assign,nonatomic) id undeleteButton; @end -@interface CommentActionSheetViewController : UIViewController -@property(assign,nonatomic) id comment; -@property(assign,nonatomic) id commentTreeNode; --(id)animationControllerForDismissedController:(id) arg1; +@interface CommentTreeHeaderView +@property(strong,nonatomic) id commentTreeNode; + +-(void) updateContentViewsForData:(id) arg1; @end /* -- Post Interfaces -- */ @interface Post -@property(assign,nonatomic) id author; +@property(strong,nonatomic) NSString *author; +@property(strong,nonatomic) NSString *selfText; +@property(strong,nonatomic) id selfTextAttributed; +@property(strong,nonatomic) id selfPostRichTextAttributed; +@property(strong,nonatomic) id previewFeedPostTextString; @property(assign,nonatomic) BOOL isSelfPost; -@property(assign,nonatomic) id selfText; -@property(assign,nonatomic) id selfTextAttributed; -@property(assign,nonatomic) id selfPostRichTextAttributed; +@property(strong,nonatomic) NSString *pk; @end @interface PostDetailViewController -@property(assign,nonatomic) id selfTextNode; +@property(strong,nonatomic) id selfTextNode; -(void) configureSelfTextNode; //custom elements -@property(assign,nonatomic) id feedPostTextWithThumbnailNode; -@property(assign,nonatomic) id feedPostDetailCellNode; +@property(strong,nonatomic) id feedPostTextWithThumbnailNode; +@property(strong,nonatomic) id feedPostDetailCellNode; @end @interface PostActionSheetViewController : UIViewController -@property(assign,nonatomic) id post; -@property(assign,nonatomic) id postActionSheetDelegate; +@property(strong,nonatomic) Post *post; +@property(strong,nonatomic) id postActionSheetDelegate; @end @interface PostDetailNavigationItemHandler -@property(assign,nonatomic) id controller; -@property(assign,nonatomic) id presenter; +@property(strong,nonatomic) id controller; +@property(strong,nonatomic) id presenter; @end @interface FeedPostDetailCellNode -@property(assign,nonatomic) id textNode; -@property(assign,nonatomic) id delegate; -@property(assign,nonatomic) id contentNode; +@property(strong,nonatomic) id textNode; +@property(strong,nonatomic) id delegate; +@property(strong,nonatomic) id contentNode; +@property(strong,nonatomic) id titleNode; +@end + +@interface FeedPostTitleNode +@property(strong,nonatomic) id delegate; +-(void) configureNodes; @end @interface FeedPostDetailDelegator -@property(assign,nonatomic) id viewController; +@property(strong,nonatomic) id viewController; @end @interface FeedPostContentNode -(void) configureSelfTextNode; @end - /* -- Other Interfaces -- */ - @interface RichTextDisplayNode -@property(assign,nonatomic) id attributedText; +@property(strong,nonatomic) id attributedText; @end @interface RUIActionSheetItem : NSObject -@property(assign,nonatomic) id leftIconImage; +@property(strong,nonatomic) id leftIconImage; -(id) initWithLeftIconImage:(id) arg1 text:(id) arg2 identifier:(id) arg3 context:(id) arg4; @end @interface RUITheme -@property(assign,nonatomic) id bodyTextColor; +@property(strong,nonatomic) id bodyTextColor; @end @interface NSAttributedStringMarkdownParser @@ -108,15 +141,18 @@ @interface ThemeManager ++(id) sharedManager; + // >= 4.45.0 -@property(assign,nonatomic) id darkTheme; -@property(assign,nonatomic) id lightTheme; +@property(strong,nonatomic) id darkTheme; +@property(strong,nonatomic) id lightTheme; -(id) initWithAppSettings:(id) arg1; // < 4.45.0 -@property(assign,nonatomic) id dayTheme; -@property(assign,nonatomic) id nightTheme; +@property(strong,nonatomic) id dayTheme; +@property(strong,nonatomic) id nightTheme; -(id) initWithTraitCollection:(id) arg1 appSettings:(id) arg2; + @end @interface AppSettings @@ -148,33 +184,14 @@ @end @interface CommentCommandView -@property (nonatomic, assign) id undeleteButton; +@property (strong, nonatomic) id undeleteButton; -(id)overflowButton; -(id) comment; -(id) delegate; @end -@interface CommentsViewController --(void) reloadCommentsWithNewCommentsHighlight:(BOOL) arg1 autoScroll:(BOOL) arg2 animated:(BOOL) arg3; --(void)updateFloatingViews; -@end - /* -- Other Interfaces -- */ @interface MarkDownParser +(id)attributedStringFromMarkdownString:(id)arg1; @end - - - -/* ---- Reddit v3 & v4 ---- */ - - -@interface Comment -//v4 -@property(assign,nonatomic) id bodyRichTextAttributed; -@property(assign,nonatomic) id pk; - -//v3 --(id)pkWithoutPrefix; -@end diff --git a/tweak/Reddit.xm b/tweak/Reddit.xm index 1efb7bc..05787bd 100644 --- a/tweak/Reddit.xm +++ b/tweak/Reddit.xm @@ -1,13 +1,22 @@ #import "Reddit.h" -%group Redditv4 +%group Reddit_v4_current %hook CommentTreeNode %property(assign,nonatomic)id commentTreeHeaderNode; %property(assign,nonatomic)id commentTreeCommandBarNode; %end +%hook CommentTreeHeaderView + +-(void) layoutSubviews{ + %orig; + + [[self commentTreeNode] setCommentTreeHeaderNode:self]; +} + +%end %hook CommentTreeHeaderNode @@ -20,8 +29,6 @@ %hook CommentTreeCommandBarNode -%property(assign,nonatomic) id activityIndicator; -%property(assign,nonatomic) id undeleteButton; -(void) didLoad{ %orig; @@ -58,7 +65,7 @@ [self dismissViewControllerAnimated:YES completion:nil]; id commentTreeNode = [self commentTreeNode]; - id comment = [commentTreeNode comment]; + Comment *comment = [commentTreeNode comment]; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; NSOperationQueue *queue = [[NSOperationQueue alloc] init]; @@ -85,10 +92,11 @@ } else if (error != nil || data == nil){ body = @"[an error occured]"; } - NSArray* appVersion = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"] componentsSeparatedByString:@"."]; + NSMutableAttributedString *bodyMutableAttributedText; + id themeManager; id isNightMode; id textColor; @@ -103,7 +111,10 @@ textColor = [[themeManager lightTheme] bodyTextColor]; } - } else { + [themeManager release]; + + + } else if ([appVersion[1] integerValue] >= 37){ themeManager = [[%c(ThemeManager) alloc] initWithTraitCollection:nil appSettings:[%c(AppSettings) sharedSettings]]; isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; @@ -112,9 +123,21 @@ } else{ textColor = [[themeManager dayTheme] bodyTextColor]; } - } - - NSMutableAttributedString *bodyMutableAttributedText = [[NSMutableAttributedString alloc] initWithAttributedString:[%c(NSAttributedStringMarkdownParser) attributedStringUsingCurrentConfig:body]]; + + [themeManager release]; + + } else { + themeManager = [%c(ThemeManager) sharedManager]; + isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; + + if (isNightMode) { + textColor = [[themeManager nightTheme] bodyTextColor]; + } else{ + textColor = [[themeManager dayTheme] bodyTextColor]; + } + } + + bodyMutableAttributedText = [[NSMutableAttributedString alloc] initWithAttributedString:[%c(NSAttributedStringMarkdownParser) attributedStringUsingCurrentConfig:body]]; [bodyMutableAttributedText beginEditing]; [bodyMutableAttributedText enumerateAttribute:NSForegroundColorAttributeName inRange:NSMakeRange(0, bodyMutableAttributedText.length) options:0 usingBlock:^(id _Nullable value, NSRange range, BOOL * _Nonnull stop) { @@ -123,20 +146,17 @@ }]; [bodyMutableAttributedText endEditing]; - - [comment setValue:bodyMutableAttributedText forKey:@"bodyRichTextAttributed"]; - - [comment setValue:author forKey:@"author"]; - [comment setValue:body forKey:@"bodyText"]; - - [comment setValue:bodyMutableAttributedText forKey:@"bodyAttributedText"]; + [comment setAuthor:author]; + [comment setBodyText:body]; + [comment setBodyRichTextAttributed:bodyMutableAttributedText]; + [comment setBodyAttributedText:bodyMutableAttributedText]; - [[commentTreeNode commentTreeHeaderNode] updateContentViewsForData:comment]; + [[commentTreeNode commentTreeHeaderNode] performSelectorOnMainThread:@selector(updateContentViewsForData:) withObject:comment waitUntilDone:NO]; [request release]; [queue release]; [bodyMutableAttributedText release]; - [themeManager release]; + }]; } } @@ -144,11 +164,10 @@ %hook PostDetailViewController -%property(assign,nonatomic) id feedPostTextWithThumbnailNode; -%property(assign,nonatomic) id feedPostDetailCellNode; +%property(strong,nonatomic) id feedPostTextWithThumbnailNode; +%property(strong,nonatomic) id feedPostDetailCellNode; %end - %hook FeedPostDetailCellNode -(void) didLoad{ @@ -158,12 +177,11 @@ } %end - %hook PostActionSheetViewController -(void) setItems:(id) arg1{ - id post = [self post]; + Post *post = [self post]; if ([post isSelfPost]){ @@ -192,7 +210,7 @@ [self dismissViewControllerAnimated:YES completion:nil]; - id post = [self post]; + Post *post = [self post]; if ([post isSelfPost]){ @@ -238,7 +256,9 @@ textColor = [[themeManager lightTheme] bodyTextColor]; } - } else { + [themeManager release]; + + } else if ([appVersion[1] integerValue] >= 37){ themeManager = [[%c(ThemeManager) alloc] initWithTraitCollection:nil appSettings:[%c(AppSettings) sharedSettings]]; isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; @@ -247,7 +267,19 @@ } else{ textColor = [[themeManager dayTheme] bodyTextColor]; } - } + + [themeManager release]; + + } else { + themeManager = [%c(ThemeManager) sharedManager]; + isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; + + if (isNightMode) { + textColor = [[themeManager nightTheme] bodyTextColor]; + } else{ + textColor = [[themeManager dayTheme] bodyTextColor]; + } + } NSMutableAttributedString *bodyMutableAttributedText = [[NSMutableAttributedString alloc] initWithAttributedString:[%c(NSAttributedStringMarkdownParser) attributedStringUsingCurrentConfig:body]]; @@ -258,21 +290,23 @@ }]; [bodyMutableAttributedText endEditing]; - [post setValue:bodyMutableAttributedText forKey:@"selfPostRichTextAttributed"]; - [post setValue:bodyMutableAttributedText forKey:@"previewFeedPostTextString"]; + [post setSelfText:body]; [post setAuthor:author]; - [post setValue:body forKey:@"selfText"]; + [post setSelfPostRichTextAttributed:bodyMutableAttributedText]; + [post setPreviewFeedPostTextString:bodyMutableAttributedText]; if ([appVersion[1] integerValue] >= 44){ [[[[[self postActionSheetDelegate] controller] feedPostDetailCellNode] contentNode] configureSelfTextNode]; + } else if ([appVersion[1] integerValue] >= 38) { + [[[[self postActionSheetDelegate] controller] feedPostDetailCellNode] configureSelfTextNode]; } else { [[[[self postActionSheetDelegate] controller] feedPostDetailCellNode] configureSelfTextNode]; + [[[[[self postActionSheetDelegate] controller] feedPostDetailCellNode] titleNode] configureNodes]; } [request release]; [queue release]; [bodyMutableAttributedText release]; - [themeManager release]; }]; } } @@ -283,7 +317,179 @@ -%group Redditv3 +%group Reddit_v4_ios10 + +%hook CommentsViewController + +%new +-(void) updateComments{ + [self reloadCommentsWithNewCommentsHighlight:NO autoScroll:NO animated:NO]; +} + +%new +-(void) updatePostText{ + [self reloadPostSection:YES]; +} + +%end + +%hook CommentActionSheetViewController + +-(void) setItems:(id) arg1{ + + UIImage* origImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; + + CGSize existingImageSize = [[arg1[0] leftIconImage] size]; + CGFloat scale = origImage.size.width / existingImageSize.width; + + UIImage *newImage = [UIImage imageWithCGImage:[origImage CGImage] scale:scale orientation:origImage.imageOrientation]; + + id undeleteItem = [[%c(RUIActionSheetItem) alloc] initWithLeftIconImage:newImage text:@"TF did that say?" identifier:@"undeleteItemIdentifier" context:[self comment]]; + + %orig([arg1 arrayByAddingObject:undeleteItem]); + + [undeleteItem release]; +} + +-(void) handleDidSelectActionSheetItem:(id) arg1{ + %orig; + + if ([[arg1 identifier] isEqualToString:@"undeleteItemIdentifier"]){ + + [self dismissViewControllerAnimated:YES completion:nil]; + + Comment *comment = [self comment]; + + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; + NSOperationQueue *queue = [[NSOperationQueue alloc] init]; + + [request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://api.pushshift.io/reddit/search/comment/?ids=%@&fields=author,body",[[comment pk] componentsSeparatedByString:@"_"][1]]]]; + [request setHTTPMethod:@"GET"]; + + [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { + + NSString *author = @"[author]"; + NSString *body = @"[body]"; + + if (data != nil && error == nil){ + id jsonData = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; + if ([[jsonData objectForKey:@"data"] count] != 0){ + author = [[jsonData objectForKey:@"data"][0] objectForKey:@"author"]; + body = [[jsonData objectForKey:@"data"][0] objectForKey:@"body"]; + if ([body isEqualToString:@"[deleted]"] || [body isEqualToString:@"[removed]"]){ + body = @"[pushshift was unable to archive this]"; + } + } else { + body = @"[pushshift has not archived this yet]"; + } + } else if (error != nil || data == nil){ + body = @"[an error occured]"; + } + + NSMutableAttributedString *bodyMutableAttributedText = [[NSMutableAttributedString alloc] initWithAttributedString:[%c(NSAttributedStringMarkdownParser) attributedStringUsingCurrentConfig:body]]; + + [comment setAuthor:author]; + [comment setBodyText:body]; + [comment setBodyRichTextAttributed:bodyMutableAttributedText]; + [comment setBodyAttributedText:bodyMutableAttributedText]; + + [[self commentActionSheetDelegate] performSelectorOnMainThread:@selector(updateComments) withObject:nil waitUntilDone:NO]; + + [request release]; + [queue release]; + [bodyMutableAttributedText release]; + }]; + } +} +%end + + +%hook PostActionSheetViewController + +-(void) setItems:(id) arg1{ + + Post *post = [self post]; + + if ([post isSelfPost]){ + + UIImage* origImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; + + CGSize existingImageSize = [[arg1[0] leftIconImage] size]; + CGFloat scale = origImage.size.width / existingImageSize.width; + + UIImage *newImage = [UIImage imageWithCGImage:[origImage CGImage] scale:scale orientation:origImage.imageOrientation]; + + id undeleteItem = [[%c(RUIActionSheetItem) alloc] initWithLeftIconImage:newImage text:@"TF did that say?" identifier:@"undeleteItemIdentifier" context:[self post]]; + + arg1 = [arg1 arrayByAddingObject:undeleteItem]; + + [undeleteItem release]; + } + + %orig; +} + + +-(void) handleDidSelectActionSheetItem:(id) arg1{ + %orig; + + if ([[arg1 identifier] isEqualToString:@"undeleteItemIdentifier"]){ + + [self dismissViewControllerAnimated:YES completion:nil]; + + Post *post = [self post]; + + if ([post isSelfPost]){ + + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; + NSOperationQueue *queue = [[NSOperationQueue alloc] init]; + + [request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://api.pushshift.io/reddit/search/submission/?ids=%@&fields=author,selftext",[[post pk] componentsSeparatedByString:@"_"][1]]]]; + [request setHTTPMethod:@"GET"]; + + [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { + + NSString *author = @"[author]"; + NSString *body = @"[body]"; + + if (data != nil && error == nil){ + id jsonData = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; + if ([[jsonData objectForKey:@"data"] count] != 0){ + author = [[jsonData objectForKey:@"data"][0] objectForKey:@"author"]; + body = [[jsonData objectForKey:@"data"][0] objectForKey:@"selftext"]; + if ([body isEqualToString:@"[deleted]"] || [body isEqualToString:@"[removed]"]){ + body = @"[pushshift was unable to archive this]"; + } + } else { + body = @"[pushshift has not archived this yet]"; + } + } else if (error != nil || data == nil){ + body = @"[an error occured]"; + } + + NSMutableAttributedString *bodyMutableAttributedText = [[NSMutableAttributedString alloc] initWithAttributedString:[%c(NSAttributedStringMarkdownParser) attributedStringUsingCurrentConfig:body]]; + + [post setSelfText:body]; + [post setAuthor:author]; + [post setSelfPostRichTextAttributed:bodyMutableAttributedText]; + [post setPreviewFeedPostTextString:bodyMutableAttributedText]; + + [[self postActionSheetDelegate] performSelectorOnMainThread:@selector(updatePostText) withObject:nil waitUntilDone:NO]; + + [request release]; + [queue release]; + [bodyMutableAttributedText release]; + }]; + } + } +} +%end + +%end + + + +%group Reddit_v3 %hook CommentView @@ -325,7 +531,6 @@ [comment setValue:body forKey:@"bodyText"]; [commentsViewController reloadCommentsWithNewCommentsHighlight:NO autoScroll:NO animated:NO]; - } @@ -359,7 +564,6 @@ UIButton *button = [self undeleteButton]; button.frame = CGRectMake([[self overflowButton ] frame].origin.x - 32, 0, 32, 32); - } %end @@ -371,14 +575,17 @@ %ctor{ NSString* processName = [[NSProcessInfo processInfo] processName]; - NSString* version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; - NSArray* versionArray = [version componentsSeparatedByString:@"."]; + NSArray* appVersion = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"] componentsSeparatedByString:@"."]; if ([processName isEqualToString:@"Reddit"]){ - if ([versionArray[0] isEqualToString:@"4"]){ - %init(Redditv4); - } else if ([versionArray[0] isEqualToString:@"3"]) { - %init(Redditv3); + if ([appVersion[0] isEqualToString:@"4"]){ + if ([appVersion[1] integerValue] <= 32){ + %init(Reddit_v4_ios10); + } else{ + %init(Reddit_v4_current); + } + } else if ([appVersion[0] isEqualToString:@"3"]) { + %init(Reddit_v3); } } }