From 6d7d6bcb739c0758ae236f99d14ec060abd9a83d Mon Sep 17 00:00:00 2001 From: lint <47455468+lint@users.noreply.github.com> Date: Fri, 10 Jan 2020 12:38:59 -0500 Subject: [PATCH] Move Apollo button to action menu --- tweak/Apollo.h | 47 ++++++---- tweak/Apollo.xm | 238 +++++++++++++++++++++++++++++++----------------- 2 files changed, 183 insertions(+), 102 deletions(-) diff --git a/tweak/Apollo.h b/tweak/Apollo.h index fe38f6b..fa04951 100644 --- a/tweak/Apollo.h +++ b/tweak/Apollo.h @@ -2,36 +2,42 @@ /* -- Comment Interfaces -- */ @interface RKComment -@property(assign,nonatomic) NSString* body; -@property(assign,nonatomic) NSString* bodyHTML; -@property(assign,nonatomic) NSString* author; -@property(assign,nonatomic) NSString* fullName; +@property(assign,nonatomic) NSString *body; +@property(assign,nonatomic) NSString *bodyHTML; +@property(assign,nonatomic) NSString *author; +@property(assign,nonatomic) NSString *fullName; @end -@interface ApolloCommentCellNode +@interface CommentCellNode @property(assign,nonatomic)id view; -(BOOL) isSelected; -(void) _layoutSublayouts; -(void) didLoad; -(void) calculatedLayoutDidChange; -//custom element -@property(strong,nonatomic) id undeleteButton; - +//custom elements +-(void) undeleteCellWasSelected; @end /* -- Post Interfaces -- */ @interface RKLink -@property(assign,nonatomic) NSString* selfText; -@property(assign,nonatomic) NSString* author; -@property(assign,nonatomic) NSString* fullName; - +@property(assign,nonatomic) NSString *selfText; +@property(assign,nonatomic) NSString *author; +@property(assign,nonatomic) NSString *fullName; -(BOOL) isSelfPost; @end -@interface ApolloCommentsHeaderCellNode +@interface CommentsHeaderCellNode @property(strong, nonatomic) id undeleteButton; +@property(strong, nonatomic) id closestViewController; +@end + +@interface CommentsViewController + +//custom elements +@property(strong, nonatomic) id headerCellNode; +-(void) undeleteCellWasSelected; @end /* -- Other Interfaces -- */ @@ -40,6 +46,14 @@ +(id) attributedStringFromMarkdown:(id) arg1 withAttributes:(id) arg2; @end +@interface ActionController +-(id) tableView:(id) arg1 cellForRowAtIndexPath:(NSIndexPath *)arg2; +-(NSInteger) tableView:(id) arg1 numberOfRowsInSection:(NSInteger) arg2; +@end + +@interface IconActionTableViewCell : UITableViewCell +@end + /* -- ASyncDisplayKit Interfaces -- */ @interface _ASDisplayView : UIView @@ -58,9 +72,6 @@ @property(assign,nonatomic) id attributedText; @end -@interface ApolloApolloButtonNode -@property(assign,nonatomic) NSArray* subnodes; +@interface ApolloButtonNode +@property(assign,nonatomic) NSArray *subnodes; @end - - - diff --git a/tweak/Apollo.xm b/tweak/Apollo.xm index f331f9c..55dd263 100644 --- a/tweak/Apollo.xm +++ b/tweak/Apollo.xm @@ -9,10 +9,17 @@ static CGFloat pushshiftRequestTimeoutValue; %group Apollo NSDictionary* apolloBodyAttributes = nil; +BOOL shouldAddUndeleteCell = NO; +id apolloCommentCell; +id apolloCommentController; -%hook ApolloApolloButtonNode +%hook ApolloButtonNode %end +%hook IconActionTableViewCell +%end + + %hook RKComment -(BOOL) isDeleted{ @@ -22,6 +29,7 @@ NSDictionary* apolloBodyAttributes = nil; -(BOOL) isModeratorRemoved{ return NO; } + %end @@ -33,60 +41,118 @@ NSDictionary* apolloBodyAttributes = nil; return %orig; } + %end -%hook ApolloCommentCellNode -%property(strong,nonatomic) id undeleteButton; +%hook ActionController --(void) didLoad { +-(id) tableView:(id) arg1 cellForRowAtIndexPath:(NSIndexPath *) arg2{ + + if (shouldAddUndeleteCell){ + if ([arg2 row] == [self tableView:arg1 numberOfRowsInSection:0] - 1){ + + id undeleteCell = [[objc_getClass("Apollo.IconActionTableViewCell") alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"IconActionCell"]; + NSArray *visibleCells = [arg1 visibleCells]; + id prevCell = visibleCells[[visibleCells count] - 2]; + + UIImageView *prevCellImageView = MSHookIvar(prevCell, "iconImageView"); + CGSize prevImageSize = [[prevCellImageView image] size]; + UIColor *menuColor = [prevCellImageView tintColor]; + + UIImage *undeleteImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; + CGFloat undeleteImageSizeValue = prevImageSize.width > prevImageSize.height ? prevImageSize.width : prevImageSize.height; + + UIGraphicsBeginImageContextWithOptions(CGSizeMake(undeleteImageSizeValue, undeleteImageSizeValue), NO, 0); + [undeleteImage drawInRect:CGRectMake(0, 0, undeleteImageSizeValue, undeleteImageSizeValue)]; + undeleteImage = [UIGraphicsGetImageFromCurrentImageContext() imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + UIGraphicsEndImageContext(); + + UILabel *undeleteLabel = MSHookIvar(undeleteCell, "actionTitleLabel"); + UIImageView *undeleteImageView = MSHookIvar(undeleteCell, "iconImageView"); + + undeleteLabel.text = @"TF Did That Say?"; + undeleteLabel.textColor = menuColor; + + undeleteImageView.image = undeleteImage; + undeleteImageView.tintColor = menuColor; + + return undeleteCell; + } + } + + return %orig; +} + +-(void) tableView:(id) arg1 didSelectRowAtIndexPath:(NSIndexPath *)arg2{ + + if (shouldAddUndeleteCell){ + if ([arg2 row] == [self tableView:arg1 numberOfRowsInSection:0] - 1){ + + if (apolloCommentCell){ + [apolloCommentCell undeleteCellWasSelected]; + } else { + [apolloCommentController undeleteCellWasSelected]; + } + } + } + %orig; +} + +-(NSInteger) tableView:(id) arg1 numberOfRowsInSection:(NSInteger) arg2{ + + if (shouldAddUndeleteCell){ + return %orig + 1; + } else { + return %orig; + } +} + +-(id) animationControllerForDismissedController:(id) arg1{ + + shouldAddUndeleteCell = NO; + + return %orig; +} + +%end + + +%hook CommentCellNode + +-(void) moreOptionsTappedWithSender:(id) arg1{ id commentBody = [MSHookIvar(self, "comment") body]; if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]){ - - CGFloat imageSize = 20.0f; - - UIButton *undeleteButton = [UIButton buttonWithType:UIButtonTypeCustom]; - [undeleteButton addTarget:self action:@selector(didTapUndeleteButton:) forControlEvents:UIControlEventTouchUpInside]; - undeleteButton.frame = CGRectMake(0, 0, imageSize, imageSize); - - UIImage* undeleteImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; - [undeleteButton setImage:undeleteImage forState:UIControlStateNormal]; - - [[self view] addSubview:undeleteButton]; - [self setUndeleteButton:undeleteButton]; - + shouldAddUndeleteCell = YES; + apolloCommentCell = self; + apolloCommentController = nil; } + + %orig; } --(void) _layoutSublayouts{ - %orig; +-(void) longPressedWithGestureRecognizer:(id) arg1{ - if ([self undeleteButton]){ + id commentBody = [MSHookIvar(self, "comment") body]; - CGFloat imageSize = 20.0f; - - id moreNode = MSHookIvar(self, "moreOptionsNode"); - id ageNode = MSHookIvar(self, "ageNode"); - - CGRect nodeFrame = [moreNode frame]; - CGFloat centerHeight = (nodeFrame.size.height + nodeFrame.origin.y * 2) / 2.0f; - CGFloat nodeSpacing =[ageNode frame].origin.x - nodeFrame.origin.x - nodeFrame.size.width; - - [[self undeleteButton] setFrame:CGRectMake(nodeFrame.origin.x - imageSize - nodeSpacing, centerHeight - (imageSize / 2), imageSize, imageSize)]; + if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]){ + shouldAddUndeleteCell = YES; + apolloCommentCell = self; + apolloCommentController = nil; } + + %orig; } %new --(void) didTapUndeleteButton:(id) sender{ - - [sender setEnabled:NO]; +-(void) undeleteCellWasSelected{ id comment = MSHookIvar(self, "comment"); - [%c(TFHelper) getUndeleteDataWithID:[[comment fullName] componentsSeparatedByString:@"_"][1] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:@{@"sender" : sender} completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; + [%c(TFHelper) getUndeleteDataWithID:[[comment fullName] componentsSeparatedByString:@"_"][1] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; } %new @@ -111,92 +177,96 @@ NSDictionary* apolloBodyAttributes = nil; [comment setAuthor:author]; [comment setBody:body]; - - [data[@"sender"] setEnabled:YES]; } %end -%hook ApolloCommentsHeaderCellNode -%property(strong, nonatomic) id undeleteButton; +%hook CommentsViewController +%property(strong, nonatomic) id headerCellNode; --(void) didLoad{ - %orig; +-(void) moreOptionsBarButtonItemTappedWithSender:(id) arg1{ + + RKLink *post = MSHookIvar(self, "link"); + NSString *postBody = [post selfText]; - id post = MSHookIvar(self, "link"); - id postBody = [post selfText]; - if ([post isSelfPost]){ if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]){ - - CGFloat imageSize = 20.0f; - - UIButton *undeleteButton = [UIButton buttonWithType:UIButtonTypeCustom]; - [undeleteButton addTarget:self action:@selector(didTapUndeleteButton:) forControlEvents:UIControlEventTouchUpInside]; - - UIImage* undeleteImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; - [undeleteButton setImage:undeleteImage forState:UIControlStateNormal]; - undeleteButton.frame = CGRectMake(0, 0, imageSize, imageSize); - - [[self view] addSubview:undeleteButton]; - [self setUndeleteButton:undeleteButton]; + shouldAddUndeleteCell = YES; + apolloCommentCell = nil; + apolloCommentController = self; } } -} - --(void) _layoutSublayouts{ - %orig; - if ([self undeleteButton]){ - - CGFloat imageSize = 20.0f; - - id postInfoNode = MSHookIvar(self, "postInfoNode"); - id ageNode = MSHookIvar(postInfoNode, "ageButtonNode"); - - CGFloat centerHeight = [postInfoNode frame].origin.y + ([ageNode frame].size.height + [ageNode frame].origin.y * 2) / 2.0f; - CGFloat buttonXPos = [postInfoNode frame].origin.x + [postInfoNode frame].size.width - imageSize; - - [[self undeleteButton] setFrame:CGRectMake(buttonXPos, centerHeight - (imageSize / 2), imageSize, imageSize)]; - } + %orig; } %new --(void) didTapUndeleteButton:(id) sender{ - - [sender setEnabled:NO]; +-(void) undeleteCellWasSelected{ id post = MSHookIvar(self, "link"); - [%c(TFHelper) getUndeleteDataWithID:[[post fullName] componentsSeparatedByString:@"_"][1] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:@{@"sender" : sender} completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; + [%c(TFHelper) getUndeleteDataWithID:[[post fullName] componentsSeparatedByString:@"_"][1] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; } %new -(void) completeUndeletePostAction:(NSDictionary *) data{ - id bodyNode = MSHookIvar(self, "bodyNode"); - id postInfoNode = MSHookIvar(self, "postInfoNode"); + id headerCellNode = [self headerCellNode]; + id bodyNode = MSHookIvar(headerCellNode, "bodyNode"); + id postInfoNode = MSHookIvar(headerCellNode, "postInfoNode"); id authorNode = MSHookIvar(postInfoNode, "authorButtonNode"); id authorTextNode = [authorNode subnodes][0]; NSString *author = data[@"author"]; + NSString *authorTextString = [NSString stringWithFormat:@"by %@", author]; + NSString *body = data[@"body"]; - //id post = MSHookIvar(self, "link"); + id post = MSHookIvar(self, "link"); //MSHookIvar(post, "_author") = author; //Crashes when clicking on author name. You will have to search the author name to go find the profile. - author = [NSString stringWithFormat:@"by %@", author]; - id prevAuthorAttributedString = [authorTextNode attributedString]; NSDictionary *authorStringAttributes = [prevAuthorAttributedString attributesAtIndex:0 longestEffectiveRange:nil inRange:NSMakeRange(0, [prevAuthorAttributedString length])]; - NSAttributedString* newAuthorAttributedString = [[NSAttributedString alloc] initWithString:author attributes:authorStringAttributes]; + NSAttributedString* newAuthorAttributedString = [[NSAttributedString alloc] initWithString:authorTextString attributes:authorStringAttributes]; [authorTextNode setAttributedText:newAuthorAttributedString]; [authorTextNode setAttributedString:newAuthorAttributedString]; - [bodyNode setAttributedString:[%c(MarkdownRenderer) attributedStringFromMarkdown:data[@"body"] withAttributes:apolloBodyAttributes]]; + [bodyNode setAttributedString:[%c(MarkdownRenderer) attributedStringFromMarkdown:body withAttributes:apolloBodyAttributes]]; + [post setSelfText:body]; +} + +%end + + +%hook CommentsHeaderCellNode + +-(void) didLoad{ + %orig; - [data[@"sender"] setEnabled:YES]; + [[self closestViewController] setHeaderCellNode:self]; +} + +-(void) _layoutSublayouts{ + %orig; + + [[self closestViewController] setHeaderCellNode:self]; +} + +-(void) longPressedWithGestureRecognizer:(id) arg1{ + + RKLink *post = MSHookIvar(self, "link"); + NSString *postBody = [post selfText]; + + if ([post isSelfPost]){ + if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]){ + shouldAddUndeleteCell = YES; + apolloCommentCell = nil; + apolloCommentController = self; + } + } + + %orig; } %end @@ -249,7 +319,7 @@ static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStrin CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, prefsChanged, CFSTR("com.lint.undelete.prefs.changed"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); - %init(Apollo, ApolloCommentsHeaderCellNode = objc_getClass("Apollo.CommentsHeaderCellNode"), ApolloCommentCellNode = objc_getClass("Apollo.CommentCellNode"), ApolloApolloButtonNode = objc_getClass("Apollo.ApolloButtonNode")); + %init(Apollo, CommentsHeaderCellNode = objc_getClass("Apollo.CommentsHeaderCellNode"), CommentCellNode = objc_getClass("Apollo.CommentCellNode"), ApolloButtonNode = objc_getClass("Apollo.ApolloButtonNode"), ActionController = objc_getClass("Apollo.ActionController"), IconActionTableViewCell = objc_getClass("Apollo.IconActionTableViewCell"), CommentsViewController = objc_getClass("Apollo.CommentsViewController")); } } }