You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

219 lines
5.7KB

  1. #import "BaconReader.h"
  2. #import "assets/TFHelper.h"
  3. #import "assets/MMMarkdown/MMMarkdown.h"
  4. static BOOL isBaconReaderEnabled;
  5. static BOOL isTFDeletedOnly;
  6. static CGFloat pushshiftRequestTimeoutValue;
  7. %group BaconReader
  8. BOOL shouldHaveBRUndeleteAction = NO;
  9. NSString *tfPostSelftext;
  10. NSString *tfPostAuthor;
  11. id tfCommentCellView;
  12. id tfStoryController;
  13. %hook CommentCell
  14. %end
  15. %hook CommentCellView
  16. %end
  17. %hook StoryDetailView
  18. %end
  19. %hook BRComment
  20. -(BOOL) contains_htmlValue{
  21. return YES;
  22. }
  23. -(BOOL) primitiveContains_htmlValue{
  24. return YES;
  25. }
  26. -(BOOL) is_deletedValue{
  27. return NO;
  28. }
  29. -(BOOL) primitiveIs_deletedValue{
  30. return NO;
  31. }
  32. %end
  33. %hook BRStory
  34. +(id) storyWithDictionary:(id) arg1 inContext:(id) arg2 {
  35. id orig = %orig;
  36. if (tfPostSelftext){
  37. [orig setSelftext_html:tfPostSelftext];
  38. [orig setAuthor:tfPostAuthor];
  39. tfPostSelftext = nil;
  40. tfPostAuthor = nil;
  41. }
  42. return orig;
  43. }
  44. %end
  45. %hook UIViewController
  46. -(void) presentViewController:(id) arg1 animated:(BOOL) arg2 completion:(id) arg3 {
  47. if ([arg1 isKindOfClass:[UIAlertController class]] && shouldHaveBRUndeleteAction){
  48. UIAlertAction *undeleteAction;
  49. if (tfCommentCellView){
  50. undeleteAction = [UIAlertAction actionWithTitle:@"TF Did That Say?" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){[tfStoryController handleUndeleteCommentAction];}];
  51. } else {
  52. undeleteAction = [UIAlertAction actionWithTitle:@"TF Did That Say?" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){[tfStoryController handleUndeletePostAction];}];
  53. }
  54. [arg1 addAction:undeleteAction];
  55. }
  56. %orig;
  57. }
  58. %end
  59. %hook StoryDetailViewController
  60. -(void) showMoreCommentActions:(id) arg1 showAll:(BOOL) arg2 {
  61. NSString *commentBody = [[arg1 comment] body];
  62. if ((isTFDeletedOnly && ([commentBody isEqualToString:@"[deleted]"] || [commentBody isEqualToString:@"[removed]"])) || !isTFDeletedOnly) {
  63. shouldHaveBRUndeleteAction = YES;
  64. tfCommentCellView = arg1;
  65. tfStoryController = self;
  66. tfPostSelftext = nil;
  67. }
  68. %orig;
  69. shouldHaveBRUndeleteAction = NO;
  70. }
  71. -(void) menuTouchedWithSender:(id) arg1 {
  72. if ([[self story] is_selfValue]){
  73. NSString *postBody = [[self story] selftext];
  74. if ((isTFDeletedOnly && ([postBody isEqualToString:@"[deleted]"] || [postBody isEqualToString:@"[removed]"])) || !isTFDeletedOnly) {
  75. shouldHaveBRUndeleteAction = YES;
  76. tfCommentCellView = nil;
  77. tfStoryController = self;
  78. tfPostSelftext = nil;
  79. }
  80. }
  81. %orig;
  82. shouldHaveBRUndeleteAction = NO;
  83. }
  84. %new
  85. -(void) handleUndeleteCommentAction{
  86. [%c(TFHelper) getUndeleteDataWithID:[[tfCommentCellView comment] serverID] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)];
  87. }
  88. %new
  89. -(void) completeUndeleteCommentAction:(NSDictionary *) data{
  90. id comment = [tfCommentCellView comment];
  91. NSString *body = data[@"body"];
  92. [comment setAuthor:data[@"author"]];
  93. [comment setBody:body];
  94. [comment setBody_html:[%c(MMMarkdown) HTMLStringWithMarkdown:body extensions:MMMarkdownExtensionsGitHubFlavored error:nil]];
  95. [comment setAttributedDescriptionString:nil];
  96. NSAttributedString *commentAttrString = [%c(BRUtils) attributedDescriptionForComment:comment];
  97. [comment setAttributedDescriptionString:commentAttrString];
  98. [[[self detailPage] tableView] reloadData];
  99. }
  100. %new
  101. -(void) handleUndeletePostAction{
  102. [%c(TFHelper) getUndeleteDataWithID:[[self story] serverID] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeletePostAction:)];
  103. }
  104. %new
  105. -(void) completeUndeletePostAction:(NSDictionary *) data{
  106. tfPostAuthor = data[@"author"];
  107. tfPostSelftext = [%c(MMMarkdown) HTMLStringWithMarkdown:data[@"body"] extensions:MMMarkdownExtensionsGitHubFlavored error:nil];
  108. [[self detailPage] refreshTouched];
  109. }
  110. %end
  111. %end
  112. static void loadPrefs(){
  113. NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/User/Library/Preferences/com.lint.undelete.prefs.plist"];
  114. if (prefs){
  115. if ([prefs objectForKey:@"isBaconReaderEnabled"] != nil){
  116. isBaconReaderEnabled = [[prefs objectForKey:@"isBaconReaderEnabled"] boolValue];
  117. } else {
  118. isBaconReaderEnabled = YES;
  119. }
  120. if ([prefs objectForKey:@"isTFDeletedOnly"] != nil) {
  121. isTFDeletedOnly = [[prefs objectForKey:@"isTFDeletedOnly"] boolValue];
  122. } else {
  123. isTFDeletedOnly = YES;
  124. }
  125. if ([prefs objectForKey:@"requestTimeoutValue"] != nil){
  126. pushshiftRequestTimeoutValue = [[prefs objectForKey:@"requestTimeoutValue"] doubleValue];
  127. } else {
  128. pushshiftRequestTimeoutValue = 10;
  129. }
  130. } else {
  131. isBaconReaderEnabled = YES;
  132. isTFDeletedOnly = YES;
  133. pushshiftRequestTimeoutValue = 10;
  134. }
  135. }
  136. static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
  137. loadPrefs();
  138. }
  139. %ctor {
  140. loadPrefs();
  141. NSString* processName = [[NSProcessInfo processInfo] processName];
  142. if ([processName isEqualToString:@"BaconReader"]){
  143. if (isBaconReaderEnabled){
  144. CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, prefsChanged, CFSTR("com.lint.undelete.prefs.changed"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately);
  145. %init(BaconReader, StoryDetailView = objc_getClass("BaconReader.StoryDetailView"), StoryDetailViewController = objc_getClass("BaconReader.StoryDetailViewController"), CommentCellView = objc_getClass("BaconReader.CommentCellView"), CommentCell = objc_getClass("BaconReader.CommentCell"));
  146. }
  147. }
  148. }