diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4a235ab --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +ARCHS = arm64 arm64e + +include $(THEOS)/makefiles/common.mk + +TWEAK_NAME = tfdidthatsay +tfdidthatsay_FILES = Tweak.xm +#tfdidthatsay_CFLAGS = -fobjc-arc + +include $(THEOS_MAKE_PATH)/tweak.mk + +after-install:: + install.exec "killall -9 Reddit" diff --git a/Tweak.h b/Tweak.h new file mode 100644 index 0000000..a9a10b7 --- /dev/null +++ b/Tweak.h @@ -0,0 +1,125 @@ + + +/* -- Comment Interfaces -- */ + + +@interface Comment +@property(assign,nonatomic) id bodyRichTextAttributed; +@property(assign,nonatomic) id pk; +@end + +@interface CommentTreeNode +@property(assign,nonatomic) id comment; + +//custom elements +@property(assign,nonatomic) id commentTreeHeaderNode; +@property(assign,nonatomic) id commentTreeCommandBarNode; +@property(assign,nonatomic) BOOL isLoadingArchivedComment; +@end + +@interface CommentTreeDisplayNode +@property(assign,nonatomic) id commentNode; +@end + +@interface CommentTreeHeaderNode +@property(assign,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(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; +@end + + +/* -- Post Interfaces -- */ + + +@interface Post +@property(assign,nonatomic) id author; +@property(assign,nonatomic) BOOL isSelfPost; +@property(assign,nonatomic) id selfText; +@property(assign,nonatomic) id selfTextAttributed; +@property(assign,nonatomic) id selfPostRichTextAttributed; +@end + +@interface PostDetailViewController +@property(assign,nonatomic) id selfTextNode; +-(void) configureSelfTextNode; + +//custom elements +@property(assign,nonatomic) id feedPostTextWithThumbnailNode; +@property(assign,nonatomic) id feedPostDetailCellNode; +@end + +@interface PostActionSheetViewController : UIViewController +@property(assign,nonatomic) id post; +@property(assign,nonatomic) id postActionSheetDelegate; +@end + +@interface PostDetailNavigationItemHandler +@property(assign,nonatomic) id controller; +@property(assign,nonatomic) id presenter; +@end + +@interface FeedPostDetailCellNode +@property(assign,nonatomic) id textNode; +@property(assign,nonatomic) id delegate; +@end + +@interface FeedPostDetailDelegator +@property(assign,nonatomic) id viewController; +@end + + +/* -- Other Interfaces -- */ + + +@interface RichTextDisplayNode +@property(assign,nonatomic) id attributedText; +@end + +@interface RUIActionSheetItem : NSObject +@property(assign,nonatomic) id leftIconImage; +-(id) initWithLeftIconImage:(id) arg1 text:(id) arg2 identifier:(id) arg3 context:(id) arg4; +@end + +@interface NSAttributedStringMarkdownParser ++(id) currentConfig; ++(id) attributedStringUsingCurrentConfig:(id) arg1; +-(id) attributedStringFromMarkdownString:(id) arg1; +-(id) initWithConfig:(id) arg1; +@end + + +/* -- ActivityIndicator Interfaces -- */ + + +@interface AccountManager +@property(assign,nonatomic) id defaults; ++(id) sharedManager; +@end + +@interface _ASCollectionViewCell +@property(assign,nonatomic) id node; +@end + +@interface CellDisplayNodeWrapper +@property(assign,nonatomic) id contentNode; +@end + + + diff --git a/Tweak.xm b/Tweak.xm new file mode 100644 index 0000000..d2d600d --- /dev/null +++ b/Tweak.xm @@ -0,0 +1,298 @@ + +#include "Tweak.h" + +%group Redditv4 + +%hook CommentTreeNode +%property(assign,nonatomic)id commentTreeHeaderNode; +%property(assign,nonatomic)id commentTreeCommandBarNode; +%property(assign,nonatomic)BOOL isLoadingArchivedComment; +%end + + +%hook CommentTreeHeaderNode + +-(void) didLoad{ + %orig; + + [[self commentTreeNode] setCommentTreeHeaderNode:self]; +} +%end + + +%hook CommentTreeCommandBarNode +%property(assign,nonatomic) id activityIndicator; +%property(assign,nonatomic) id undeleteButton; + +-(void) didLoad{ + %orig; + + [[self commentTreeNode] setCommentTreeCommandBarNode:self]; + [[self commentTreeNode] setIsLoadingArchivedComment:NO]; +} +%end + + +/* +%hook ASCollectionView + +-(id) dequeueReusableCellWithReuseIdentifier: (id) arg1 forIndexPath:(id) arg2{ + id orig = %orig; + + if ([orig isKindOfClass:[%c(_ASCollectionViewCell) class]]){ + + id node = [[orig node] contentNode]; + + if ([node isKindOfClass:[%c(CommentTreeDisplayNode) class]]) { + id commentNode = [node commentNode]; + + if ([commentNode isLoadingArchivedComment]){ + + //[[[commentNode commentTreeCommandBarNode] activityIndicator] startAnimating]; + + } + } + } + return orig; +} +%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]; + + id commentTreeNode = [self commentTreeNode]; + id comment = [commentTreeNode comment]; + + [commentTreeNode setIsLoadingArchivedComment:YES]; + + /* + id isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; + if (isNightMode){ + UIActivityIndicatorView* activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; + } else { + UIActivityIndicatorView* activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; + } + [self setActivityIndicator:activityIndicator]; + [activityIndicator startAnimating]; + [sender addSubview:activityIndicator]; + */ + + 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]; + + author = [[jsonData objectForKey:@"data"][0] objectForKey:@"author"]; + body = [[jsonData objectForKey:@"data"][0] objectForKey:@"body"]; + + if ([body isEqualToString:@"[deleted]"] || [body isEqualToString:@"[removed]"]){ + body = @"[comment was unable to be archived]"; + } + + } else if (error != nil || data == nil){ + body = @"[an error occured]"; + } + + + id textColor = [[comment bodyRichTextAttributed] attributesAtIndex:0 longestEffectiveRange:nil inRange:NSMakeRange(0, [[comment bodyRichTextAttributed] length])][@"NSColor"]; + + NSMutableAttributedString *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) { + [bodyMutableAttributedText removeAttribute:NSForegroundColorAttributeName range:range]; + [bodyMutableAttributedText addAttribute:NSForegroundColorAttributeName value:textColor range:range]; + }]; + [bodyMutableAttributedText endEditing]; + + [comment setValue:bodyMutableAttributedText forKey:@"bodyRichTextAttributed"]; + + [comment setValue:author forKey:@"author"]; + [comment setValue:body forKey:@"bodyText"]; + + [comment setValue:bodyMutableAttributedText forKey:@"bodyAttributedText"]; + + [[commentTreeNode commentTreeHeaderNode] updateContentViewsForData:comment]; + + + [commentTreeNode setIsLoadingArchivedComment:NO]; + //[activityIndicator stopAnimating]; + + [request release]; + [queue release]; + [bodyMutableAttributedText release]; + }]; + } +} +%end + + +%hook PostDetailViewController +%property(assign,nonatomic) id feedPostTextWithThumbnailNode; +%property(assign,nonatomic) id feedPostDetailCellNode; +%end + + +%hook FeedPostDetailCellNode + +-(void) didLoad{ + %orig; + + [[[self delegate] viewController] setFeedPostTextWithThumbnailNode:[self textNode]]; + [[[self delegate] viewController] setFeedPostDetailCellNode:self]; +} +%end + + +%hook PostActionSheetViewController + +-(void) setItems:(id) arg1{ + + id 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]; + + id 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]; + + author = [[jsonData objectForKey:@"data"][0] objectForKey:@"author"]; + body = [[jsonData objectForKey:@"data"][0] objectForKey:@"selftext"]; + + if ([body isEqualToString:@"[deleted]"] || [body isEqualToString:@"[removed]"]){ + body = @"[comment was unable to be archived]"; + } + + } else if (error != nil || data == nil){ + body = @"[an error occured]"; + } + + id textColor = [[post selfPostRichTextAttributed] attributesAtIndex:0 longestEffectiveRange:nil inRange:NSMakeRange(0, [[post selfPostRichTextAttributed] length])][@"NSColor"]; + + if (textColor == nil){ + textColor = [UIColor colorWithRed:0.843137 green:0.854902 blue:0.862745 alpha:1.0]; + } + + NSMutableAttributedString *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) { + [bodyMutableAttributedText removeAttribute:NSForegroundColorAttributeName range:range]; + [bodyMutableAttributedText addAttribute:NSForegroundColorAttributeName value:textColor range:range]; + }]; + [bodyMutableAttributedText endEditing]; + + [post setValue:bodyMutableAttributedText forKey:@"selfPostRichTextAttributed"]; + [post setValue:bodyMutableAttributedText forKey:@"previewFeedPostTextString"]; + [post setAuthor:author]; + [post setValue:body forKey:@"selfText"]; + + + [[[[self postActionSheetDelegate] controller] feedPostDetailCellNode] configureSelfTextNode]; + + [request release]; + [queue release]; + [bodyMutableAttributedText release]; + }]; + } + } +} +%end + +%end + + + + +%ctor{ + + NSString* version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; + NSArray* versionArray = [version componentsSeparatedByString:@"."]; + + if ([versionArray[0] isEqualToString:@"4"]){ + %init(Redditv4); + } else if ([versionArray[0] isEqualToString:@"3"]) { + + } + +} + + + + + diff --git a/control b/control new file mode 100644 index 0000000..5a5df97 --- /dev/null +++ b/control @@ -0,0 +1,9 @@ +Package: com.lint.undelete +Name: TFDidThatSay? +Depends: mobilesubstrate +Version: 1.1.0 +Architecture: iphoneos-arm +Description: See "[deleted]" comments and posts without leaving Reddit! +Maintainer: lint +Author: lint +Section: Tweaks diff --git a/layout/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png b/layout/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png new file mode 100644 index 0000000..cac642d Binary files /dev/null and b/layout/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png differ diff --git a/layout/var/mobile/Library/Application Support/TFDidThatSay/eye160light.png b/layout/var/mobile/Library/Application Support/TFDidThatSay/eye160light.png new file mode 100644 index 0000000..9779a9f Binary files /dev/null and b/layout/var/mobile/Library/Application Support/TFDidThatSay/eye160light.png differ diff --git a/tfdidthatsay.plist b/tfdidthatsay.plist new file mode 100644 index 0000000..5849087 --- /dev/null +++ b/tfdidthatsay.plist @@ -0,0 +1 @@ +{ Filter = { Bundles = ( "com.reddit.Reddit" ); }; }