Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

326 Zeilen
9.7KB

  1. #import "Apollo.h"
  2. #import "assets/TFHelper.h"
  3. static BOOL isTFDeletedOnly;
  4. static BOOL isApolloEnabled;
  5. static CGFloat pushshiftRequestTimeoutValue;
  6. %group Apollo
  7. NSDictionary* apolloBodyAttributes = nil;
  8. BOOL shouldAddUndeleteCell = NO;
  9. id apolloCommentCell;
  10. id apolloCommentController;
  11. %hook ApolloButtonNode
  12. %end
  13. %hook IconActionTableViewCell
  14. %end
  15. %hook RKComment
  16. -(BOOL) isDeleted{
  17. return NO;
  18. }
  19. -(BOOL) isModeratorRemoved{
  20. return NO;
  21. }
  22. %end
  23. %hook MarkdownRenderer
  24. +(id) attributedStringFromHTML:(id)arg1 attributes:(id) arg2 compact:(BOOL) arg3{
  25. apolloBodyAttributes = [arg2 copy];
  26. return %orig;
  27. }
  28. %end
  29. %hook ActionController
  30. -(id) tableView:(id) arg1 cellForRowAtIndexPath:(NSIndexPath *) arg2{
  31. if (shouldAddUndeleteCell){
  32. if ([arg2 row] == [self tableView:arg1 numberOfRowsInSection:0] - 1){
  33. id undeleteCell = [[objc_getClass("Apollo.IconActionTableViewCell") alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"IconActionCell"];
  34. NSArray *visibleCells = [arg1 visibleCells];
  35. id prevCell = visibleCells[[visibleCells count] - 2];
  36. UIImageView *prevCellImageView = MSHookIvar<UIImageView *>(prevCell, "iconImageView");
  37. CGSize prevImageSize = [[prevCellImageView image] size];
  38. UIColor *menuColor = [prevCellImageView tintColor];
  39. UIImage *undeleteImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"];
  40. CGFloat undeleteImageSizeValue = prevImageSize.width > prevImageSize.height ? prevImageSize.width : prevImageSize.height;
  41. UIGraphicsBeginImageContextWithOptions(CGSizeMake(undeleteImageSizeValue, undeleteImageSizeValue), NO, 0);
  42. [undeleteImage drawInRect:CGRectMake(0, 0, undeleteImageSizeValue, undeleteImageSizeValue)];
  43. undeleteImage = [UIGraphicsGetImageFromCurrentImageContext() imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
  44. UIGraphicsEndImageContext();
  45. UILabel *undeleteLabel = MSHookIvar<UILabel *>(undeleteCell, "actionTitleLabel");
  46. UIImageView *undeleteImageView = MSHookIvar<UIImageView *>(undeleteCell, "iconImageView");
  47. undeleteLabel.text = @"TF Did That Say?";
  48. undeleteLabel.textColor = menuColor;
  49. undeleteImageView.image = undeleteImage;
  50. undeleteImageView.tintColor = menuColor;
  51. return undeleteCell;
  52. }
  53. }
  54. return %orig;
  55. }
  56. -(void) tableView:(id) arg1 didSelectRowAtIndexPath:(NSIndexPath *)arg2{
  57. if (shouldAddUndeleteCell){
  58. if ([arg2 row] == [self tableView:arg1 numberOfRowsInSection:0] - 1){
  59. if (apolloCommentCell){
  60. [apolloCommentCell undeleteCellWasSelected];
  61. } else {
  62. [apolloCommentController undeleteCellWasSelected];
  63. }
  64. }
  65. }
  66. %orig;
  67. }
  68. -(NSInteger) tableView:(id) arg1 numberOfRowsInSection:(NSInteger) arg2{
  69. if (shouldAddUndeleteCell){
  70. return %orig + 1;
  71. } else {
  72. return %orig;
  73. }
  74. }
  75. -(id) animationControllerForDismissedController:(id) arg1{
  76. shouldAddUndeleteCell = NO;
  77. return %orig;
  78. }
  79. %end
  80. %hook CommentCellNode
  81. -(void) moreOptionsTappedWithSender:(id) arg1{
  82. id commentBody = [MSHookIvar<id>(self, "comment") body];
  83. if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]){
  84. shouldAddUndeleteCell = YES;
  85. apolloCommentCell = self;
  86. apolloCommentController = nil;
  87. }
  88. %orig;
  89. }
  90. -(void) longPressedWithGestureRecognizer:(id) arg1{
  91. id commentBody = [MSHookIvar<id>(self, "comment") body];
  92. if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]){
  93. shouldAddUndeleteCell = YES;
  94. apolloCommentCell = self;
  95. apolloCommentController = nil;
  96. }
  97. %orig;
  98. }
  99. %new
  100. -(void) undeleteCellWasSelected{
  101. id comment = MSHookIvar<id>(self, "comment");
  102. [%c(TFHelper) getUndeleteDataWithID:[[comment fullName] componentsSeparatedByString:@"_"][1] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)];
  103. }
  104. %new
  105. -(void) completeUndeleteCommentAction:(NSDictionary *) data{
  106. id comment = MSHookIvar<id>(self, "comment");
  107. id bodyNode = MSHookIvar<id>(self, "bodyNode");
  108. id authorNode = MSHookIvar<id>(self, "authorNode");
  109. id authorTextNode = [authorNode subnodes][0];
  110. NSString *author = data[@"author"];
  111. NSString *body = data[@"body"];
  112. id prevAuthorAttributedString = [authorTextNode attributedString];
  113. NSDictionary *authorStringAttributes = [prevAuthorAttributedString attributesAtIndex:0 longestEffectiveRange:nil inRange:NSMakeRange(0, [prevAuthorAttributedString length])];
  114. NSAttributedString *newAuthorAttributedString = [[NSAttributedString alloc] initWithString:author attributes:authorStringAttributes];
  115. [authorTextNode setAttributedText:newAuthorAttributedString];
  116. [authorTextNode setAttributedString:newAuthorAttributedString];
  117. [bodyNode setAttributedString:[%c(MarkdownRenderer) attributedStringFromMarkdown:body withAttributes:apolloBodyAttributes]];
  118. [comment setAuthor:author];
  119. [comment setBody:body];
  120. }
  121. %end
  122. %hook CommentsViewController
  123. %property(strong, nonatomic) id headerCellNode;
  124. -(void) moreOptionsBarButtonItemTappedWithSender:(id) arg1{
  125. RKLink *post = MSHookIvar<RKLink *>(self, "link");
  126. NSString *postBody = [post selfText];
  127. if ([post isSelfPost]){
  128. if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]){
  129. shouldAddUndeleteCell = YES;
  130. apolloCommentCell = nil;
  131. apolloCommentController = self;
  132. }
  133. }
  134. %orig;
  135. }
  136. %new
  137. -(void) undeleteCellWasSelected{
  138. id post = MSHookIvar<id>(self, "link");
  139. [%c(TFHelper) getUndeleteDataWithID:[[post fullName] componentsSeparatedByString:@"_"][1] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeletePostAction:)];
  140. }
  141. %new
  142. -(void) completeUndeletePostAction:(NSDictionary *) data{
  143. id headerCellNode = [self headerCellNode];
  144. id bodyNode = MSHookIvar<id>(headerCellNode, "bodyNode");
  145. id postInfoNode = MSHookIvar<id>(headerCellNode, "postInfoNode");
  146. id authorNode = MSHookIvar<id>(postInfoNode, "authorButtonNode");
  147. id authorTextNode = [authorNode subnodes][0];
  148. NSString *author = data[@"author"];
  149. NSString *authorTextString = [NSString stringWithFormat:@"by %@", author];
  150. NSString *body = data[@"body"];
  151. id post = MSHookIvar<id>(self, "link");
  152. //MSHookIvar<NSString*>(post, "_author") = author; //Crashes when clicking on author name. You will have to search the author name to go find the profile.
  153. id prevAuthorAttributedString = [authorTextNode attributedString];
  154. NSDictionary *authorStringAttributes = [prevAuthorAttributedString attributesAtIndex:0 longestEffectiveRange:nil inRange:NSMakeRange(0, [prevAuthorAttributedString length])];
  155. NSAttributedString* newAuthorAttributedString = [[NSAttributedString alloc] initWithString:authorTextString attributes:authorStringAttributes];
  156. [authorTextNode setAttributedText:newAuthorAttributedString];
  157. [authorTextNode setAttributedString:newAuthorAttributedString];
  158. [bodyNode setAttributedString:[%c(MarkdownRenderer) attributedStringFromMarkdown:body withAttributes:apolloBodyAttributes]];
  159. [post setSelfText:body];
  160. }
  161. %end
  162. %hook CommentsHeaderCellNode
  163. -(void) didLoad{
  164. %orig;
  165. [[self closestViewController] setHeaderCellNode:self];
  166. }
  167. -(void) _layoutSublayouts{
  168. %orig;
  169. [[self closestViewController] setHeaderCellNode:self];
  170. }
  171. -(void) longPressedWithGestureRecognizer:(id) arg1{
  172. RKLink *post = MSHookIvar<RKLink *>(self, "link");
  173. NSString *postBody = [post selfText];
  174. if ([post isSelfPost]){
  175. if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]){
  176. shouldAddUndeleteCell = YES;
  177. apolloCommentCell = nil;
  178. apolloCommentController = self;
  179. }
  180. }
  181. %orig;
  182. }
  183. %end
  184. %end
  185. static void loadPrefs(){
  186. NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/User/Library/Preferences/com.lint.undelete.prefs.plist"];
  187. if (prefs){
  188. if ([prefs objectForKey:@"isApolloEnabled"] != nil) {
  189. isApolloEnabled = [[prefs objectForKey:@"isApolloEnabled"] boolValue];
  190. } else {
  191. isApolloEnabled = YES;
  192. }
  193. if ([prefs objectForKey:@"isTFDeletedOnly"] != nil) {
  194. isTFDeletedOnly = [[prefs objectForKey:@"isTFDeletedOnly"] boolValue];
  195. } else {
  196. isTFDeletedOnly = YES;
  197. }
  198. if ([prefs objectForKey:@"requestTimeoutValue"] != nil){
  199. pushshiftRequestTimeoutValue = [[prefs objectForKey:@"requestTimeoutValue"] doubleValue];
  200. } else {
  201. pushshiftRequestTimeoutValue = 10;
  202. }
  203. } else {
  204. isApolloEnabled = YES;
  205. isTFDeletedOnly = YES;
  206. pushshiftRequestTimeoutValue = 10;
  207. }
  208. }
  209. static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
  210. loadPrefs();
  211. }
  212. %ctor {
  213. loadPrefs();
  214. NSString* processName = [[NSProcessInfo processInfo] processName];
  215. if ([processName isEqualToString:@"Apollo"]){
  216. if (isApolloEnabled){
  217. CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, prefsChanged, CFSTR("com.lint.undelete.prefs.changed"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately);
  218. %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"));
  219. }
  220. }
  221. }