@end | @end | ||||
@interface CommentsViewController | @interface CommentsViewController | ||||
-(void) respondToStyleChange; | |||||
- (void)respondToStyleChange; | |||||
@end | @end | ||||
@interface CommentPostHeaderNode | @interface CommentPostHeaderNode | ||||
@property(assign, nonatomic) BOOL isPostHeader; | @property(assign, nonatomic) BOOL isPostHeader; | ||||
@property(strong, nonatomic) id delegate; | @property(strong, nonatomic) id delegate; | ||||
@property(strong, nonatomic) id node; | @property(strong, nonatomic) id node; | ||||
-(void) addButton:(id) arg1; | |||||
- (void)addButton:(id)arg1; | |||||
@end | @end | ||||
/* -- Other Interfaces -- */ | /* -- Other Interfaces -- */ | ||||
@interface MarkupEngine | @interface MarkupEngine | ||||
+(id) markDownHTML:(id) arg1 forSubreddit:(id) arg2; | |||||
+ (id)markDownHTML:(id)arg1 forSubreddit:(id)arg2; | |||||
@end | @end | ||||
@interface Resources | @interface Resources | ||||
+(BOOL) isNight; | |||||
+ (BOOL)isNight; | |||||
@end | @end |
#import "assets/TFHelper.h" | #import "assets/TFHelper.h" | ||||
#import "assets/MMMarkdown/MMMarkdown.h" | #import "assets/MMMarkdown/MMMarkdown.h" | ||||
static BOOL isEnabled; | |||||
static BOOL isAlienBlueEnabled; | static BOOL isAlienBlueEnabled; | ||||
static BOOL isTFDeletedOnly; | static BOOL isTFDeletedOnly; | ||||
static CGFloat pushshiftRequestTimeoutValue; | static CGFloat pushshiftRequestTimeoutValue; | ||||
%hook CommentOptionsDrawerView | %hook CommentOptionsDrawerView | ||||
-(id) initWithNode:(id) arg1 { | |||||
- (id)initWithNode:(id)arg1 { | |||||
id orig = %orig; | id orig = %orig; | ||||
NSString *body; | NSString *body; | ||||
if ([self isPostHeader]) { | if ([self isPostHeader]) { | ||||
body = [[arg1 post] selftext]; | body = [[arg1 post] selftext]; | ||||
} else { | } else { | ||||
body = [[(CommentNode *)arg1 comment] body]; | body = [[(CommentNode *)arg1 comment] body]; | ||||
} | |||||
} | |||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:body isDeletedOnly:isTFDeletedOnly]){ | if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:body isDeletedOnly:isTFDeletedOnly]){ | ||||
CGSize refSize = [[self buttons][0] frame].size; | CGSize refSize = [[self buttons][0] frame].size; | ||||
UIButton *undeleteButton = [UIButton buttonWithType:UIButtonTypeCustom]; | UIButton *undeleteButton = [UIButton buttonWithType:UIButtonTypeCustom]; | ||||
[undeleteButton setFrame:CGRectMake(0, 0, refSize.width, refSize.height)]; | [undeleteButton setFrame:CGRectMake(0, 0, refSize.width, refSize.height)]; | ||||
if ([self isPostHeader]){ | if ([self isPostHeader]){ | ||||
[undeleteButton addTarget:self action:@selector(didTapPostUndeleteButton:) forControlEvents:UIControlEventTouchUpInside]; | [undeleteButton addTarget:self action:@selector(didTapPostUndeleteButton:) forControlEvents:UIControlEventTouchUpInside]; | ||||
} else { | } else { | ||||
[undeleteButton addTarget:self action:@selector(didTapCommentUndeleteButton:) forControlEvents:UIControlEventTouchUpInside]; | [undeleteButton addTarget:self action:@selector(didTapCommentUndeleteButton:) forControlEvents:UIControlEventTouchUpInside]; | ||||
} | } | ||||
if ([%c(Resources) isNight]) { | if ([%c(Resources) isNight]) { | ||||
[undeleteButton setImage:[UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"] forState:UIControlStateNormal]; | [undeleteButton setImage:[UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"] forState:UIControlStateNormal]; | ||||
} else { | } else { | ||||
[undeleteButton setImage:[UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160light.png"] forState:UIControlStateNormal]; | [undeleteButton setImage:[UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160light.png"] forState:UIControlStateNormal]; | ||||
} | } | ||||
undeleteButton.imageView.contentMode = UIViewContentModeScaleAspectFit; | undeleteButton.imageView.contentMode = UIViewContentModeScaleAspectFit; | ||||
undeleteButton.imageEdgeInsets = UIEdgeInsetsMake(10, 10, 10, 10); | undeleteButton.imageEdgeInsets = UIEdgeInsetsMake(10, 10, 10, 10); | ||||
[self addButton:undeleteButton]; | [self addButton:undeleteButton]; | ||||
} | } | ||||
return orig; | return orig; | ||||
} | } | ||||
%new | |||||
-(void) didTapCommentUndeleteButton:(id) sender { | |||||
%new | |||||
- (void)didTapCommentUndeleteButton:(id)sender { | |||||
[sender setEnabled:NO]; | [sender setEnabled:NO]; | ||||
id comment = [[self node] comment]; | id comment = [[self node] comment]; | ||||
[%c(TFHelper) getUndeleteDataWithID:[comment ident] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:@{@"sender" : sender} completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; | [%c(TFHelper) getUndeleteDataWithID:[comment ident] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:@{@"sender" : sender} completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; | ||||
} | } | ||||
%new | |||||
-(void) completeUndeleteCommentAction:(NSDictionary *) data{ | |||||
%new | |||||
- (void)completeUndeleteCommentAction:(NSDictionary *)data { | |||||
id comment = [[self node] comment]; | id comment = [[self node] comment]; | ||||
NSString *body = data[@"body"]; | NSString *body = data[@"body"]; | ||||
NSString *bodyHTML = [%c(MMMarkdown) HTMLStringWithMarkdown:body extensions:MMMarkdownExtensionsGitHubFlavored error:nil]; | NSString *bodyHTML = [%c(MMMarkdown) HTMLStringWithMarkdown:body extensions:MMMarkdownExtensionsGitHubFlavored error:nil]; | ||||
[comment setAuthor:data[@"author"]]; | [comment setAuthor:data[@"author"]]; | ||||
[comment setBody:body]; | [comment setBody:body]; | ||||
[comment setBodyHTML:bodyHTML]; | [comment setBodyHTML:bodyHTML]; | ||||
[[self delegate] respondToStyleChange]; | [[self delegate] respondToStyleChange]; | ||||
[data[@"sender"] setEnabled:YES]; | [data[@"sender"] setEnabled:YES]; | ||||
} | } | ||||
%new | |||||
-(void) didTapPostUndeleteButton:(id) sender { | |||||
%new | |||||
- (void)didTapPostUndeleteButton:(id)sender { | |||||
[sender setEnabled:NO]; | [sender setEnabled:NO]; | ||||
id post = [[self node] post]; | id post = [[self node] post]; | ||||
[%c(TFHelper) getUndeleteDataWithID:[post ident] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:@{@"sender" : sender} completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; | [%c(TFHelper) getUndeleteDataWithID:[post ident] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:@{@"sender" : sender} completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; | ||||
} | } | ||||
%new | %new | ||||
-(void) completeUndeletePostAction:(NSDictionary *) data{ | |||||
- (void)completeUndeletePostAction:(NSDictionary *)data { | |||||
id post = [[self node] post]; | id post = [[self node] post]; | ||||
id postComment = [[self node] comment]; //Don't know why he used a comment to store info about a post, but it exists | id postComment = [[self node] comment]; //Don't know why he used a comment to store info about a post, but it exists | ||||
NSString *body = data[@"body"]; | NSString *body = data[@"body"]; | ||||
NSString *bodyHTML = [%c(MMMarkdown) HTMLStringWithMarkdown:body extensions:MMMarkdownExtensionsGitHubFlavored error:nil]; | NSString *bodyHTML = [%c(MMMarkdown) HTMLStringWithMarkdown:body extensions:MMMarkdownExtensionsGitHubFlavored error:nil]; | ||||
[post setAuthor:data[@"author"]]; | [post setAuthor:data[@"author"]]; | ||||
[post setSelftext:body]; | [post setSelftext:body]; | ||||
[postComment setBodyHTML:bodyHTML]; | [postComment setBodyHTML:bodyHTML]; | ||||
[[self delegate] respondToStyleChange]; | [[self delegate] respondToStyleChange]; | ||||
[data[@"sender"] setEnabled:YES]; | [data[@"sender"] setEnabled:YES]; | ||||
} | } | ||||
static void loadPrefs(){ | static void loadPrefs(){ | ||||
NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/User/Library/Preferences/com.lint.undelete.prefs.plist"]; | NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/User/Library/Preferences/com.lint.undelete.prefs.plist"]; | ||||
if (prefs){ | if (prefs){ | ||||
if ([prefs objectForKey:@"isAlienBlueEnabled"] != nil){ | |||||
isAlienBlueEnabled = [[prefs objectForKey:@"isAlienBlueEnabled"] boolValue]; | |||||
} else { | |||||
isAlienBlueEnabled = YES; | |||||
} | |||||
if ([prefs objectForKey:@"isTFDeletedOnly"] != nil){ | |||||
isTFDeletedOnly = [[prefs objectForKey:@"isTFDeletedOnly"] boolValue]; | |||||
} else { | |||||
isTFDeletedOnly = YES; | |||||
} | |||||
if ([prefs objectForKey:@"requestTimeoutValue"] != nil){ | |||||
pushshiftRequestTimeoutValue = [[prefs objectForKey:@"requestTimeoutValue"] doubleValue]; | |||||
} else { | |||||
pushshiftRequestTimeoutValue = 10; | |||||
} | |||||
isEnabled = [prefs objectForKey:@"isEnabled"] ? [[prefs objectForKey:@"isEnabled"] boolValue] : YES; | |||||
isAlienBlueEnabled = [prefs objectForKey:@"isAlienBlueEnabled"] ? [[prefs objectForKey:@"isAlienBlueEnabled"] boolValue] : YES; | |||||
isTFDeletedOnly = [prefs objectForKey:@"isTFDeletedOnly"] ? [[prefs objectForKey:@"isTFDeletedOnly"] boolValue] : YES; | |||||
pushshiftRequestTimeoutValue = [prefs objectForKey:@"requestTimeoutValue"] ? [[prefs objectForKey:@"requestTimeoutValue"] doubleValue] : 10; | |||||
} else { | } else { | ||||
isEnabled = YES; | |||||
isAlienBlueEnabled = YES; | isAlienBlueEnabled = YES; | ||||
isTFDeletedOnly = YES; | isTFDeletedOnly = YES; | ||||
pushshiftRequestTimeoutValue = 10; | pushshiftRequestTimeoutValue = 10; | ||||
} | |||||
} | |||||
} | } | ||||
static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { | static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { | ||||
%ctor { | %ctor { | ||||
loadPrefs(); | loadPrefs(); | ||||
NSString* processName = [[NSProcessInfo processInfo] processName]; | NSString* processName = [[NSProcessInfo processInfo] processName]; | ||||
if ([processName isEqualToString:@"AlienBlue"]){ | |||||
if (isAlienBlueEnabled){ | |||||
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, prefsChanged, CFSTR("com.lint.undelete.prefs.changed"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); | |||||
if ([processName isEqualToString:@"AlienBlue"]){ | |||||
if (isAlienBlueEnabled && isEnabled){ | |||||
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)prefsChanged, CFSTR("com.lint.undelete.prefs.changed"), NULL, CFNotificationSuspensionBehaviorCoalesce); | |||||
%init(AlienBlue); | %init(AlienBlue); | ||||
} | } | ||||
} | } |
@interface RCCommentCell : NSObject | @interface RCCommentCell : NSObject | ||||
@property(strong, nonatomic) id comment; | @property(strong, nonatomic) id comment; | ||||
-(void) updateWithModelObject:(id) arg1; | |||||
- (void)updateWithModelObject:(id)arg1; | |||||
@end | @end | ||||
@interface RCPostCommentsController | @interface RCPostCommentsController | ||||
@property(strong, nonatomic) id postCommentsCollector; | @property(strong, nonatomic) id postCommentsCollector; | ||||
@property(strong, nonatomic) id delegate; | @property(strong, nonatomic) id delegate; | ||||
@property(strong, nonatomic) NSMutableDictionary *commentHeightCache; | @property(strong, nonatomic) NSMutableDictionary *commentHeightCache; | ||||
-(void) controllerWillChangeContent:(id) arg1; | |||||
-(void) controllerDidChangeContent:(id) arg1; | |||||
-(void) controller:(id) arg1 didChange:(id) arg2 at:(id) arg3 for:(long long) arg4 newIndexPath:(id) arg5; | |||||
- (void)controllerWillChangeContent:(id)arg1; | |||||
- (void)controllerDidChangeContent:(id)arg1; | |||||
- (void)controller:(id)arg1 didChange:(id)arg2 at:(id)arg3 for:(long long)arg4 newIndexPath:(id)arg5; | |||||
//custom elements | //custom elements | ||||
-(void)handleUndeleteCommentAction; | |||||
- (void)handleUndeleteCommentAction; | |||||
@end | @end | ||||
@interface AHKActionSheet | @interface AHKActionSheet | ||||
@property(strong, nonatomic) NSMutableArray *items; | @property(strong, nonatomic) NSMutableArray *items; | ||||
-(void) addButtonWithTitle:(id) arg1 image:(id) arg2 type:(long long) arg3 handler:(id) arg4; | |||||
- (void)addButtonWithTitle:(id)arg1 image:(id)arg2 type:(long long)arg3 handler:(id)arg4; | |||||
@end | @end | ||||
@interface AHKActionSheetItem | @interface AHKActionSheetItem | ||||
@property(strong, nonatomic) NSNumber *isSelf; | @property(strong, nonatomic) NSNumber *isSelf; | ||||
@property(strong, nonatomic) NSString *itemId; | @property(strong, nonatomic) NSString *itemId; | ||||
@property(strong, nonatomic) id selfCommentText; | @property(strong, nonatomic) id selfCommentText; | ||||
-(BOOL) isSelfPost; | |||||
- (BOOL)isSelfPost; | |||||
@end | @end | ||||
@interface RCPostActionsSectionHeader : UIView | @interface RCPostActionsSectionHeader : UIView | ||||
@interface RCPostHeaderCellController : NSObject | @interface RCPostHeaderCellController : NSObject | ||||
@property(strong, nonatomic) id post; | @property(strong, nonatomic) id post; | ||||
@property(strong, nonatomic) UITableView *tableView; | @property(strong, nonatomic) UITableView *tableView; | ||||
-(void) loadView; | |||||
- (void)loadView; | |||||
//custom elements | //custom elements | ||||
-(void) handleUndeletePostAction:(id) arg1; | |||||
- (void)handleUndeletePostAction:(id)arg1; | |||||
@end | @end |
#import "assets/TFHelper.h" | #import "assets/TFHelper.h" | ||||
#import "assets/MMMarkdown/MMMarkdown.h" | #import "assets/MMMarkdown/MMMarkdown.h" | ||||
static BOOL isEnabled; | |||||
static BOOL isAntennaEnabled; | static BOOL isAntennaEnabled; | ||||
static BOOL isTFDeletedOnly; | static BOOL isTFDeletedOnly; | ||||
static CGFloat pushshiftRequestTimeoutValue; | static CGFloat pushshiftRequestTimeoutValue; | ||||
%hook RCCommentSwift | %hook RCCommentSwift | ||||
-(BOOL) isCommentDeleted{ | |||||
- (BOOL)isCommentDeleted{ | |||||
return NO; | return NO; | ||||
} | } | ||||
%hook RCPostCommentsController | %hook RCPostCommentsController | ||||
-(void) didLongPressCell:(id) arg1 gesture:(id) arg2 { | |||||
- (void)didLongPressCell:(id)arg1 gesture:(id)arg2 { | |||||
NSString *commentBody = [[[arg1 comment] commentText] body]; | NSString *commentBody = [[[arg1 comment] commentText] body]; | ||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]){ | if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]){ | ||||
tfAntennaController = self; | tfAntennaController = self; | ||||
tfAntennaCommentCell = arg1; | tfAntennaCommentCell = arg1; | ||||
shouldHaveAntennaUndeleteAction = YES; | shouldHaveAntennaUndeleteAction = YES; | ||||
} | } | ||||
%orig; | %orig; | ||||
shouldHaveAntennaUndeleteAction = NO; | shouldHaveAntennaUndeleteAction = NO; | ||||
} | } | ||||
%new | %new | ||||
-(void) handleUndeleteCommentAction{ | |||||
- (void)handleUndeleteCommentAction{ | |||||
[%c(TFHelper) getUndeleteDataWithID:[[tfAntennaCommentCell comment] itemId] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; | [%c(TFHelper) getUndeleteDataWithID:[[tfAntennaCommentCell comment] itemId] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; | ||||
} | } | ||||
%new | %new | ||||
-(void) completeUndeleteCommentAction:(NSDictionary *) data{ | |||||
- (void)completeUndeleteCommentAction:(NSDictionary *)data { | |||||
id comment = [tfAntennaCommentCell comment]; | id comment = [tfAntennaCommentCell comment]; | ||||
id commentText = [comment commentText]; | id commentText = [comment commentText]; | ||||
NSString *body = data[@"body"]; | NSString *body = data[@"body"]; | ||||
[comment setAuthor:data[@"author"]]; | [comment setAuthor:data[@"author"]]; | ||||
[commentText setBody:body]; | [commentText setBody:body]; | ||||
[commentText setBodyHTML:[%c(MMMarkdown) HTMLStringWithMarkdown:body extensions:MMMarkdownExtensionsGitHubFlavored error:nil]]; | [commentText setBodyHTML:[%c(MMMarkdown) HTMLStringWithMarkdown:body extensions:MMMarkdownExtensionsGitHubFlavored error:nil]]; | ||||
[commentText setBodyAttributedString:nil]; | [commentText setBodyAttributedString:nil]; | ||||
[commentText setBodyAttributedStringForPreview:nil]; | [commentText setBodyAttributedStringForPreview:nil]; | ||||
[commentText setTextHeightCache:nil]; | [commentText setTextHeightCache:nil]; | ||||
[self setCommentHeightCache:nil]; | [self setCommentHeightCache:nil]; | ||||
[tfAntennaCommentCell updateWithModelObject:comment]; | [tfAntennaCommentCell updateWithModelObject:comment]; | ||||
[[[self delegate] tableView] reloadData]; | [[[self delegate] tableView] reloadData]; | ||||
} | } | ||||
%end | %end | ||||
%hook AHKActionSheet | |||||
%hook AHKActionSheet | |||||
- (void)show { | |||||
if (shouldHaveAntennaUndeleteAction) { | |||||
-(void)show{ | |||||
if (shouldHaveAntennaUndeleteAction){ | |||||
UIImage *undeleteImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; | UIImage *undeleteImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; | ||||
AHKActionSheetItem *actionItem = [self items][0]; | AHKActionSheetItem *actionItem = [self items][0]; | ||||
CGSize actionItemImageSize = [[actionItem image] size]; | CGSize actionItemImageSize = [[actionItem image] size]; | ||||
CGSize newUndeleteImageSize = CGSizeMake(actionItemImageSize.width * 2, actionItemImageSize.height * 2); | CGSize newUndeleteImageSize = CGSizeMake(actionItemImageSize.width * 2, actionItemImageSize.height * 2); | ||||
UIGraphicsBeginImageContext(newUndeleteImageSize); | UIGraphicsBeginImageContext(newUndeleteImageSize); | ||||
[undeleteImage drawInRect:CGRectMake(0, 0, newUndeleteImageSize.width, newUndeleteImageSize.height)]; | [undeleteImage drawInRect:CGRectMake(0, 0, newUndeleteImageSize.width, newUndeleteImageSize.height)]; | ||||
undeleteImage = UIGraphicsGetImageFromCurrentImageContext(); | |||||
undeleteImage = UIGraphicsGetImageFromCurrentImageContext(); | |||||
UIGraphicsEndImageContext(); | UIGraphicsEndImageContext(); | ||||
undeleteImage = [[UIImage alloc] initWithCGImage:[undeleteImage CGImage] scale:2 orientation:UIImageOrientationUp]; | undeleteImage = [[UIImage alloc] initWithCGImage:[undeleteImage CGImage] scale:2 orientation:UIImageOrientationUp]; | ||||
[self addButtonWithTitle:@"TF did that say?" image:undeleteImage type:0 handler:^{[tfAntennaController handleUndeleteCommentAction];}]; | [self addButtonWithTitle:@"TF did that say?" image:undeleteImage type:0 handler:^{[tfAntennaController handleUndeleteCommentAction];}]; | ||||
} | } | ||||
%hook RCPostActionsSectionHeader | %hook RCPostActionsSectionHeader | ||||
%property(strong, nonatomic) UIButton *undeleteButton; | %property(strong, nonatomic) UIButton *undeleteButton; | ||||
-(void) layoutSubviews{ | |||||
- (void)layoutSubviews { | |||||
BOOL isAbleToUndeletePost = NO; | BOOL isAbleToUndeletePost = NO; | ||||
id post = [[self delegate] postInternal]; | id post = [[self delegate] postInternal]; | ||||
NSString *postBody = [[post selfCommentText] body]; | NSString *postBody = [[post selfCommentText] body]; | ||||
if ([post isSelfPost]){ | if ([post isSelfPost]){ | ||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]){ | if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]){ | ||||
isAbleToUndeletePost = YES; | isAbleToUndeletePost = YES; | ||||
NSMutableArray *barButtons = [self defaultHeaderButtons]; | NSMutableArray *barButtons = [self defaultHeaderButtons]; | ||||
if ([barButtons count] <= 5){ | if ([barButtons count] <= 5){ | ||||
UIView *tempView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)]; | UIView *tempView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)]; | ||||
[barButtons addObject:tempView]; | [barButtons addObject:tempView]; | ||||
} | } | ||||
%orig; | %orig; | ||||
if (![self undeleteButton]){ | if (![self undeleteButton]){ | ||||
UIButton *undeleteButton = [UIButton buttonWithType:UIButtonTypeCustom]; | UIButton *undeleteButton = [UIButton buttonWithType:UIButtonTypeCustom]; | ||||
[undeleteButton addTarget:[[self delegate] headerCellController] action:@selector(handleUndeletePostAction:) forControlEvents:UIControlEventTouchUpInside]; | [undeleteButton addTarget:[[self delegate] headerCellController] action:@selector(handleUndeletePostAction:) forControlEvents:UIControlEventTouchUpInside]; | ||||
[undeleteButton setImage:[[UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; | [undeleteButton setImage:[[UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; | ||||
undeleteButton.imageView.contentMode = UIViewContentModeScaleAspectFit; | undeleteButton.imageView.contentMode = UIViewContentModeScaleAspectFit; | ||||
undeleteButton.tintColor = [barButtons[4] defaultColor]; | undeleteButton.tintColor = [barButtons[4] defaultColor]; | ||||
[self addSubview:undeleteButton]; | [self addSubview:undeleteButton]; | ||||
[self setUndeleteButton:undeleteButton]; | [self setUndeleteButton:undeleteButton]; | ||||
} | } | ||||
[[self undeleteButton] setFrame:[barButtons[[barButtons count] - 1] frame]]; | [[self undeleteButton] setFrame:[barButtons[[barButtons count] - 1] frame]]; | ||||
} | } | ||||
} | } | ||||
if (!isAbleToUndeletePost){ | if (!isAbleToUndeletePost){ | ||||
%orig; | %orig; | ||||
} | } | ||||
%hook RCPostHeaderCellController | %hook RCPostHeaderCellController | ||||
%new | %new | ||||
-(void) handleUndeletePostAction:(id) sender{ | |||||
- (void)handleUndeletePostAction:(id)sender { | |||||
[sender setEnabled:NO]; | [sender setEnabled:NO]; | ||||
[%c(TFHelper) getUndeleteDataWithID:[[self post] itemId] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:@{@"sender" : sender} completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; | [%c(TFHelper) getUndeleteDataWithID:[[self post] itemId] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:@{@"sender" : sender} completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; | ||||
} | } | ||||
%new | %new | ||||
-(void) completeUndeletePostAction:(NSDictionary *) data{ | |||||
- (void)completeUndeletePostAction:(NSDictionary *)data { | |||||
id post = [self post]; | id post = [self post]; | ||||
id postText = [post selfCommentText]; | id postText = [post selfCommentText]; | ||||
NSString *body = data[@"body"]; | NSString *body = data[@"body"]; | ||||
[post setAuthor:data[@"author"]]; | [post setAuthor:data[@"author"]]; | ||||
[postText setBody:body]; | [postText setBody:body]; | ||||
[postText setBodyHTML:[%c(MMMarkdown) HTMLStringWithMarkdown:body extensions:MMMarkdownExtensionsGitHubFlavored error:nil]]; | [postText setBodyHTML:[%c(MMMarkdown) HTMLStringWithMarkdown:body extensions:MMMarkdownExtensionsGitHubFlavored error:nil]]; | ||||
[postText setBodyAttributedString:nil]; | [postText setBodyAttributedString:nil]; | ||||
[postText setBodyAttributedStringForPreview:nil]; | [postText setBodyAttributedStringForPreview:nil]; | ||||
[postText setTextHeightCache:nil]; | [postText setTextHeightCache:nil]; | ||||
[self loadView]; | [self loadView]; | ||||
[[self tableView] reloadData]; | [[self tableView] reloadData]; | ||||
[data[@"sender"] setEnabled:YES]; | [data[@"sender"] setEnabled:YES]; | ||||
} | } | ||||
static void loadPrefs(){ | static void loadPrefs(){ | ||||
NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/User/Library/Preferences/com.lint.undelete.prefs.plist"]; | NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/User/Library/Preferences/com.lint.undelete.prefs.plist"]; | ||||
if (prefs){ | if (prefs){ | ||||
if ([prefs objectForKey:@"isAntennaEnabled"] != nil){ | |||||
isAntennaEnabled = [[prefs objectForKey:@"isAntennaEnabled"] boolValue]; | |||||
} else { | |||||
isAntennaEnabled = YES; | |||||
} | |||||
if ([prefs objectForKey:@"isTFDeletedOnly"] != nil){ | |||||
isTFDeletedOnly = [[prefs objectForKey:@"isTFDeletedOnly"] boolValue]; | |||||
} else { | |||||
isTFDeletedOnly = YES; | |||||
} | |||||
if ([prefs objectForKey:@"requestTimeoutValue"] != nil){ | |||||
pushshiftRequestTimeoutValue = [[prefs objectForKey:@"requestTimeoutValue"] doubleValue]; | |||||
} else { | |||||
pushshiftRequestTimeoutValue = 10; | |||||
} | |||||
isEnabled = [prefs objectForKey:@"isEnabled"] ? [[prefs objectForKey:@"isEnabled"] boolValue] : YES; | |||||
isAntennaEnabled = [prefs objectForKey:@"isAntennaEnabled"] ? [[prefs objectForKey:@"isAntennaEnabled"] boolValue] : YES; | |||||
isTFDeletedOnly = [prefs objectForKey:@"isTFDeletedOnly"] ? [[prefs objectForKey:@"isTFDeletedOnly"] boolValue] : YES; | |||||
pushshiftRequestTimeoutValue = [prefs objectForKey:@"requestTimeoutValue"] ? [[prefs objectForKey:@"requestTimeoutValue"] doubleValue] : 10; | |||||
} else { | } else { | ||||
isEnabled = YES; | |||||
isAntennaEnabled = YES; | isAntennaEnabled = YES; | ||||
isTFDeletedOnly = YES; | isTFDeletedOnly = YES; | ||||
pushshiftRequestTimeoutValue = 10; | pushshiftRequestTimeoutValue = 10; | ||||
} | |||||
} | |||||
} | } | ||||
static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { | static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { | ||||
%ctor{ | %ctor{ | ||||
loadPrefs(); | loadPrefs(); | ||||
NSString* processName = [[NSProcessInfo processInfo] processName]; | NSString* processName = [[NSProcessInfo processInfo] processName]; | ||||
if ([processName isEqualToString:@"amrc"]){ | if ([processName isEqualToString:@"amrc"]){ | ||||
if (isAntennaEnabled){ | |||||
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, prefsChanged, CFSTR("com.lint.undelete.prefs.changed"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); | |||||
if (isAntennaEnabled && isEnabled){ | |||||
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)prefsChanged, CFSTR("com.lint.undelete.prefs.changed"), NULL, CFNotificationSuspensionBehaviorCoalesce); | |||||
%init(Antenna, RCCommentSwift = objc_getClass("amrc.RCCommentSwift"), RCPostSwift = objc_getClass("amrc.RCPostSwift"), RCCommentTextSwift = objc_getClass("amrc.RCCommentTextSwift")); | %init(Antenna, RCCommentSwift = objc_getClass("amrc.RCCommentSwift"), RCPostSwift = objc_getClass("amrc.RCPostSwift"), RCCommentTextSwift = objc_getClass("amrc.RCCommentTextSwift")); | ||||
} | } | ||||
} | } |
@interface CommentCellNode | @interface CommentCellNode | ||||
@property(assign,nonatomic)id view; | @property(assign,nonatomic)id view; | ||||
-(BOOL) isSelected; | |||||
-(void) _layoutSublayouts; | |||||
-(void) didLoad; | |||||
-(void) calculatedLayoutDidChange; | |||||
- (BOOL)isSelected; | |||||
- (void)_layoutSublayouts; | |||||
- (void)didLoad; | |||||
- (void)calculatedLayoutDidChange; | |||||
//custom elements | //custom elements | ||||
@property(strong,nonatomic) UIButton *undeleteButton; | @property(strong,nonatomic) UIButton *undeleteButton; | ||||
-(void) undeleteCellWasSelected; | |||||
- (void)undeleteCellWasSelected; | |||||
@end | @end | ||||
/* -- Post Interfaces -- */ | /* -- Post Interfaces -- */ | ||||
@property(assign,nonatomic) NSString *selfText; | @property(assign,nonatomic) NSString *selfText; | ||||
@property(assign,nonatomic) NSString *author; | @property(assign,nonatomic) NSString *author; | ||||
@property(assign,nonatomic) NSString *fullName; | @property(assign,nonatomic) NSString *fullName; | ||||
-(BOOL) isSelfPost; | |||||
- (BOOL)isSelfPost; | |||||
//custom elements | //custom elements | ||||
@property(strong, nonatomic) NSString *undeleteAuthor; | @property(strong, nonatomic) NSString *undeleteAuthor; | ||||
@property(assign,nonatomic) NSString *selfText; | @property(assign,nonatomic) NSString *selfText; | ||||
@property(assign,nonatomic) NSString *author; | @property(assign,nonatomic) NSString *author; | ||||
@property(assign,nonatomic) NSString *fullName; | @property(assign,nonatomic) NSString *fullName; | ||||
-(BOOL) isSelfPost; | |||||
- (BOOL)isSelfPost; | |||||
//custom elements | //custom elements | ||||
@property(strong, nonatomic) NSString *undeleteAuthor; | @property(strong, nonatomic) NSString *undeleteAuthor; | ||||
//custom elements | //custom elements | ||||
@property(strong, nonatomic) id headerCellNode; | @property(strong, nonatomic) id headerCellNode; | ||||
-(void) undeleteCellWasSelected; | |||||
- (void)undeleteCellWasSelected; | |||||
@end | @end | ||||
/* -- Other Interfaces -- */ | /* -- Other Interfaces -- */ | ||||
@interface MarkdownRenderer | @interface MarkdownRenderer | ||||
+(id) attributedStringFromMarkdown:(id) arg1 withAttributes:(id) arg2; | |||||
+ (id)attributedStringFromMarkdown:(id)arg1 withAttributes:(id)arg2; | |||||
@end | @end | ||||
@interface ActionController | @interface ActionController | ||||
-(id) tableView:(id) arg1 cellForRowAtIndexPath:(NSIndexPath *)arg2; | |||||
-(NSInteger) tableView:(id) arg1 numberOfRowsInSection:(NSInteger) arg2; | |||||
- (id)tableView:(id)arg1 cellForRowAtIndexPath:(NSIndexPath *)arg2; | |||||
- (NSInteger)tableView:(id)arg1 numberOfRowsInSection:(NSInteger)arg2; | |||||
@end | @end | ||||
@interface UIImage (ios13) | @interface UIImage (ios13) | ||||
@property(assign,nonatomic)id image; | @property(assign,nonatomic)id image; | ||||
@property(assign,nonatomic) CGRect frame; | @property(assign,nonatomic) CGRect frame; | ||||
@property(assign,nonatomic) id view; | @property(assign,nonatomic) id view; | ||||
-(CGRect)_frameInWindow; | |||||
- (CGRect)_frameInWindow; | |||||
@end | @end | ||||
@interface ASTextNode | @interface ASTextNode | ||||
@interface ApolloButtonNode | @interface ApolloButtonNode | ||||
@property(assign,nonatomic) ASTextNode *titleNode; | @property(assign,nonatomic) ASTextNode *titleNode; | ||||
-(void) setAttributedTitle:(id) arg1 forState:(NSInteger) arg2; | |||||
-(id) attributedTitleForState:(NSInteger) arg1; | |||||
- (void) setAttributedTitle:(id)arg1 forState:(NSInteger)arg2; | |||||
- (id) attributedTitleForState:(NSInteger)arg1; | |||||
@end | @end |
#import "Apollo.h" | #import "Apollo.h" | ||||
#import "assets/TFHelper.h" | #import "assets/TFHelper.h" | ||||
static BOOL isTFDeletedOnly; | |||||
static BOOL isEnabled; | |||||
static BOOL isApolloEnabled; | static BOOL isApolloEnabled; | ||||
static BOOL isTFDeletedOnly; | |||||
static CGFloat pushshiftRequestTimeoutValue; | static CGFloat pushshiftRequestTimeoutValue; | ||||
static BOOL shouldApolloHaveButton; | static BOOL shouldApolloHaveButton; | ||||
%hook MarkdownRenderer | %hook MarkdownRenderer | ||||
+(id) attributedStringFromHTML:(id)arg1 attributes:(id) arg2 compact:(BOOL) arg3{ | |||||
+ (id)attributedStringFromHTML:(id)arg1 attributes:(id)arg2 compact:(BOOL)arg3 { | |||||
apolloBodyAttributes = [arg2 copy]; | apolloBodyAttributes = [arg2 copy]; | ||||
return %orig; | return %orig; | ||||
} | } | ||||
%hook ActionController | %hook ActionController | ||||
-(id) tableView:(id) arg1 cellForRowAtIndexPath:(NSIndexPath *) arg2{ | |||||
if (shouldAddUndeleteCell){ | |||||
- (id) tableView:(id)arg1 cellForRowAtIndexPath:(NSIndexPath *)arg2 { | |||||
if (shouldAddUndeleteCell) { | |||||
if ([arg2 row] == [self tableView:arg1 numberOfRowsInSection:0] - 1){ | if ([arg2 row] == [self tableView:arg1 numberOfRowsInSection:0] - 1){ | ||||
id undeleteCell = [arg1 dequeueReusableCellWithIdentifier:@"IconActionCell" forIndexPath:arg2]; | id undeleteCell = [arg1 dequeueReusableCellWithIdentifier:@"IconActionCell" forIndexPath:arg2]; | ||||
id prevCell = [arg1 dequeueReusableCellWithIdentifier:@"IconActionCell"]; | id prevCell = [arg1 dequeueReusableCellWithIdentifier:@"IconActionCell"]; | ||||
UIImageView *prevCellImageView = MSHookIvar<UIImageView *>(prevCell, "iconImageView"); | UIImageView *prevCellImageView = MSHookIvar<UIImageView *>(prevCell, "iconImageView"); | ||||
CGSize prevImageSize = [[prevCellImageView image] size]; | CGSize prevImageSize = [[prevCellImageView image] size]; | ||||
UIImage *undeleteImage; | |||||
if (@available(iOS 13.0, *)){ | |||||
UIImage *undeleteImage; | |||||
//if (@available(iOS 13.0, *)){ | |||||
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"13.0")) { | |||||
undeleteImage = [UIImage systemImageNamed:@"eye"]; | undeleteImage = [UIImage systemImageNamed:@"eye"]; | ||||
if (!undeleteImage){ | if (!undeleteImage){ | ||||
undeleteImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; | undeleteImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; | ||||
} else { | |||||
CGSize squareSize = CGSizeMake(undeleteImage.size.width, undeleteImage.size.width); | |||||
UIGraphicsBeginImageContextWithOptions(squareSize, NO, 0); | |||||
[undeleteImage drawInRect:CGRectMake(0, (squareSize.height - undeleteImage.size.height) / 2, squareSize.width, undeleteImage.size.height)]; | |||||
undeleteImage = UIGraphicsGetImageFromCurrentImageContext(); | |||||
UIGraphicsEndImageContext(); | |||||
} | } | ||||
} else { | } else { | ||||
undeleteImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; | undeleteImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; | ||||
} | } | ||||
CGFloat undeleteImageSizeValue = prevImageSize.width > prevImageSize.height ? prevImageSize.width : prevImageSize.height; | CGFloat undeleteImageSizeValue = prevImageSize.width > prevImageSize.height ? prevImageSize.width : prevImageSize.height; | ||||
if (undeleteImageSizeValue == 0){ | |||||
if (undeleteImageSizeValue == 0) { | |||||
undeleteImageSizeValue = 25; | undeleteImageSizeValue = 25; | ||||
} | } | ||||
UIGraphicsBeginImageContextWithOptions(CGSizeMake(undeleteImageSizeValue, undeleteImageSizeValue), NO, 0); | UIGraphicsBeginImageContextWithOptions(CGSizeMake(undeleteImageSizeValue, undeleteImageSizeValue), NO, 0); | ||||
[undeleteImage drawInRect:CGRectMake(0, 0, undeleteImageSizeValue, undeleteImageSizeValue)]; | [undeleteImage drawInRect:CGRectMake(0, 0, undeleteImageSizeValue, undeleteImageSizeValue)]; | ||||
undeleteImage = [UIGraphicsGetImageFromCurrentImageContext() imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; | undeleteImage = [UIGraphicsGetImageFromCurrentImageContext() imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; | ||||
UIGraphicsEndImageContext(); | UIGraphicsEndImageContext(); | ||||
UILabel *undeleteLabel = MSHookIvar<UILabel *>(undeleteCell, "actionTitleLabel"); | UILabel *undeleteLabel = MSHookIvar<UILabel *>(undeleteCell, "actionTitleLabel"); | ||||
UIImageView *undeleteImageView = MSHookIvar<UIImageView *>(undeleteCell, "iconImageView"); | UIImageView *undeleteImageView = MSHookIvar<UIImageView *>(undeleteCell, "iconImageView"); | ||||
undeleteLabel.text = @"TF Did That Say?"; | undeleteLabel.text = @"TF Did That Say?"; | ||||
undeleteImageView.image = undeleteImage; | undeleteImageView.image = undeleteImage; | ||||
return undeleteCell; | return undeleteCell; | ||||
} | } | ||||
} | } | ||||
return %orig; | |||||
return %orig; | |||||
} | } | ||||
-(void) tableView:(id) arg1 didSelectRowAtIndexPath:(NSIndexPath *)arg2{ | |||||
if (shouldAddUndeleteCell){ | |||||
- (void)tableView:(id)arg1 didSelectRowAtIndexPath:(NSIndexPath *)arg2 { | |||||
if (shouldAddUndeleteCell) { | |||||
if ([arg2 row] == [self tableView:arg1 numberOfRowsInSection:0] - 1){ | if ([arg2 row] == [self tableView:arg1 numberOfRowsInSection:0] - 1){ | ||||
if (apolloCommentCell){ | |||||
if (apolloCommentCell) { | |||||
[apolloCommentCell undeleteCellWasSelected]; | [apolloCommentCell undeleteCellWasSelected]; | ||||
} else { | } else { | ||||
[apolloCommentController undeleteCellWasSelected]; | [apolloCommentController undeleteCellWasSelected]; | ||||
} | } | ||||
} | } | ||||
} | |||||
} | |||||
%orig; | %orig; | ||||
} | } | ||||
-(NSInteger) tableView:(id) arg1 numberOfRowsInSection:(NSInteger) arg2{ | |||||
- (NSInteger) tableView:(id)arg1 numberOfRowsInSection:(NSInteger)arg2 { | |||||
if (shouldAddUndeleteCell){ | if (shouldAddUndeleteCell){ | ||||
return %orig + 1; | return %orig + 1; | ||||
} else { | } else { | ||||
} | } | ||||
} | } | ||||
-(id) animationControllerForDismissedController:(id) arg1{ | |||||
- (id) animationControllerForDismissedController:(id)arg1 { | |||||
shouldAddUndeleteCell = NO; | shouldAddUndeleteCell = NO; | ||||
return %orig; | return %orig; | ||||
} | } | ||||
%hook CommentCellNode | %hook CommentCellNode | ||||
%property(strong,nonatomic) UIButton *undeleteButton; | %property(strong,nonatomic) UIButton *undeleteButton; | ||||
-(void) moreOptionsTappedWithSender:(id) arg1{ | |||||
- (void)moreOptionsTappedWithSender:(id)arg1 { | |||||
if (!shouldApolloHaveButton){ | if (!shouldApolloHaveButton){ | ||||
NSString *commentBody = [MSHookIvar<RKComment *>(self, "comment") body]; | NSString *commentBody = [MSHookIvar<RKComment *>(self, "comment") body]; | ||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]){ | if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]){ | ||||
shouldAddUndeleteCell = YES; | shouldAddUndeleteCell = YES; | ||||
apolloCommentCell = self; | apolloCommentCell = self; | ||||
apolloCommentController = nil; | apolloCommentController = nil; | ||||
} | |||||
} | |||||
} | } | ||||
%orig; | %orig; | ||||
} | } | ||||
-(void) longPressedWithGestureRecognizer:(id) arg1{ | |||||
- (void)longPressedWithGestureRecognizer:(id)arg1 { | |||||
if (!shouldApolloHaveButton){ | if (!shouldApolloHaveButton){ | ||||
NSString *commentBody = [MSHookIvar<RKComment *>(self, "comment") body]; | NSString *commentBody = [MSHookIvar<RKComment *>(self, "comment") body]; | ||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]){ | if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]){ | ||||
shouldAddUndeleteCell = YES; | shouldAddUndeleteCell = YES; | ||||
apolloCommentCell = self; | apolloCommentCell = self; | ||||
apolloCommentController = nil; | apolloCommentController = nil; | ||||
} | } | ||||
} | } | ||||
%orig; | %orig; | ||||
} | } | ||||
-(void) didLoad { | |||||
- (void)didLoad { | |||||
%orig; | %orig; | ||||
if (shouldApolloHaveButton){ | if (shouldApolloHaveButton){ | ||||
NSString *commentBody = [MSHookIvar<RKComment *>(self, "comment") body]; | NSString *commentBody = [MSHookIvar<RKComment *>(self, "comment") body]; | ||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]){ | if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]){ | ||||
CGFloat imageSize = 20.0f; | CGFloat imageSize = 20.0f; | ||||
UIButton *undeleteButton = [UIButton buttonWithType:UIButtonTypeCustom]; | UIButton *undeleteButton = [UIButton buttonWithType:UIButtonTypeCustom]; | ||||
[undeleteButton addTarget:self action:@selector(didTapUndeleteButton:) forControlEvents:UIControlEventTouchUpInside]; | [undeleteButton addTarget:self action:@selector(didTapUndeleteButton:) forControlEvents:UIControlEventTouchUpInside]; | ||||
undeleteButton.frame = CGRectMake(0, 0, imageSize, imageSize); | undeleteButton.frame = CGRectMake(0, 0, imageSize, imageSize); | ||||
UIImage* undeleteImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; | UIImage* undeleteImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; | ||||
[undeleteButton setImage:undeleteImage forState:UIControlStateNormal]; | [undeleteButton setImage:undeleteImage forState:UIControlStateNormal]; | ||||
} | } | ||||
} | } | ||||
-(void) _layoutSublayouts{ | |||||
- (void)_layoutSublayouts { | |||||
%orig; | %orig; | ||||
if (shouldApolloHaveButton){ | if (shouldApolloHaveButton){ | ||||
if ([self undeleteButton]){ | if ([self undeleteButton]){ | ||||
CGFloat imageSize = 20.0f; | CGFloat imageSize = 20.0f; | ||||
id moreNode = MSHookIvar<id>(self, "moreOptionsNode"); | id moreNode = MSHookIvar<id>(self, "moreOptionsNode"); | ||||
} | } | ||||
%new | %new | ||||
-(void) didTapUndeleteButton:(id) sender{ | |||||
- (void)didTapUndeleteButton:(id)sender { | |||||
[sender setEnabled:NO]; | [sender setEnabled:NO]; | ||||
id comment = MSHookIvar<id>(self, "comment"); | id comment = MSHookIvar<id>(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:@{@"sender" : sender} completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; | ||||
} | } | ||||
%new | %new | ||||
-(void) undeleteCellWasSelected{ | |||||
- (void)undeleteCellWasSelected { | |||||
RKComment *comment = MSHookIvar<RKComment *>(self, "comment"); | RKComment *comment = MSHookIvar<RKComment *>(self, "comment"); | ||||
[%c(TFHelper) getUndeleteDataWithID:[[comment fullName] componentsSeparatedByString:@"_"][1] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; | [%c(TFHelper) getUndeleteDataWithID:[[comment fullName] componentsSeparatedByString:@"_"][1] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; | ||||
} | } | ||||
%new | %new | ||||
-(void) completeUndeleteCommentAction:(NSDictionary *) data{ | |||||
- (void)completeUndeleteCommentAction:(NSDictionary *)data { | |||||
RKComment *comment = MSHookIvar<RKComment *>(self, "comment"); | RKComment *comment = MSHookIvar<RKComment *>(self, "comment"); | ||||
id bodyNode = MSHookIvar<id>(self, "bodyNode"); | id bodyNode = MSHookIvar<id>(self, "bodyNode"); | ||||
id authorNode = MSHookIvar<id>(self, "authorNode"); | id authorNode = MSHookIvar<id>(self, "authorNode"); | ||||
NSString *author = data[@"author"]; | NSString *author = data[@"author"]; | ||||
NSString *body = data[@"body"]; | NSString *body = data[@"body"]; | ||||
[comment setAuthor:author]; | [comment setAuthor:author]; | ||||
[comment setBody:body]; | [comment setBody:body]; | ||||
NSAttributedString *prevAuthorAttributedString = [authorNode attributedTitleForState:UIControlStateNormal]; | NSAttributedString *prevAuthorAttributedString = [authorNode attributedTitleForState:UIControlStateNormal]; | ||||
NSDictionary *authorStringAttributes = [prevAuthorAttributedString attributesAtIndex:0 longestEffectiveRange:nil inRange:NSMakeRange(0, [prevAuthorAttributedString length])]; | 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:author attributes:authorStringAttributes]; | ||||
[authorNode setAttributedTitle:newAuthorAttributedString forState:UIControlStateNormal]; | [authorNode setAttributedTitle:newAuthorAttributedString forState:UIControlStateNormal]; | ||||
[bodyNode setAttributedString:[%c(MarkdownRenderer) attributedStringFromMarkdown:body withAttributes:apolloBodyAttributes]]; | [bodyNode setAttributedString:[%c(MarkdownRenderer) attributedStringFromMarkdown:body withAttributes:apolloBodyAttributes]]; | ||||
if ([data objectForKey:@"sender"]) { | if ([data objectForKey:@"sender"]) { | ||||
[data[@"sender"] setEnabled:YES]; | [data[@"sender"] setEnabled:YES]; | ||||
} | } | ||||
%hook CommentsViewController | %hook CommentsViewController | ||||
%property(strong, nonatomic) id headerCellNode; | |||||
%property(strong, nonatomic) id headerCellNode; | |||||
- (void)moreOptionsBarButtonItemTappedWithSender:(id)arg1 { | |||||
-(void) moreOptionsBarButtonItemTappedWithSender:(id) arg1{ | |||||
RKLink *post = MSHookIvar<RKLink *>(self, "link"); | RKLink *post = MSHookIvar<RKLink *>(self, "link"); | ||||
NSString *postBody = [post selfText]; | NSString *postBody = [post selfText]; | ||||
if ([post isSelfPost]){ | if ([post isSelfPost]){ | ||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]){ | if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]){ | ||||
shouldAddUndeleteCell = YES; | shouldAddUndeleteCell = YES; | ||||
apolloCommentController = self; | apolloCommentController = self; | ||||
} | } | ||||
} | } | ||||
%orig; | %orig; | ||||
} | } | ||||
%new | %new | ||||
-(void) undeleteCellWasSelected{ | |||||
- (void)undeleteCellWasSelected { | |||||
RKLink *post = MSHookIvar<RKLink *>(self, "link"); | RKLink *post = MSHookIvar<RKLink *>(self, "link"); | ||||
[%c(TFHelper) getUndeleteDataWithID:[[post fullName] componentsSeparatedByString:@"_"][1] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; | [%c(TFHelper) getUndeleteDataWithID:[[post fullName] componentsSeparatedByString:@"_"][1] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; | ||||
} | } | ||||
%new | %new | ||||
-(void) completeUndeletePostAction:(NSDictionary *) data{ | |||||
- (void)completeUndeletePostAction:(NSDictionary *)data { | |||||
RKLink *post = MSHookIvar<RKLink *>(self, "link"); | RKLink *post = MSHookIvar<RKLink *>(self, "link"); | ||||
id headerCellNode = [self headerCellNode]; | id headerCellNode = [self headerCellNode]; | ||||
id bodyNode = MSHookIvar<id>(headerCellNode, "bodyNode"); | id bodyNode = MSHookIvar<id>(headerCellNode, "bodyNode"); | ||||
id postInfoNode = MSHookIvar<id>(headerCellNode, "postInfoNode"); | id postInfoNode = MSHookIvar<id>(headerCellNode, "postInfoNode"); | ||||
id authorNode = MSHookIvar<id>(postInfoNode, "authorButtonNode"); | id authorNode = MSHookIvar<id>(postInfoNode, "authorButtonNode"); | ||||
NSString *author = data[@"author"]; | NSString *author = data[@"author"]; | ||||
NSString *authorTextString = [NSString stringWithFormat:@"by %@", author]; | NSString *authorTextString = [NSString stringWithFormat:@"by %@", author]; | ||||
NSString *body = data[@"body"]; | NSString *body = data[@"body"]; | ||||
[post setUndeleteAuthor:author]; | [post setUndeleteAuthor:author]; | ||||
[post setSelfText:body]; | [post setSelfText:body]; | ||||
NSAttributedString *prevAuthorAttributedString = [authorNode attributedTitleForState:UIControlStateNormal]; | NSAttributedString *prevAuthorAttributedString = [authorNode attributedTitleForState:UIControlStateNormal]; | ||||
NSDictionary *authorStringAttributes = [prevAuthorAttributedString attributesAtIndex:0 longestEffectiveRange:nil inRange:NSMakeRange(0, [prevAuthorAttributedString length])]; | NSDictionary *authorStringAttributes = [prevAuthorAttributedString attributesAtIndex:0 longestEffectiveRange:nil inRange:NSMakeRange(0, [prevAuthorAttributedString length])]; | ||||
NSAttributedString* newAuthorAttributedString = [[NSAttributedString alloc] initWithString:authorTextString attributes:authorStringAttributes]; | NSAttributedString* newAuthorAttributedString = [[NSAttributedString alloc] initWithString:authorTextString attributes:authorStringAttributes]; | ||||
%hook CommentsHeaderCellNode | %hook CommentsHeaderCellNode | ||||
-(void) didLoad{ | |||||
- (void)didLoad { | |||||
%orig; | %orig; | ||||
[[self closestViewController] setHeaderCellNode:self]; | [[self closestViewController] setHeaderCellNode:self]; | ||||
} | } | ||||
-(void) _layoutSublayouts{ | |||||
- (void)_layoutSublayouts { | |||||
%orig; | %orig; | ||||
[[self closestViewController] setHeaderCellNode:self]; | [[self closestViewController] setHeaderCellNode:self]; | ||||
} | } | ||||
-(void) longPressedWithGestureRecognizer:(id) arg1{ | |||||
- (void)longPressedWithGestureRecognizer:(id)arg1 { | |||||
RKLink *post = MSHookIvar<RKLink *>(self, "link"); | RKLink *post = MSHookIvar<RKLink *>(self, "link"); | ||||
NSString *postBody = [post selfText]; | NSString *postBody = [post selfText]; | ||||
if ([post isSelfPost]){ | |||||
if ([post isSelfPost]) { | |||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]){ | if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]){ | ||||
shouldAddUndeleteCell = YES; | shouldAddUndeleteCell = YES; | ||||
apolloCommentCell = nil; | apolloCommentCell = nil; | ||||
apolloCommentController = self; | apolloCommentController = self; | ||||
} | } | ||||
} | } | ||||
%orig; | %orig; | ||||
} | } | ||||
static void loadPrefs(){ | static void loadPrefs(){ | ||||
NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/User/Library/Preferences/com.lint.undelete.prefs.plist"]; | NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/User/Library/Preferences/com.lint.undelete.prefs.plist"]; | ||||
if (prefs){ | |||||
if ([prefs objectForKey:@"isApolloEnabled"] != nil) { | |||||
isApolloEnabled = [[prefs objectForKey:@"isApolloEnabled"] boolValue]; | |||||
} else { | |||||
isApolloEnabled = YES; | |||||
} | |||||
if ([prefs objectForKey:@"isTFDeletedOnly"] != nil) { | |||||
isTFDeletedOnly = [[prefs objectForKey:@"isTFDeletedOnly"] boolValue]; | |||||
} else { | |||||
isTFDeletedOnly = YES; | |||||
} | |||||
if ([prefs objectForKey:@"requestTimeoutValue"] != nil){ | |||||
pushshiftRequestTimeoutValue = [[prefs objectForKey:@"requestTimeoutValue"] doubleValue]; | |||||
} else { | |||||
pushshiftRequestTimeoutValue = 10; | |||||
} | |||||
if ([prefs objectForKey:@"shouldApolloHaveButton"] != nil){ | |||||
shouldApolloHaveButton = [[prefs objectForKey:@"shouldApolloHaveButton"] boolValue]; | |||||
} else { | |||||
shouldApolloHaveButton = NO; | |||||
} | |||||
if (prefs){ | |||||
isEnabled = [prefs objectForKey:@"isEnabled"] ? [[prefs objectForKey:@"isEnabled"] boolValue] : YES; | |||||
isApolloEnabled = [prefs objectForKey:@"isApolloEnabled"] ? [[prefs objectForKey:@"isApolloEnabled"] boolValue] : YES; | |||||
isTFDeletedOnly = [prefs objectForKey:@"isTFDeletedOnly"] ? [[prefs objectForKey:@"isTFDeletedOnly"] boolValue] : YES; | |||||
pushshiftRequestTimeoutValue = [prefs objectForKey:@"requestTimeoutValue"] ? [[prefs objectForKey:@"requestTimeoutValue"] doubleValue] : 10; | |||||
shouldApolloHaveButton = [prefs objectForKey:@"shouldApolloHaveButton"] ? [[prefs objectForKey:@"shouldApolloHaveButton"] boolValue] : NO; | |||||
} else { | } else { | ||||
isEnabled = YES; | |||||
isApolloEnabled = YES; | isApolloEnabled = YES; | ||||
isTFDeletedOnly = YES; | isTFDeletedOnly = YES; | ||||
pushshiftRequestTimeoutValue = 10; | pushshiftRequestTimeoutValue = 10; | ||||
shouldApolloHaveButton = NO; | shouldApolloHaveButton = NO; | ||||
} | |||||
} | |||||
} | } | ||||
static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { | static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { | ||||
%ctor { | %ctor { | ||||
loadPrefs(); | loadPrefs(); | ||||
NSString* processName = [[NSProcessInfo processInfo] processName]; | NSString* processName = [[NSProcessInfo processInfo] processName]; | ||||
if ([processName isEqualToString:@"Apollo"]){ | if ([processName isEqualToString:@"Apollo"]){ | ||||
if (isApolloEnabled){ | |||||
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, prefsChanged, CFSTR("com.lint.undelete.prefs.changed"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); | |||||
if (isApolloEnabled && isEnabled){ | |||||
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)prefsChanged, CFSTR("com.lint.undelete.prefs.changed"), NULL, CFNotificationSuspensionBehaviorCoalesce); | |||||
%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")); | %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")); | ||||
} | } | ||||
} | } |
/* -- Votable Interfaces -- */ | /* -- Votable Interfaces -- */ | ||||
@interface BRVotable | |||||
@interface BRVotable | |||||
@property(strong, nonatomic) NSString *serverID; | @property(strong, nonatomic) NSString *serverID; | ||||
@property(strong, nonatomic) NSAttributedString *attributedDescriptionString; | @property(strong, nonatomic) NSAttributedString *attributedDescriptionString; | ||||
@property(assign, nonatomic) CGSize cellSize; | @property(assign, nonatomic) CGSize cellSize; | ||||
@interface StoryDetailView | @interface StoryDetailView | ||||
@property(strong, nonatomic) UITableView *tableView; | @property(strong, nonatomic) UITableView *tableView; | ||||
-(void) refreshTouched; | |||||
- (void)refreshTouched; | |||||
@end | @end | ||||
@interface StoryDetailViewController | @interface StoryDetailViewController | ||||
@property(strong, nonatomic) id detailPage; | @property(strong, nonatomic) id detailPage; | ||||
//custom elements | //custom elements | ||||
-(void) handleUndeleteCommentAction; | |||||
-(void) handleUndeletePostAction; | |||||
- (void)handleUndeleteCommentAction; | |||||
- (void)handleUndeletePostAction; | |||||
@end | @end | ||||
/* -- Other Interfaces -- */ | /* -- Other Interfaces -- */ | ||||
@interface BRUtils | @interface BRUtils | ||||
+(id) attributedDescriptionForComment:(id) arg1; | |||||
+(id) createAttributedStringFromHTML:(id) arg1 options:(id) arg2; | |||||
+ (id)attributedDescriptionForComment:(id)arg1; | |||||
+ (id)createAttributedStringFromHTML:(id)arg1 options:(id)arg2; | |||||
@end | @end |
#import "assets/TFHelper.h" | #import "assets/TFHelper.h" | ||||
#import "assets/MMMarkdown/MMMarkdown.h" | #import "assets/MMMarkdown/MMMarkdown.h" | ||||
static BOOL isEnabled; | |||||
static BOOL isBaconReaderEnabled; | static BOOL isBaconReaderEnabled; | ||||
static BOOL isTFDeletedOnly; | static BOOL isTFDeletedOnly; | ||||
static CGFloat pushshiftRequestTimeoutValue; | static CGFloat pushshiftRequestTimeoutValue; | ||||
%hook BRComment | %hook BRComment | ||||
-(BOOL) contains_htmlValue{ | |||||
- (BOOL)contains_htmlValue { | |||||
return YES; | return YES; | ||||
} | |||||
} | |||||
-(BOOL) primitiveContains_htmlValue{ | |||||
- (BOOL)primitiveContains_htmlValue { | |||||
return YES; | return YES; | ||||
} | } | ||||
-(BOOL) is_deletedValue{ | |||||
- (BOOL)is_deletedValue { | |||||
return NO; | return NO; | ||||
} | } | ||||
-(BOOL) primitiveIs_deletedValue{ | |||||
- (BOOL)primitiveIs_deletedValue { | |||||
return NO; | return NO; | ||||
} | } | ||||
%hook BRStory | %hook BRStory | ||||
+(id) storyWithDictionary:(id) arg1 inContext:(id) arg2 { | |||||
+ (id)storyWithDictionary:(id)arg1 inContext:(id)arg2 { | |||||
id orig = %orig; | id orig = %orig; | ||||
if (tfPostSelftext){ | |||||
if (tfPostSelftext) { | |||||
[orig setSelftext_html:tfPostSelftext]; | [orig setSelftext_html:tfPostSelftext]; | ||||
[orig setAuthor:tfPostAuthor]; | [orig setAuthor:tfPostAuthor]; | ||||
tfPostSelftext = nil; | tfPostSelftext = nil; | ||||
tfPostAuthor = nil; | tfPostAuthor = nil; | ||||
} | } | ||||
return orig; | return orig; | ||||
} | } | ||||
%hook UIViewController | %hook UIViewController | ||||
-(void) presentViewController:(id) arg1 animated:(BOOL) arg2 completion:(id) arg3 { | |||||
if ([arg1 isKindOfClass:[UIAlertController class]] && shouldHaveBRUndeleteAction){ | |||||
- (void)presentViewController:(id)arg1 animated:(BOOL)arg2 completion:(id)arg3 { | |||||
if ([arg1 isKindOfClass:[UIAlertController class]] && shouldHaveBRUndeleteAction) { | |||||
UIAlertAction *undeleteAction; | UIAlertAction *undeleteAction; | ||||
if (tfCommentCellView){ | |||||
if (tfCommentCellView) { | |||||
undeleteAction = [UIAlertAction actionWithTitle:@"TF Did That Say?" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){[tfStoryController handleUndeleteCommentAction];}]; | undeleteAction = [UIAlertAction actionWithTitle:@"TF Did That Say?" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){[tfStoryController handleUndeleteCommentAction];}]; | ||||
} else { | } else { | ||||
undeleteAction = [UIAlertAction actionWithTitle:@"TF Did That Say?" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){[tfStoryController handleUndeletePostAction];}]; | undeleteAction = [UIAlertAction actionWithTitle:@"TF Did That Say?" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){[tfStoryController handleUndeletePostAction];}]; | ||||
} | } | ||||
[arg1 addAction:undeleteAction]; | [arg1 addAction:undeleteAction]; | ||||
} | } | ||||
%orig; | %orig; | ||||
} | } | ||||
%hook StoryDetailViewController | %hook StoryDetailViewController | ||||
-(void) showMoreCommentActions:(id) arg1 showAll:(BOOL) arg2 { | |||||
- (void)showMoreCommentActions:(id)arg1 showAll:(BOOL)arg2 { | |||||
NSString *commentBody = [[arg1 comment] body]; | NSString *commentBody = [[arg1 comment] body]; | ||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]){ | |||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]) { | |||||
shouldHaveBRUndeleteAction = YES; | shouldHaveBRUndeleteAction = YES; | ||||
tfCommentCellView = arg1; | tfCommentCellView = arg1; | ||||
tfStoryController = self; | tfStoryController = self; | ||||
tfPostSelftext = nil; | tfPostSelftext = nil; | ||||
} | } | ||||
%orig; | %orig; | ||||
shouldHaveBRUndeleteAction = NO; | shouldHaveBRUndeleteAction = NO; | ||||
} | } | ||||
-(void) menuTouchedWithSender:(id) arg1 { | |||||
if ([[self story] is_selfValue]){ | |||||
- (void)menuTouchedWithSender:(id)arg1 { | |||||
if ([[self story] is_selfValue]) { | |||||
NSString *postBody = [[self story] selftext]; | NSString *postBody = [[self story] selftext]; | ||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]){ | |||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]) { | |||||
shouldHaveBRUndeleteAction = YES; | shouldHaveBRUndeleteAction = YES; | ||||
tfCommentCellView = nil; | tfCommentCellView = nil; | ||||
tfStoryController = self; | tfStoryController = self; | ||||
tfPostSelftext = nil; | tfPostSelftext = nil; | ||||
} | } | ||||
} | } | ||||
%orig; | %orig; | ||||
shouldHaveBRUndeleteAction = NO; | shouldHaveBRUndeleteAction = NO; | ||||
} | } | ||||
%new | %new | ||||
-(void) handleUndeleteCommentAction{ | |||||
- (void)handleUndeleteCommentAction { | |||||
[%c(TFHelper) getUndeleteDataWithID:[[tfCommentCellView comment] serverID] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; | [%c(TFHelper) getUndeleteDataWithID:[[tfCommentCellView comment] serverID] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; | ||||
} | } | ||||
%new | %new | ||||
-(void) completeUndeleteCommentAction:(NSDictionary *) data{ | |||||
- (void)completeUndeleteCommentAction:(NSDictionary *)data { | |||||
id comment = [tfCommentCellView comment]; | id comment = [tfCommentCellView comment]; | ||||
NSString *body = data[@"body"]; | NSString *body = data[@"body"]; | ||||
[comment setAuthor:data[@"author"]]; | [comment setAuthor:data[@"author"]]; | ||||
[comment setBody:body]; | [comment setBody:body]; | ||||
[comment setBody_html:[%c(MMMarkdown) HTMLStringWithMarkdown:body extensions:MMMarkdownExtensionsGitHubFlavored error:nil]]; | [comment setBody_html:[%c(MMMarkdown) HTMLStringWithMarkdown:body extensions:MMMarkdownExtensionsGitHubFlavored error:nil]]; | ||||
[comment setAttributedDescriptionString:nil]; | [comment setAttributedDescriptionString:nil]; | ||||
NSAttributedString *commentAttrString = [%c(BRUtils) attributedDescriptionForComment:comment]; | NSAttributedString *commentAttrString = [%c(BRUtils) attributedDescriptionForComment:comment]; | ||||
[comment setAttributedDescriptionString:commentAttrString]; | [comment setAttributedDescriptionString:commentAttrString]; | ||||
[[[self detailPage] tableView] reloadData]; | [[[self detailPage] tableView] reloadData]; | ||||
} | } | ||||
%new | %new | ||||
-(void) handleUndeletePostAction{ | |||||
- (void)handleUndeletePostAction { | |||||
[%c(TFHelper) getUndeleteDataWithID:[[self story] serverID] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; | [%c(TFHelper) getUndeleteDataWithID:[[self story] serverID] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; | ||||
} | } | ||||
%new | %new | ||||
-(void) completeUndeletePostAction:(NSDictionary *) data{ | |||||
- (void)completeUndeletePostAction:(NSDictionary *)data { | |||||
tfPostAuthor = data[@"author"]; | tfPostAuthor = data[@"author"]; | ||||
tfPostSelftext = [%c(MMMarkdown) HTMLStringWithMarkdown:data[@"body"] extensions:MMMarkdownExtensionsGitHubFlavored error:nil]; | tfPostSelftext = [%c(MMMarkdown) HTMLStringWithMarkdown:data[@"body"] extensions:MMMarkdownExtensionsGitHubFlavored error:nil]; | ||||
[[self detailPage] refreshTouched]; | [[self detailPage] refreshTouched]; | ||||
} | } | ||||
static void loadPrefs(){ | static void loadPrefs(){ | ||||
NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/User/Library/Preferences/com.lint.undelete.prefs.plist"]; | NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/User/Library/Preferences/com.lint.undelete.prefs.plist"]; | ||||
if (prefs){ | if (prefs){ | ||||
if ([prefs objectForKey:@"isBaconReaderEnabled"] != nil){ | |||||
isBaconReaderEnabled = [[prefs objectForKey:@"isBaconReaderEnabled"] boolValue]; | |||||
} else { | |||||
isBaconReaderEnabled = YES; | |||||
} | |||||
if ([prefs objectForKey:@"isTFDeletedOnly"] != nil) { | |||||
isTFDeletedOnly = [[prefs objectForKey:@"isTFDeletedOnly"] boolValue]; | |||||
} else { | |||||
isTFDeletedOnly = YES; | |||||
} | |||||
if ([prefs objectForKey:@"requestTimeoutValue"] != nil){ | |||||
pushshiftRequestTimeoutValue = [[prefs objectForKey:@"requestTimeoutValue"] doubleValue]; | |||||
} else { | |||||
pushshiftRequestTimeoutValue = 10; | |||||
} | |||||
isEnabled = [prefs objectForKey:@"isEnabled"] ? [[prefs objectForKey:@"isEnabled"] boolValue] : YES; | |||||
isBaconReaderEnabled = [prefs objectForKey:@"isBaconReaderEnabled"] ? [[prefs objectForKey:@"isBaconReaderEnabled"] boolValue] : YES; | |||||
isTFDeletedOnly = [prefs objectForKey:@"isTFDeletedOnly"] ? [[prefs objectForKey:@"isTFDeletedOnly"] boolValue] : YES; | |||||
pushshiftRequestTimeoutValue = [prefs objectForKey:@"requestTimeoutValue"] ? [[prefs objectForKey:@"requestTimeoutValue"] doubleValue] : 10; | |||||
} else { | } else { | ||||
isEnabled = YES; | |||||
isBaconReaderEnabled = YES; | isBaconReaderEnabled = YES; | ||||
isTFDeletedOnly = YES; | isTFDeletedOnly = YES; | ||||
pushshiftRequestTimeoutValue = 10; | pushshiftRequestTimeoutValue = 10; | ||||
} | |||||
} | |||||
} | } | ||||
static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { | static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { | ||||
%ctor { | %ctor { | ||||
loadPrefs(); | loadPrefs(); | ||||
NSString* processName = [[NSProcessInfo processInfo] processName]; | NSString* processName = [[NSProcessInfo processInfo] processName]; | ||||
if ([processName isEqualToString:@"BaconReader"]){ | |||||
if (isBaconReaderEnabled){ | |||||
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, prefsChanged, CFSTR("com.lint.undelete.prefs.changed"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); | |||||
if ([processName isEqualToString:@"BaconReader"]){ | |||||
if (isBaconReaderEnabled && isEnabled){ | |||||
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)prefsChanged, CFSTR("com.lint.undelete.prefs.changed"), NULL, CFNotificationSuspensionBehaviorCoalesce); | |||||
%init(BaconReader, StoryDetailView = objc_getClass("BaconReader.StoryDetailView"), StoryDetailViewController = objc_getClass("BaconReader.StoryDetailViewController"), CommentCellView = objc_getClass("BaconReader.CommentCellView"), CommentCell = objc_getClass("BaconReader.CommentCell")); | %init(BaconReader, StoryDetailView = objc_getClass("BaconReader.StoryDetailView"), StoryDetailViewController = objc_getClass("BaconReader.StoryDetailViewController"), CommentCellView = objc_getClass("BaconReader.CommentCellView"), CommentCell = objc_getClass("BaconReader.CommentCell")); | ||||
} | } | ||||
} | } | ||||
} | |||||
} |
@property(strong, nonatomic) id authorButton; | @property(strong, nonatomic) id authorButton; | ||||
@property(assign, nonatomic) BOOL isCollapsed; | @property(assign, nonatomic) BOOL isCollapsed; | ||||
@property(assign, nonatomic) BOOL commentDidChange; | @property(assign, nonatomic) BOOL commentDidChange; | ||||
-(void) reloadContents; | |||||
- (void)reloadContents; | |||||
//custom elements | //custom elements | ||||
@property(strong, nonatomic) UIButton *undeleteButton; | @property(strong, nonatomic) UIButton *undeleteButton; | ||||
@end | @end | ||||
@interface PostSelfTextPartCell | @interface PostSelfTextPartCell | ||||
-(id) _viewControllerForAncestor; | |||||
- (id)_viewControllerForAncestor; | |||||
@end | @end | ||||
@interface PostMetadataView | @interface PostMetadataView |
#import "Beam.h" | #import "Beam.h" | ||||
#import "assets/TFHelper.h" | #import "assets/TFHelper.h" | ||||
static BOOL isEnabled; | |||||
static BOOL isBeamEnabled; | static BOOL isBeamEnabled; | ||||
static BOOL isTFDeletedOnly; | static BOOL isTFDeletedOnly; | ||||
static CGFloat pushshiftRequestTimeoutValue; | static CGFloat pushshiftRequestTimeoutValue; | ||||
%hook CommentCell | %hook CommentCell | ||||
%property(strong, nonatomic) UIButton *undeleteButton; | %property(strong, nonatomic) UIButton *undeleteButton; | ||||
-(void) layoutSubviews{ | |||||
- (void)layoutSubviews { | |||||
%orig; | %orig; | ||||
UIButton *undeleteButton = [self undeleteButton]; | UIButton *undeleteButton = [self undeleteButton]; | ||||
if (undeleteButton){ | |||||
if ([self isCollapsed]){ | |||||
if (undeleteButton) { | |||||
if ([self isCollapsed]) { | |||||
[undeleteButton setHidden:YES]; | [undeleteButton setHidden:YES]; | ||||
} else { | } else { | ||||
[undeleteButton setHidden:NO]; | [undeleteButton setHidden:NO]; | ||||
} | } | ||||
} else { | } else { | ||||
NSString *commentBody = [[self comment] content]; | NSString *commentBody = [[self comment] content]; | ||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]){ | |||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]) { | |||||
CGFloat authorTextHeight = [[self authorButton] frame].size.height; | CGFloat authorTextHeight = [[self authorButton] frame].size.height; | ||||
undeleteButton = [UIButton buttonWithType:UIButtonTypeCustom]; | undeleteButton = [UIButton buttonWithType:UIButtonTypeCustom]; | ||||
[undeleteButton addTarget:self action:@selector(handleUndeleteCommentAction:) forControlEvents:UIControlEventTouchUpInside]; | [undeleteButton addTarget:self action:@selector(handleUndeleteCommentAction:) forControlEvents:UIControlEventTouchUpInside]; | ||||
[undeleteButton setImage:[UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"] forState:UIControlStateNormal]; | [undeleteButton setImage:[UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"] forState:UIControlStateNormal]; | ||||
undeleteButton.imageView.contentMode = UIViewContentModeScaleAspectFit; | undeleteButton.imageView.contentMode = UIViewContentModeScaleAspectFit; | ||||
undeleteButton.imageEdgeInsets = UIEdgeInsetsMake(5, 5, 5, 5); | undeleteButton.imageEdgeInsets = UIEdgeInsetsMake(5, 5, 5, 5); | ||||
undeleteButton.frame = CGRectMake([[UIScreen mainScreen] bounds].size.width - authorTextHeight - 5, 5, authorTextHeight, authorTextHeight); | undeleteButton.frame = CGRectMake([[UIScreen mainScreen] bounds].size.width - authorTextHeight - 5, 5, authorTextHeight, authorTextHeight); | ||||
[[self commentContentView] addSubview:undeleteButton]; | [[self commentContentView] addSubview:undeleteButton]; | ||||
[self setUndeleteButton:undeleteButton]; | [self setUndeleteButton:undeleteButton]; | ||||
} | } | ||||
} | } | ||||
%new | %new | ||||
-(void) handleUndeleteCommentAction:(id) sender{ | |||||
- (void)handleUndeleteCommentAction:(id)sender { | |||||
[sender setEnabled:NO]; | [sender setEnabled:NO]; | ||||
[%c(TFHelper) getUndeleteDataWithID:[[self comment] identifier] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:@{@"sender" : sender} completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; | [%c(TFHelper) getUndeleteDataWithID:[[self comment] identifier] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:@{@"sender" : sender} completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; | ||||
} | } | ||||
%new | %new | ||||
-(void) completeUndeleteCommentAction:(NSDictionary *) data{ | |||||
- (void)completeUndeleteCommentAction:(NSDictionary *)data { | |||||
id comment = [self comment]; | id comment = [self comment]; | ||||
[comment setAuthor:data[@"author"]]; | [comment setAuthor:data[@"author"]]; | ||||
[comment setContent:data[@"body"]]; | [comment setContent:data[@"body"]]; | ||||
[comment setMarkdownString:nil]; | [comment setMarkdownString:nil]; | ||||
[self setCommentDidChange:YES]; | [self setCommentDidChange:YES]; | ||||
[self reloadContents]; | [self reloadContents]; | ||||
[[MSHookIvar<id>(self, "delegate") tableView] reloadData]; | [[MSHookIvar<id>(self, "delegate") tableView] reloadData]; | ||||
[data[@"sender"] setEnabled:YES]; | [data[@"sender"] setEnabled:YES]; | ||||
} | } | ||||
%hook PostSelfTextPartCell | %hook PostSelfTextPartCell | ||||
-(void) setSelected:(BOOL) arg1 animated:(BOOL) arg2{ | |||||
- (void)setSelected:(BOOL)arg1 animated:(BOOL)arg2{ | |||||
%orig; | %orig; | ||||
id postViewController = [self _viewControllerForAncestor]; | id postViewController = [self _viewControllerForAncestor]; | ||||
if ([postViewController isMemberOfClass:objc_getClass("beam.PostDetailEmbeddedViewController")]){ | |||||
if ([postViewController isMemberOfClass:objc_getClass("beam.PostDetailEmbeddedViewController")]) { | |||||
[postViewController setSelfTextView:self]; | [postViewController setSelfTextView:self]; | ||||
[postViewController setPost:[self post]]; | [postViewController setPost:[self post]]; | ||||
} | } | ||||
%hook PostMetadataView | %hook PostMetadataView | ||||
-(void) layoutSubviews{ | |||||
- (void)layoutSubviews { | |||||
%orig; | %orig; | ||||
id postViewController = MSHookIvar<id>(self, "delegate"); | id postViewController = MSHookIvar<id>(self, "delegate"); | ||||
if ([postViewController isMemberOfClass:objc_getClass("beam.PostDetailEmbeddedViewController")]){ | |||||
if ([postViewController isMemberOfClass:objc_getClass("beam.PostDetailEmbeddedViewController")]) { | |||||
[postViewController setMetadataView:self]; | [postViewController setMetadataView:self]; | ||||
} | } | ||||
} | } | ||||
%hook PostToolbarView | %hook PostToolbarView | ||||
%property(strong, nonatomic) UIButton *undeleteButton; | %property(strong, nonatomic) UIButton *undeleteButton; | ||||
-(void) layoutSubviews{ | |||||
- (void)layoutSubviews { | |||||
%orig; | %orig; | ||||
if (![self undeleteButton] && [[[self post] isSelfText] boolValue] && [MSHookIvar<id>(self, "delegate") isMemberOfClass:objc_getClass("beam.PostDetailEmbeddedViewController")]){ | |||||
if (![self undeleteButton] && [[[self post] isSelfText] boolValue] && [MSHookIvar<id>(self, "delegate") isMemberOfClass:objc_getClass("beam.PostDetailEmbeddedViewController")]) { | |||||
NSString *postBody = [[self post] content]; | NSString *postBody = [[self post] content]; | ||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]){ | |||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]) { | |||||
id moreButton = MSHookIvar<id>(self, "moreButton"); | id moreButton = MSHookIvar<id>(self, "moreButton"); | ||||
CGFloat buttonHeight = [moreButton frame].size.height; | CGFloat buttonHeight = [moreButton frame].size.height; | ||||
UIButton *undeleteButton = [UIButton buttonWithType:UIButtonTypeCustom]; | UIButton *undeleteButton = [UIButton buttonWithType:UIButtonTypeCustom]; | ||||
[undeleteButton addTarget:MSHookIvar<id>(self, "delegate") action:@selector(handleUndeletePostAction:) forControlEvents:UIControlEventTouchUpInside]; | [undeleteButton addTarget:MSHookIvar<id>(self, "delegate") action:@selector(handleUndeletePostAction:) forControlEvents:UIControlEventTouchUpInside]; | ||||
[undeleteButton setImage:[UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"] forState:UIControlStateNormal]; | [undeleteButton setImage:[UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"] forState:UIControlStateNormal]; | ||||
undeleteButton.imageView.contentMode = UIViewContentModeScaleAspectFit; | undeleteButton.imageView.contentMode = UIViewContentModeScaleAspectFit; | ||||
undeleteButton.imageEdgeInsets = UIEdgeInsetsMake(5, 5, 5, 5); | undeleteButton.imageEdgeInsets = UIEdgeInsetsMake(5, 5, 5, 5); | ||||
undeleteButton.frame = CGRectMake([moreButton frame].origin.x - buttonHeight, 1, buttonHeight, buttonHeight); | undeleteButton.frame = CGRectMake([moreButton frame].origin.x - buttonHeight, 1, buttonHeight, buttonHeight); | ||||
[self addSubview:undeleteButton]; | [self addSubview:undeleteButton]; | ||||
[self setUndeleteButton:undeleteButton]; | [self setUndeleteButton:undeleteButton]; | ||||
} | } | ||||
%property(strong, nonatomic) id post; | %property(strong, nonatomic) id post; | ||||
%new | %new | ||||
-(void) handleUndeletePostAction:(id) sender{ | |||||
- (void)handleUndeletePostAction:(id)sender { | |||||
[sender setEnabled:NO]; | [sender setEnabled:NO]; | ||||
id post = [self post]; | id post = [self post]; | ||||
if (post){ | if (post){ | ||||
[%c(TFHelper) getUndeleteDataWithID:[post identifier] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:@{@"sender" : sender} completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; | [%c(TFHelper) getUndeleteDataWithID:[post identifier] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:@{@"sender" : sender} completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; | ||||
} | } | ||||
} | } | ||||
%new | %new | ||||
-(void) completeUndeletePostAction:(NSDictionary *) data{ | |||||
- (void)completeUndeletePostAction:(NSDictionary *)data { | |||||
id post = [self post]; | id post = [self post]; | ||||
[post setAuthor:data[@"author"]]; | [post setAuthor:data[@"author"]]; | ||||
[post setContent:data[@"body"]]; | [post setContent:data[@"body"]]; | ||||
[post setMarkdownString:nil]; | [post setMarkdownString:nil]; | ||||
if ([self selfTextView]){ | |||||
if ([self selfTextView]) { | |||||
[[self selfTextView] reloadContents]; | [[self selfTextView] reloadContents]; | ||||
} | } | ||||
if ([self metadataView]){ | |||||
if ([self metadataView]) { | |||||
[[self metadataView] setPost:post]; | [[self metadataView] setPost:post]; | ||||
} | } | ||||
[[self tableView] reloadData]; | [[self tableView] reloadData]; | ||||
[data[@"sender"] setEnabled:YES]; | [data[@"sender"] setEnabled:YES]; | ||||
} | } | ||||
static void loadPrefs(){ | static void loadPrefs(){ | ||||
NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/User/Library/Preferences/com.lint.undelete.prefs.plist"]; | NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/User/Library/Preferences/com.lint.undelete.prefs.plist"]; | ||||
if (prefs){ | if (prefs){ | ||||
if ([prefs objectForKey:@"isBeamEnabled"] != nil){ | |||||
isBeamEnabled = [[prefs objectForKey:@"isBeamEnabled"] boolValue]; | |||||
} else { | |||||
isBeamEnabled = YES; | |||||
} | |||||
if ([prefs objectForKey:@"isTFDeletedOnly"] != nil) { | |||||
isTFDeletedOnly = [[prefs objectForKey:@"isTFDeletedOnly"] boolValue]; | |||||
} else { | |||||
isTFDeletedOnly = YES; | |||||
} | |||||
if ([prefs objectForKey:@"requestTimeoutValue"] != nil){ | |||||
pushshiftRequestTimeoutValue = [[prefs objectForKey:@"requestTimeoutValue"] doubleValue]; | |||||
} else { | |||||
pushshiftRequestTimeoutValue = 10; | |||||
} | |||||
isEnabled = [prefs objectForKey:@"isEnabled"] ? [[prefs objectForKey:@"isEnabled"] boolValue] : YES; | |||||
isBeamEnabled = [prefs objectForKey:@"isBeamEnabled"] ? [[prefs objectForKey:@"isBeamEnabled"] boolValue] : YES; | |||||
isTFDeletedOnly = [prefs objectForKey:@"isTFDeletedOnly"] ? [[prefs objectForKey:@"isTFDeletedOnly"] boolValue] : YES; | |||||
pushshiftRequestTimeoutValue = [prefs objectForKey:@"requestTimeoutValue"] ? [[prefs objectForKey:@"requestTimeoutValue"] doubleValue] : 10; | |||||
} else { | } else { | ||||
isEnabled = YES; | |||||
isBeamEnabled = YES; | isBeamEnabled = YES; | ||||
isTFDeletedOnly = YES; | isTFDeletedOnly = YES; | ||||
pushshiftRequestTimeoutValue = 10; | pushshiftRequestTimeoutValue = 10; | ||||
} | |||||
} | |||||
} | } | ||||
static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { | static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { | ||||
%ctor{ | %ctor{ | ||||
loadPrefs(); | loadPrefs(); | ||||
NSString* processName = [[NSProcessInfo processInfo] processName]; | NSString* processName = [[NSProcessInfo processInfo] processName]; | ||||
if ([processName isEqualToString:@"beam"]){ | |||||
if (isBeamEnabled){ | |||||
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, prefsChanged, CFSTR("com.lint.undelete.prefs.changed"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); | |||||
if ([processName isEqualToString:@"beam"]){ | |||||
if (isBeamEnabled && isEnabled){ | |||||
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)prefsChanged, CFSTR("com.lint.undelete.prefs.changed"), NULL, CFNotificationSuspensionBehaviorCoalesce); | |||||
%init(Beam, CommentCell = objc_getClass("beam.CommentCell"), PostDetailEmbeddedViewController = objc_getClass("beam.PostDetailEmbeddedViewController"), PostToolbarView = objc_getClass("beam.PostToolbarView"), PostSelfTextPartCell = objc_getClass("beam.PostSelfTextPartCell"), PostMetadataView = objc_getClass("beam.PostMetadataView")); | %init(Beam, CommentCell = objc_getClass("beam.CommentCell"), PostDetailEmbeddedViewController = objc_getClass("beam.PostDetailEmbeddedViewController"), PostToolbarView = objc_getClass("beam.PostToolbarView"), PostSelfTextPartCell = objc_getClass("beam.PostSelfTextPartCell"), PostMetadataView = objc_getClass("beam.PostMetadataView")); | ||||
} | } | ||||
} | } |
@property(assign,nonatomic) NSString* body; | @property(assign,nonatomic) NSString* body; | ||||
@property(assign,nonatomic) NSString* fullName; | @property(assign,nonatomic) NSString* fullName; | ||||
-(BOOL) isSaved; | |||||
- (BOOL)isSaved; | |||||
@end | @end | ||||
@interface NRTCommentsManager | @interface NRTCommentsManager | ||||
@property(assign,nonatomic) NSMutableArray* comments; | @property(assign,nonatomic) NSMutableArray* comments; | ||||
-(void) updateComment:(id) arg1 fromEdited:(id) arg2; | |||||
- (void)updateComment:(id)arg1 fromEdited:(id)arg2; | |||||
@end | @end | ||||
/* -- Post Interfaces -- */ | /* -- Post Interfaces -- */ | ||||
@property(assign,nonatomic) NSString* fullName; | @property(assign,nonatomic) NSString* fullName; | ||||
@end | @end | ||||
@interface NRTLinkTitleCell | |||||
-(void) configureCellForLink:(id) arg1; | |||||
@interface NRTLinkTitleCell | |||||
- (void)configureCellForLink:(id)arg1; | |||||
@end | @end | ||||
@interface NRTLinkTextCell | @interface NRTLinkTextCell | ||||
@property(assign,nonatomic) id bodyLabel; | @property(assign,nonatomic) id bodyLabel; | ||||
-(void) configureCellForText:(id) arg1 links:(id) arg2; | |||||
- (void)configureCellForText:(id)arg1 links:(id)arg2; | |||||
@end | @end | ||||
/* -- Other Interfaces -- */ | /* -- Other Interfaces -- */ | ||||
@interface NRTAuthManager | @interface NRTAuthManager | ||||
@property(assign,nonatomic) NSString* currentUsername; | @property(assign,nonatomic) NSString* currentUsername; | ||||
+(id) sharedManager; | |||||
+ (id)sharedManager; | |||||
@end | @end | ||||
@interface NRTMarkdownManager | @interface NRTMarkdownManager | ||||
+(id) attributedStringFromMarkdown:(id) arg1 type:(id) arg2; | |||||
+ (id)attributedStringFromMarkdown:(id)arg1 type:(id)arg2; | |||||
@end | @end | ||||
@interface NRTAttributedLabel | @interface NRTAttributedLabel | ||||
@property(assign,nonatomic) id linkText; | @property(assign,nonatomic) id linkText; | ||||
@property(assign,nonatomic) id tableView; | @property(assign,nonatomic) id tableView; | ||||
-(void) _handleActionSheetCopyCommentText:(id) arg1; | |||||
-(void) _handleActionSheetDeleteComment:(id) arg1; | |||||
-(void) _handleActionSheetDeletePost; | |||||
-(void) _handleActionSheetEditComment:(id) arg1; | |||||
-(void) _handleActionSheetEditPost; | |||||
-(void) _handleActionSheetOpenChrome; | |||||
-(void) _handleActionSheetOpenSafari; | |||||
-(void) _handleActionSheetPrivateMessage:(id) arg1; | |||||
-(void) _handleActionSheetRefreshComments; | |||||
-(void) _handleActionSheetRefreshPost; | |||||
-(void) _handleActionSheetReportComment:(id) arg1; | |||||
-(void) _handleActionSheetReportPost; | |||||
-(void) _handleActionSheetSaveComment:(id) arg1 index:(NSUInteger) arg2; | |||||
-(void) _handleActionSheetShareComment:(id) arg1; | |||||
-(void) _handleActionSheetShareLink; | |||||
-(void) _handleActionSheetSharePost; | |||||
-(void) _handleActionSheetSortComments; | |||||
-(void) _handleActionSheetUnsaveComment:(id) arg1 index:(NSUInteger) arg2; | |||||
-(void) _handleActionSheetViewParent:(id) arg1; | |||||
-(void) _handleActionSheetViewProfile:(id) arg1; | |||||
- (void)_handleActionSheetCopyCommentText:(id)arg1; | |||||
- (void)_handleActionSheetDeleteComment:(id)arg1; | |||||
- (void)_handleActionSheetDeletePost; | |||||
- (void)_handleActionSheetEditComment:(id)arg1; | |||||
- (void)_handleActionSheetEditPost; | |||||
- (void)_handleActionSheetOpenChrome; | |||||
- (void)_handleActionSheetOpenSafari; | |||||
- (void)_handleActionSheetPrivateMessage:(id)arg1; | |||||
- (void)_handleActionSheetRefreshComments; | |||||
- (void)_handleActionSheetRefreshPost; | |||||
- (void)_handleActionSheetReportComment:(id)arg1; | |||||
- (void)_handleActionSheetReportPost; | |||||
- (void)_handleActionSheetSaveComment:(id)arg1 index:(NSUInteger)arg2; | |||||
- (void)_handleActionSheetShareComment:(id)arg1; | |||||
- (void)_handleActionSheetShareLink; | |||||
- (void)_handleActionSheetSharePost; | |||||
- (void)_handleActionSheetSortComments; | |||||
- (void)_handleActionSheetUnsaveComment:(id)arg1 index:(NSUInteger)arg2; | |||||
- (void)_handleActionSheetViewParent:(id)arg1; | |||||
- (void)_handleActionSheetViewProfile:(id)arg1; | |||||
//custom elements | //custom elements | ||||
-(void) handleUndeleteAction:(id) arg1; | |||||
-(void) handleUndeletePostAction; | |||||
-(void) mainThreadTest:(id) arg1; | |||||
- (void) handleUndeleteAction:(id)arg1; | |||||
- (void) handleUndeletePostAction; | |||||
- (void) mainThreadTest:(id)arg1; | |||||
@end | @end | ||||
@interface NRTMediaTableViewDataSource | @interface NRTMediaTableViewDataSource | ||||
@property(assign,nonatomic) id commentsManager; | @property(assign,nonatomic) id commentsManager; | ||||
@property(assign,nonatomic) id parentController; | @property(assign,nonatomic) id parentController; | ||||
-(void) _handleActionSheetCopyCommentText:(id) arg1; | |||||
-(void) _handleActionSheetDeleteComment:(id) arg1; | |||||
-(void) _handleActionSheetDeletePost; | |||||
-(void) _handleActionSheetEditComment:(id) arg1; | |||||
-(void) _handleActionSheetEditPost; | |||||
-(void) _handleActionSheetOpenChrome; | |||||
-(void) _handleActionSheetOpenSafari; | |||||
-(void) _handleActionSheetPrivateMessage:(id) arg1; | |||||
-(void) _handleActionSheetRefreshComments; | |||||
-(void) _handleActionSheetRefreshPost; | |||||
-(void) _handleActionSheetReportComment:(id) arg1; | |||||
-(void) _handleActionSheetReportPost; | |||||
-(void) _handleActionSheetSaveComment:(id) arg1 index:(NSUInteger) arg2; | |||||
-(void) _handleActionSheetShareComment:(id) arg1; | |||||
-(void) _handleActionSheetShareLink; | |||||
-(void) _handleActionSheetSharePost; | |||||
-(void) _handleActionSheetSortComments; | |||||
-(void) _handleActionSheetUnsaveComment:(id) arg1 index:(NSUInteger) arg2; | |||||
-(void) _handleActionSheetViewParent:(id) arg1; | |||||
-(void) _handleActionSheetViewProfile:(id) arg1; | |||||
- (void)_handleActionSheetCopyCommentText:(id)arg1; | |||||
- (void)_handleActionSheetDeleteComment:(id)arg1; | |||||
- (void)_handleActionSheetDeletePost; | |||||
- (void)_handleActionSheetEditComment:(id)arg1; | |||||
- (void)_handleActionSheetEditPost; | |||||
- (void)_handleActionSheetOpenChrome; | |||||
- (void)_handleActionSheetOpenSafari; | |||||
- (void)_handleActionSheetPrivateMessage:(id)arg1; | |||||
- (void)_handleActionSheetRefreshComments; | |||||
- (void)_handleActionSheetRefreshPost; | |||||
- (void)_handleActionSheetReportComment:(id)arg1; | |||||
- (void)_handleActionSheetReportPost; | |||||
- (void)_handleActionSheetSaveComment:(id)arg1 index:(NSUInteger)arg2; | |||||
- (void)_handleActionSheetShareComment:(id)arg1; | |||||
- (void)_handleActionSheetShareLink; | |||||
- (void)_handleActionSheetSharePost; | |||||
- (void)_handleActionSheetSortComments; | |||||
- (void)_handleActionSheetUnsaveComment:(id)arg1 index:(NSUInteger)arg2; | |||||
- (void)_handleActionSheetViewParent:(id)arg1; | |||||
- (void)_handleActionSheetViewProfile:(id)arg1; | |||||
//custom elements | //custom elements | ||||
-(void) handleUndeleteCommentAction:(id) comment; | |||||
- (void)handleUndeleteCommentAction:(id)comment; | |||||
@end | @end | ||||
#import "Narwhal.h" | #import "Narwhal.h" | ||||
#import "assets/TFHelper.h" | #import "assets/TFHelper.h" | ||||
static BOOL isEnabled; | |||||
static BOOL isNarwhalEnabled; | static BOOL isNarwhalEnabled; | ||||
static BOOL isTFDeletedOnly; | static BOOL isTFDeletedOnly; | ||||
static CGFloat pushshiftRequestTimeoutValue; | static CGFloat pushshiftRequestTimeoutValue; | ||||
id tfComment; | id tfComment; | ||||
id tfController; | id tfController; | ||||
void getUndeleteCommentData(id controller, id comment){ | |||||
void getUndeleteCommentData(id controller, id comment){ | |||||
[%c(TFHelper) getUndeleteDataWithID:[[comment fullName] componentsSeparatedByString:@"_"][1] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:@{@"comment" : comment} completionTarget:controller completionSelector:@selector(completeUndeleteCommentAction:)]; | [%c(TFHelper) getUndeleteDataWithID:[[comment fullName] componentsSeparatedByString:@"_"][1] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:@{@"comment" : comment} completionTarget:controller completionSelector:@selector(completeUndeleteCommentAction:)]; | ||||
} | } | ||||
%hook UIViewController | %hook UIViewController | ||||
-(void) presentViewController:(id) arg1 animated:(BOOL) arg2 completion:(id) arg3{ | |||||
if ([arg1 isKindOfClass:[UIAlertController class]] && shouldHaveUndeleteAction){ | |||||
- (void)presentViewController:(id)arg1 animated:(BOOL)arg2 completion:(id)arg3 { | |||||
if ([arg1 isKindOfClass:[UIAlertController class]] && shouldHaveUndeleteAction) { | |||||
UIAlertAction* undeleteAction; | UIAlertAction* undeleteAction; | ||||
if (tfComment){ | |||||
if (tfComment) { | |||||
undeleteAction = [UIAlertAction actionWithTitle:@"tf did that say?" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){getUndeleteCommentData(tfController, tfComment);}]; | undeleteAction = [UIAlertAction actionWithTitle:@"tf did that say?" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){getUndeleteCommentData(tfController, tfComment);}]; | ||||
} else { | } else { | ||||
undeleteAction = [UIAlertAction actionWithTitle:@"tf did that say?" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){[tfController handleUndeletePostAction];}]; | undeleteAction = [UIAlertAction actionWithTitle:@"tf did that say?" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){[tfController handleUndeletePostAction];}]; | ||||
} | } | ||||
[arg1 addAction:undeleteAction]; | [arg1 addAction:undeleteAction]; | ||||
} | } | ||||
%orig; | %orig; | ||||
} | } | ||||
%hook NRTLinkViewController | %hook NRTLinkViewController | ||||
-(void) swipeCell:(id) arg1 didEndDragWithState:(NSUInteger) arg2{ | |||||
- (void)swipeCell:(id)arg1 didEndDragWithState:(NSUInteger)arg2 { | |||||
if (arg2 == 2){ | |||||
if (arg2 == 2) { | |||||
if ([arg1 isKindOfClass:[%c(NRTCommentTableViewCell) class]]) { | if ([arg1 isKindOfClass:[%c(NRTCommentTableViewCell) class]]) { | ||||
NSString *commentBody = MSHookIvar<NSString*>([arg1 comment], "_body"); | NSString *commentBody = MSHookIvar<NSString*>([arg1 comment], "_body"); | ||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]){ | if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]){ | ||||
tfComment = [arg1 comment]; | tfComment = [arg1 comment]; | ||||
tfController = self; | tfController = self; | ||||
shouldHaveUndeleteAction = YES; | shouldHaveUndeleteAction = YES; | ||||
} | } | ||||
} | |||||
} | |||||
} | |||||
} | |||||
%orig; | %orig; | ||||
shouldHaveUndeleteAction = NO; | shouldHaveUndeleteAction = NO; | ||||
} | } | ||||
-(void) _dotsButtonTouched:(id) arg1{ | |||||
if ([self linkTextOffscreenCell]){ | |||||
- (void)_dotsButtonTouched:(id)arg1 { | |||||
if ([self linkTextOffscreenCell]) { | |||||
NSString *postBody = [[self link] selfText]; | NSString *postBody = [[self link] selfText]; | ||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]){ | |||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]) { | |||||
tfController = self; | tfController = self; | ||||
tfComment = nil; | tfComment = nil; | ||||
shouldHaveUndeleteAction = YES; | shouldHaveUndeleteAction = YES; | ||||
} | } | ||||
} | } | ||||
%orig; | %orig; | ||||
shouldHaveUndeleteAction = NO; | shouldHaveUndeleteAction = NO; | ||||
} | } | ||||
%new | %new | ||||
-(void) handleUndeletePostAction{ | |||||
- (void)handleUndeletePostAction { | |||||
id post = [self link]; | id post = [self link]; | ||||
[%c(TFHelper) getUndeleteDataWithID:[[post fullName] componentsSeparatedByString:@"_"][1] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:@{@"post" : post} completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; | [%c(TFHelper) getUndeleteDataWithID:[[post fullName] componentsSeparatedByString:@"_"][1] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:@{@"post" : post} completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; | ||||
} | } | ||||
%new | |||||
-(void) completeUndeletePostAction:(NSDictionary *) data{ | |||||
%new | |||||
- (void)completeUndeletePostAction:(NSDictionary *)data { | |||||
id post = data[@"post"]; | id post = data[@"post"]; | ||||
MSHookIvar<NSString*>(post, "_author") = data[@"author"]; | MSHookIvar<NSString*>(post, "_author") = data[@"author"]; | ||||
NSAttributedString* postBodyAttributedString = [%c(NRTMarkdownManager) attributedStringFromMarkdown:data[@"body"] type:0]; | NSAttributedString* postBodyAttributedString = [%c(NRTMarkdownManager) attributedStringFromMarkdown:data[@"body"] type:0]; | ||||
[self setLinkText:postBodyAttributedString]; | [self setLinkText:postBodyAttributedString]; | ||||
[[self tableView] reloadData]; | [[self tableView] reloadData]; | ||||
} | } | ||||
%new | %new | ||||
-(void) completeUndeleteCommentAction:(NSDictionary *) data{ | |||||
- (void)completeUndeleteCommentAction:(NSDictionary *)data { | |||||
id comment = data[@"comment"]; | id comment = data[@"comment"]; | ||||
if (comment){ | |||||
if (comment) { | |||||
MSHookIvar<NSString*>(comment, "_author") = data[@"author"]; | MSHookIvar<NSString*>(comment, "_author") = data[@"author"]; | ||||
MSHookIvar<NSString*>(comment, "_body") = data[@"body"]; | MSHookIvar<NSString*>(comment, "_body") = data[@"body"]; | ||||
[[self commentsManager] updateComment:comment fromEdited:comment]; | [[self commentsManager] updateComment:comment fromEdited:comment]; | ||||
} | } | ||||
} | } | ||||
%hook NRTMediaTableViewDataSource | %hook NRTMediaTableViewDataSource | ||||
-(void) swipeCell:(id) arg1 didEndDragWithState:(NSUInteger) arg2{ | |||||
- (void)swipeCell:(id)arg1 didEndDragWithState:(NSUInteger)arg2 { | |||||
if (arg2 == 2){ | |||||
if (arg2 == 2) { | |||||
if ([arg1 isKindOfClass:[%c(NRTCommentTableViewCell) class]]) { | if ([arg1 isKindOfClass:[%c(NRTCommentTableViewCell) class]]) { | ||||
NSString *commentBody = MSHookIvar<NSString*>([arg1 comment], "_body"); | NSString *commentBody = MSHookIvar<NSString*>([arg1 comment], "_body"); | ||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]){ | |||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]) { | |||||
tfComment = [arg1 comment]; | tfComment = [arg1 comment]; | ||||
tfController = self; | tfController = self; | ||||
shouldHaveUndeleteAction = YES; | shouldHaveUndeleteAction = YES; | ||||
} | } | ||||
} | |||||
} | |||||
} | |||||
} | |||||
%orig; | %orig; | ||||
shouldHaveUndeleteAction = NO; | shouldHaveUndeleteAction = NO; | ||||
} | } | ||||
%new | %new | ||||
-(void) completeUndeleteCommentAction:(NSDictionary *) data{ | |||||
- (void)completeUndeleteCommentAction:(NSDictionary *)data { | |||||
id comment = data[@"comment"]; | id comment = data[@"comment"]; | ||||
if (comment){ | |||||
if (comment) { | |||||
MSHookIvar<NSString*>(comment, "_author") = data[@"author"]; | MSHookIvar<NSString*>(comment, "_author") = data[@"author"]; | ||||
MSHookIvar<NSString*>(comment, "_body") = data[@"body"]; | MSHookIvar<NSString*>(comment, "_body") = data[@"body"]; | ||||
[[self commentsManager] updateComment:comment fromEdited:comment]; | [[self commentsManager] updateComment:comment fromEdited:comment]; | ||||
} | } | ||||
} | } | ||||
static void loadPrefs(){ | static void loadPrefs(){ | ||||
NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/User/Library/Preferences/com.lint.undelete.prefs.plist"]; | NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/User/Library/Preferences/com.lint.undelete.prefs.plist"]; | ||||
if (prefs){ | if (prefs){ | ||||
if ([prefs objectForKey:@"isNarwhalEnabled"] != nil){ | |||||
isNarwhalEnabled = [[prefs objectForKey:@"isNarwhalEnabled"] boolValue]; | |||||
} else { | |||||
isNarwhalEnabled = YES; | |||||
} | |||||
if ([prefs objectForKey:@"isTFDeletedOnly"] != nil) { | |||||
isTFDeletedOnly = [[prefs objectForKey:@"isTFDeletedOnly"] boolValue]; | |||||
} else { | |||||
isTFDeletedOnly = YES; | |||||
} | |||||
if ([prefs objectForKey:@"requestTimeoutValue"] != nil){ | |||||
pushshiftRequestTimeoutValue = [[prefs objectForKey:@"requestTimeoutValue"] doubleValue]; | |||||
} else { | |||||
pushshiftRequestTimeoutValue = 10; | |||||
} | |||||
isEnabled = [prefs objectForKey:@"isEnabled"] ? [[prefs objectForKey:@"isEnabled"] boolValue] : YES; | |||||
isNarwhalEnabled = [prefs objectForKey:@"isNarwhalEnabled"] ? [[prefs objectForKey:@"isNarwhalEnabled"] boolValue] : YES; | |||||
isTFDeletedOnly = [prefs objectForKey:@"isTFDeletedOnly"] ? [[prefs objectForKey:@"isTFDeletedOnly"] boolValue] : YES; | |||||
pushshiftRequestTimeoutValue = [prefs objectForKey:@"requestTimeoutValue"] ? [[prefs objectForKey:@"requestTimeoutValue"] doubleValue] : 10; | |||||
} else { | } else { | ||||
isEnabled = YES; | |||||
isNarwhalEnabled = YES; | isNarwhalEnabled = YES; | ||||
isTFDeletedOnly = YES; | isTFDeletedOnly = YES; | ||||
pushshiftRequestTimeoutValue = 10; | pushshiftRequestTimeoutValue = 10; | ||||
} | |||||
} | |||||
} | } | ||||
static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { | static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { | ||||
%ctor { | %ctor { | ||||
loadPrefs(); | loadPrefs(); | ||||
NSString* processName = [[NSProcessInfo processInfo] processName]; | NSString* processName = [[NSProcessInfo processInfo] processName]; | ||||
if ([processName isEqualToString:@"narwhal"]){ | |||||
if (isNarwhalEnabled){ | |||||
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, prefsChanged, CFSTR("com.lint.undelete.prefs.changed"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); | |||||
if ([processName isEqualToString:@"narwhal"]){ | |||||
if (isNarwhalEnabled && isEnabled){ | |||||
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)prefsChanged, CFSTR("com.lint.undelete.prefs.changed"), NULL, CFNotificationSuspensionBehaviorCoalesce); | |||||
%init(Narwhal); | %init(Narwhal); | ||||
} | } | ||||
} | } |
/* -- Comment Interfaces -- */ | /* -- Comment Interfaces -- */ | ||||
@interface Comment | @interface Comment | ||||
//v4 | |||||
//v4 | |||||
@property(strong,nonatomic) id pk; | @property(strong,nonatomic) id pk; | ||||
@property(strong, nonatomic) NSString *bodyText; | @property(strong, nonatomic) NSString *bodyText; | ||||
@property(strong, nonatomic) NSString *author; | @property(strong, nonatomic) NSString *author; | ||||
@interface CommentsViewController : NSObject | @interface CommentsViewController : NSObject | ||||
@property(strong,nonatomic) id postData; | @property(strong,nonatomic) id postData; | ||||
-(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; | |||||
- (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; | |||||
//custom elements | //custom elements | ||||
-(void) updateComments; | |||||
-(void) updatePostText; | |||||
- (void)updateComments; | |||||
- (void)updatePostText; | |||||
@end | @end | ||||
@interface CommentActionSheetViewController : UIViewController | @interface CommentActionSheetViewController : UIViewController | ||||
@property(strong,nonatomic) Comment *comment; | @property(strong,nonatomic) Comment *comment; | ||||
@property(strong,nonatomic) id commentTreeNode; | @property(strong,nonatomic) id commentTreeNode; | ||||
@property(strong,nonatomic) CommentsViewController *commentActionSheetDelegate; | @property(strong,nonatomic) CommentsViewController *commentActionSheetDelegate; | ||||
-(id)animationControllerForDismissedController:(id) arg1; | |||||
- (id)animationControllerForDismissedController:(id)arg1; | |||||
@end | @end | ||||
@interface CommentTreeHeaderNode | @interface CommentTreeHeaderNode | ||||
@property(strong,nonatomic) id commentTreeNode; | @property(strong,nonatomic) id commentTreeNode; | ||||
-(void) updateContentViewsForData:(id)arg1; | |||||
- (void)updateContentViewsForData:(id)arg1; | |||||
@end | @end | ||||
@interface CommentTreeCommandBarNode | @interface CommentTreeCommandBarNode | ||||
@interface CommentTreeHeaderView | @interface CommentTreeHeaderView | ||||
@property(strong,nonatomic) id commentTreeNode; | @property(strong,nonatomic) id commentTreeNode; | ||||
-(void) updateContentViewsForData:(id) arg1; | |||||
- (void)updateContentViewsForData:(id)arg1; | |||||
@end | @end | ||||
/* -- Post Interfaces -- */ | /* -- Post Interfaces -- */ | ||||
@interface PostDetailViewController | @interface PostDetailViewController | ||||
@property(strong,nonatomic) id selfTextNode; | @property(strong,nonatomic) id selfTextNode; | ||||
-(void) configureSelfTextNode; | |||||
- (void)configureSelfTextNode; | |||||
//custom elements | //custom elements | ||||
@property(strong,nonatomic) id feedPostTextWithThumbnailNode; | @property(strong,nonatomic) id feedPostTextWithThumbnailNode; | ||||
@interface FeedPostTitleNode | @interface FeedPostTitleNode | ||||
@property(strong,nonatomic) id delegate; | @property(strong,nonatomic) id delegate; | ||||
-(void) configureNodes; | |||||
- (void)configureNodes; | |||||
@end | @end | ||||
@interface FeedPostDetailDelegator | @interface FeedPostDetailDelegator | ||||
@end | @end | ||||
@interface FeedPostContentNode | @interface FeedPostContentNode | ||||
-(void) configureSelfTextNode; | |||||
- (void)configureSelfTextNode; | |||||
@end | @end | ||||
/* -- Other Interfaces -- */ | /* -- Other Interfaces -- */ | ||||
@interface RUIActionSheetItem : NSObject | @interface RUIActionSheetItem : NSObject | ||||
@property(strong,nonatomic) id leftIconImage; | @property(strong,nonatomic) id leftIconImage; | ||||
-(id) initWithLeftIconImage:(id) arg1 text:(id) arg2 identifier:(id) arg3 context:(id) arg4; | |||||
- (id)initWithLeftIconImage:(id)arg1 text:(id)arg2 identifier:(id)arg3 context:(id)arg4; | |||||
@end | @end | ||||
@interface ActionSheetItem : NSObject | @interface ActionSheetItem : NSObject | ||||
// <= 4.17 | // <= 4.17 | ||||
@property(strong,nonatomic) id leftIconImage; | @property(strong,nonatomic) id leftIconImage; | ||||
-(id) initWithLeftIconImage:(id) arg1 text:(id) arg2 identifier:(id) arg3 context:(id) arg4; | |||||
- (id) initWithLeftIconImage:(id)arg1 text:(id)arg2 identifier:(id)arg3 context:(id)arg4; | |||||
@end | @end | ||||
@interface RUITheme | @interface RUITheme | ||||
@end | @end | ||||
@interface NSAttributedStringMarkdownParser | @interface NSAttributedStringMarkdownParser | ||||
+(id) currentConfig; | |||||
+(id) attributedStringUsingCurrentConfig:(id) arg1; | |||||
-(id) attributedStringFromMarkdownString:(id) arg1; | |||||
-(id) initWithConfig:(id) arg1; | |||||
+ (id)currentConfig; | |||||
+ (id)attributedStringUsingCurrentConfig:(id)arg1; | |||||
- (id)attributedStringFromMarkdownString:(id)arg1; | |||||
- (id)initWithConfig:(id)arg1; | |||||
@end | @end | ||||
@interface ThemeManager | @interface ThemeManager | ||||
+(id) sharedManager; | |||||
+ (id)sharedManager; | |||||
// >= 4.45.0 | // >= 4.45.0 | ||||
@property(strong,nonatomic) id darkTheme; | @property(strong,nonatomic) id darkTheme; | ||||
@property(strong,nonatomic) id lightTheme; | @property(strong,nonatomic) id lightTheme; | ||||
-(id) initWithAppSettings:(id) arg1; | |||||
- (id)initWithAppSettings:(id)arg1; | |||||
// < 4.45.0 | // < 4.45.0 | ||||
@property(strong,nonatomic) id dayTheme; | @property(strong,nonatomic) id dayTheme; | ||||
@property(strong,nonatomic) id nightTheme; | @property(strong,nonatomic) id nightTheme; | ||||
-(id) initWithTraitCollection:(id) arg1 appSettings:(id) arg2; | |||||
- (id)initWithTraitCollection:(id)arg1 appSettings:(id)arg2; | |||||
@end | @end | ||||
@interface AppSettings | @interface AppSettings | ||||
+(id) sharedSettings; | |||||
+ (id)sharedSettings; | |||||
@end | @end | ||||
@interface AccountManager | @interface AccountManager | ||||
@property(assign,nonatomic) id defaults; | @property(assign,nonatomic) id defaults; | ||||
+(id) sharedManager; | |||||
+ (id)sharedManager; | |||||
@end | @end | ||||
/* ---- Reddit v3 ---- */ | /* ---- Reddit v3 ---- */ | ||||
/* -- Comment Interfaces -- */ | /* -- Comment Interfaces -- */ | ||||
@interface CommentCell : UIView | @interface CommentCell : UIView | ||||
-(id) delegate; | |||||
-(id) comment; | |||||
-(id) commentView; | |||||
- (id)delegate; | |||||
- (id)comment; | |||||
- (id)commentView; | |||||
@end | @end | ||||
@interface CommentView | @interface CommentView | ||||
-(void) configureSubviews; | |||||
-(void) layoutSubviews; | |||||
-(id) commandView; | |||||
-(id) comment; | |||||
-(id) delegate; | |||||
- (void)configureSubviews; | |||||
- (void)layoutSubviews; | |||||
- (id)commandView; | |||||
- (id)comment; | |||||
- (id)delegate; | |||||
@end | @end | ||||
@interface CommentCommandView | @interface CommentCommandView | ||||
@property (strong, nonatomic) id undeleteButton; | @property (strong, nonatomic) id undeleteButton; | ||||
-(id)overflowButton; | |||||
-(id) comment; | |||||
-(id) delegate; | |||||
- (id)overflowButton; | |||||
- (id)comment; | |||||
- (id)delegate; | |||||
@end | @end | ||||
/* -- Other Interfaces -- */ | /* -- Other Interfaces -- */ | ||||
@interface MarkDownParser | @interface MarkDownParser | ||||
+(id)attributedStringFromMarkdownString:(id)arg1; | |||||
+ (id)attributedStringFromMarkdownString:(id)arg1; | |||||
@end | @end |
#import "Reddit.h" | #import "Reddit.h" | ||||
#import "assets/TFHelper.h" | #import "assets/TFHelper.h" | ||||
static BOOL isEnabled; | |||||
static BOOL isRedditEnabled; | static BOOL isRedditEnabled; | ||||
static BOOL isTFDeletedOnly; | static BOOL isTFDeletedOnly; | ||||
static CGFloat pushshiftRequestTimeoutValue; | static CGFloat pushshiftRequestTimeoutValue; | ||||
%hook CommentTreeHeaderView | %hook CommentTreeHeaderView | ||||
-(void) layoutSubviews{ | |||||
- (void)layoutSubviews { | |||||
%orig; | %orig; | ||||
[[self commentTreeNode] setCommentTreeHeaderNode:self]; | [[self commentTreeNode] setCommentTreeHeaderNode:self]; | ||||
} | } | ||||
%hook CommentTreeHeaderNode | %hook CommentTreeHeaderNode | ||||
-(void) didLoad{ | |||||
- (void)didLoad { | |||||
%orig; | %orig; | ||||
[[self commentTreeNode] setCommentTreeHeaderNode:self]; | [[self commentTreeNode] setCommentTreeHeaderNode:self]; | ||||
} | } | ||||
%end | %end | ||||
%hook CommentTreeCommandBarNode | %hook CommentTreeCommandBarNode | ||||
-(void) didLoad{ | |||||
- (void)didLoad { | |||||
%orig; | %orig; | ||||
[[self commentTreeNode] setCommentTreeCommandBarNode:self]; | [[self commentTreeNode] setCommentTreeCommandBarNode:self]; | ||||
%hook CommentActionSheetViewController | %hook CommentActionSheetViewController | ||||
-(void) setItems:(id) arg1{ | |||||
NSString *commentBody = [[self comment] bodyText]; | |||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]){ | |||||
- (void)setItems:(id)arg1 { | |||||
NSString *commentAuthor = [[self comment] author]; | |||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentAuthor isDeletedOnly:isTFDeletedOnly]) { | |||||
UIImage* origImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; | UIImage* origImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; | ||||
id undeleteItem = [[%c(RUIActionSheetItem) alloc] initWithLeftIconImage:newImage text:@"TF did that say?" identifier:@"undeleteItemIdentifier" context:[self comment]]; | id undeleteItem = [[%c(RUIActionSheetItem) alloc] initWithLeftIconImage:newImage text:@"TF did that say?" identifier:@"undeleteItemIdentifier" context:[self comment]]; | ||||
arg1 = [arg1 arrayByAddingObject:undeleteItem]; | arg1 = [arg1 arrayByAddingObject:undeleteItem]; | ||||
[undeleteItem release]; | [undeleteItem release]; | ||||
} | } | ||||
%orig; | %orig; | ||||
} | } | ||||
-(void) handleDidSelectActionSheetItem:(id) arg1{ | |||||
- (void)handleDidSelectActionSheetItem:(id)arg1 { | |||||
%orig; | %orig; | ||||
if ([[arg1 identifier] isEqualToString:@"undeleteItemIdentifier"]){ | |||||
[self dismissViewControllerAnimated:YES completion:nil]; | |||||
if ([[arg1 identifier] isEqualToString:@"undeleteItemIdentifier"]) { | |||||
[self dismissViewControllerAnimated:YES completion:nil]; | |||||
id commentTreeNode = [self commentTreeNode]; | id commentTreeNode = [self commentTreeNode]; | ||||
Comment *comment = [commentTreeNode comment]; | Comment *comment = [commentTreeNode comment]; | ||||
[%c(TFHelper) getUndeleteDataWithID:[[comment pk] componentsSeparatedByString:@"_"][1] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; | [%c(TFHelper) getUndeleteDataWithID:[[comment pk] componentsSeparatedByString:@"_"][1] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; | ||||
} | } | ||||
} | } | ||||
%new | |||||
-(void) completeUndeleteCommentAction:(NSDictionary *) data{ | |||||
%new | |||||
- (void)completeUndeleteCommentAction:(NSDictionary *)data { | |||||
id commentTreeNode = [self commentTreeNode]; | id commentTreeNode = [self commentTreeNode]; | ||||
Comment *comment = [commentTreeNode comment]; | Comment *comment = [commentTreeNode comment]; | ||||
NSString *author = data[@"author"]; | NSString *author = data[@"author"]; | ||||
NSString *body = data[@"body"]; | NSString *body = data[@"body"]; | ||||
NSMutableAttributedString *bodyMutableAttributedText; | NSMutableAttributedString *bodyMutableAttributedText; | ||||
id themeManager; | id themeManager; | ||||
id isNightMode; | id isNightMode; | ||||
id textColor; | id textColor; | ||||
if (firstVersionPart == 2020){ | |||||
if (firstVersionPart == 2020) { | |||||
themeManager = [[%c(ThemeManager) alloc] initWithAppSettings:[%c(AppSettings) sharedSettings]]; | themeManager = [[%c(ThemeManager) alloc] initWithAppSettings:[%c(AppSettings) sharedSettings]]; | ||||
isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; | isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; | ||||
if (isNightMode) { | if (isNightMode) { | ||||
textColor = [[themeManager darkTheme] bodyTextColor]; | textColor = [[themeManager darkTheme] bodyTextColor]; | ||||
} else{ | |||||
} else { | |||||
textColor = [[themeManager lightTheme] bodyTextColor]; | textColor = [[themeManager lightTheme] bodyTextColor]; | ||||
} | } | ||||
[themeManager release]; | [themeManager release]; | ||||
} else { | } else { | ||||
if (secondVersionPart >= 45){ | |||||
if (secondVersionPart >= 45) { | |||||
themeManager = [[%c(ThemeManager) alloc] initWithAppSettings:[%c(AppSettings) sharedSettings]]; | themeManager = [[%c(ThemeManager) alloc] initWithAppSettings:[%c(AppSettings) sharedSettings]]; | ||||
isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; | isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; | ||||
if (isNightMode) { | if (isNightMode) { | ||||
textColor = [[themeManager darkTheme] bodyTextColor]; | textColor = [[themeManager darkTheme] bodyTextColor]; | ||||
} else{ | |||||
} else { | |||||
textColor = [[themeManager lightTheme] bodyTextColor]; | textColor = [[themeManager lightTheme] bodyTextColor]; | ||||
} | } | ||||
[themeManager release]; | [themeManager release]; | ||||
} else if (secondVersionPart >= 37){ | |||||
} else if (secondVersionPart >= 37) { | |||||
themeManager = [[%c(ThemeManager) alloc] initWithTraitCollection:nil appSettings:[%c(AppSettings) sharedSettings]]; | themeManager = [[%c(ThemeManager) alloc] initWithTraitCollection:nil appSettings:[%c(AppSettings) sharedSettings]]; | ||||
isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; | isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; | ||||
if (isNightMode) { | if (isNightMode) { | ||||
textColor = [[themeManager nightTheme] bodyTextColor]; | textColor = [[themeManager nightTheme] bodyTextColor]; | ||||
} else{ | |||||
} else { | |||||
textColor = [[themeManager dayTheme] bodyTextColor]; | textColor = [[themeManager dayTheme] bodyTextColor]; | ||||
} | } | ||||
[themeManager release]; | [themeManager release]; | ||||
} else { | } else { | ||||
themeManager = [%c(ThemeManager) sharedManager]; | themeManager = [%c(ThemeManager) sharedManager]; | ||||
isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; | isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; | ||||
if (isNightMode) { | if (isNightMode) { | ||||
textColor = [[themeManager nightTheme] bodyTextColor]; | textColor = [[themeManager nightTheme] bodyTextColor]; | ||||
} else{ | |||||
} else { | |||||
textColor = [[themeManager dayTheme] bodyTextColor]; | textColor = [[themeManager dayTheme] bodyTextColor]; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
bodyMutableAttributedText = [[NSMutableAttributedString alloc] initWithAttributedString:[%c(NSAttributedStringMarkdownParser) attributedStringUsingCurrentConfig:body]]; | bodyMutableAttributedText = [[NSMutableAttributedString alloc] initWithAttributedString:[%c(NSAttributedStringMarkdownParser) attributedStringUsingCurrentConfig:body]]; | ||||
[bodyMutableAttributedText beginEditing]; | [bodyMutableAttributedText beginEditing]; | ||||
[bodyMutableAttributedText enumerateAttribute:NSForegroundColorAttributeName inRange:NSMakeRange(0, bodyMutableAttributedText.length) options:0 usingBlock:^(id _Nullable value, NSRange range, BOOL * _Nonnull stop) { | [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 removeAttribute:NSForegroundColorAttributeName range:range]; | |||||
[bodyMutableAttributedText addAttribute:NSForegroundColorAttributeName value:textColor range:range]; | [bodyMutableAttributedText addAttribute:NSForegroundColorAttributeName value:textColor range:range]; | ||||
}]; | }]; | ||||
[bodyMutableAttributedText endEditing]; | [bodyMutableAttributedText endEditing]; | ||||
[comment setAuthor:author]; | [comment setAuthor:author]; | ||||
[comment setBodyText:body]; | [comment setBodyText:body]; | ||||
[comment setBodyRichTextAttributed:bodyMutableAttributedText]; | [comment setBodyRichTextAttributed:bodyMutableAttributedText]; | ||||
[comment setBodyAttributedText:bodyMutableAttributedText]; | [comment setBodyAttributedText:bodyMutableAttributedText]; | ||||
[[commentTreeNode commentTreeHeaderNode] updateContentViewsForData:comment]; | [[commentTreeNode commentTreeHeaderNode] updateContentViewsForData:comment]; | ||||
[bodyMutableAttributedText release]; | [bodyMutableAttributedText release]; | ||||
%hook FeedPostDetailCellNode | %hook FeedPostDetailCellNode | ||||
-(void) didLoad{ | |||||
- (void)didLoad { | |||||
%orig; | %orig; | ||||
[[[self delegate] viewController] setFeedPostDetailCellNode:self]; | [[[self delegate] viewController] setFeedPostDetailCellNode:self]; | ||||
} | } | ||||
%end | %end | ||||
%hook PostActionSheetViewController | %hook PostActionSheetViewController | ||||
-(void) setItems:(id) arg1{ | |||||
- (void)setItems:(id)arg1 { | |||||
Post *post = [self post]; | Post *post = [self post]; | ||||
NSString *postBody = [post selfText]; | NSString *postBody = [post selfText]; | ||||
if ([post isSelfPost]){ | |||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]){ | |||||
if ([post isSelfPost]) { | |||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]) { | |||||
UIImage* origImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; | UIImage* origImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; | ||||
id undeleteItem = [[%c(RUIActionSheetItem) alloc] initWithLeftIconImage:newImage text:@"TF did that say?" identifier:@"undeleteItemIdentifier" context:[self post]]; | id undeleteItem = [[%c(RUIActionSheetItem) alloc] initWithLeftIconImage:newImage text:@"TF did that say?" identifier:@"undeleteItemIdentifier" context:[self post]]; | ||||
arg1 = [arg1 arrayByAddingObject:undeleteItem]; | arg1 = [arg1 arrayByAddingObject:undeleteItem]; | ||||
[undeleteItem release]; | [undeleteItem release]; | ||||
} | } | ||||
} | } | ||||
%orig; | %orig; | ||||
} | } | ||||
-(void) handleDidSelectActionSheetItem:(id) arg1{ | |||||
- (void)handleDidSelectActionSheetItem:(id)arg1 { | |||||
%orig; | %orig; | ||||
if ([[arg1 identifier] isEqualToString:@"undeleteItemIdentifier"]){ | |||||
if ([[arg1 identifier] isEqualToString:@"undeleteItemIdentifier"]) { | |||||
[self dismissViewControllerAnimated:YES completion:nil]; | [self dismissViewControllerAnimated:YES completion:nil]; | ||||
Post *post = [self post]; | Post *post = [self post]; | ||||
if ([post isSelfPost]){ | if ([post isSelfPost]){ | ||||
[%c(TFHelper) getUndeleteDataWithID:[[post pk] componentsSeparatedByString:@"_"][1] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; | [%c(TFHelper) getUndeleteDataWithID:[[post pk] componentsSeparatedByString:@"_"][1] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; | ||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
%new | %new | ||||
-(void) completeUndeletePostAction:(NSDictionary *) data{ | |||||
- (void)completeUndeletePostAction:(NSDictionary *)data { | |||||
Post *post = [self post]; | Post *post = [self post]; | ||||
NSString *author = data[@"author"]; | NSString *author = data[@"author"]; | ||||
NSString *body = data[@"body"]; | NSString *body = data[@"body"]; | ||||
id themeManager; | id themeManager; | ||||
id isNightMode; | id isNightMode; | ||||
id textColor; | id textColor; | ||||
if (firstVersionPart == 2020){ | |||||
if (firstVersionPart == 2020) { | |||||
themeManager = [[%c(ThemeManager) alloc] initWithAppSettings:[%c(AppSettings) sharedSettings]]; | themeManager = [[%c(ThemeManager) alloc] initWithAppSettings:[%c(AppSettings) sharedSettings]]; | ||||
isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; | isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; | ||||
if (isNightMode) { | if (isNightMode) { | ||||
textColor = [[themeManager darkTheme] bodyTextColor]; | textColor = [[themeManager darkTheme] bodyTextColor]; | ||||
} else{ | |||||
} else { | |||||
textColor = [[themeManager lightTheme] bodyTextColor]; | textColor = [[themeManager lightTheme] bodyTextColor]; | ||||
} | } | ||||
[themeManager release]; | [themeManager release]; | ||||
} else { | } else { | ||||
if (secondVersionPart >= 45){ | |||||
if (secondVersionPart >= 45) { | |||||
themeManager = [[%c(ThemeManager) alloc] initWithAppSettings:[%c(AppSettings) sharedSettings]]; | themeManager = [[%c(ThemeManager) alloc] initWithAppSettings:[%c(AppSettings) sharedSettings]]; | ||||
isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; | isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; | ||||
if (isNightMode) { | if (isNightMode) { | ||||
textColor = [[themeManager darkTheme] bodyTextColor]; | textColor = [[themeManager darkTheme] bodyTextColor]; | ||||
} else{ | |||||
} else { | |||||
textColor = [[themeManager lightTheme] bodyTextColor]; | textColor = [[themeManager lightTheme] bodyTextColor]; | ||||
} | } | ||||
[themeManager release]; | [themeManager release]; | ||||
} else if (secondVersionPart >= 37){ | |||||
} else if (secondVersionPart >= 37) { | |||||
themeManager = [[%c(ThemeManager) alloc] initWithTraitCollection:nil appSettings:[%c(AppSettings) sharedSettings]]; | themeManager = [[%c(ThemeManager) alloc] initWithTraitCollection:nil appSettings:[%c(AppSettings) sharedSettings]]; | ||||
isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; | isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; | ||||
if (isNightMode) { | if (isNightMode) { | ||||
textColor = [[themeManager nightTheme] bodyTextColor]; | textColor = [[themeManager nightTheme] bodyTextColor]; | ||||
} else{ | |||||
} else { | |||||
textColor = [[themeManager dayTheme] bodyTextColor]; | textColor = [[themeManager dayTheme] bodyTextColor]; | ||||
} | } | ||||
[themeManager release]; | [themeManager release]; | ||||
} else { | } else { | ||||
themeManager = [%c(ThemeManager) sharedManager]; | themeManager = [%c(ThemeManager) sharedManager]; | ||||
isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; | isNightMode = [[[%c(AccountManager) sharedManager] defaults] objectForKey:@"kUseNightKey"]; | ||||
if (isNightMode) { | if (isNightMode) { | ||||
textColor = [[themeManager nightTheme] bodyTextColor]; | textColor = [[themeManager nightTheme] bodyTextColor]; | ||||
} else{ | |||||
} else { | |||||
textColor = [[themeManager dayTheme] bodyTextColor]; | textColor = [[themeManager dayTheme] bodyTextColor]; | ||||
} | } | ||||
} | |||||
} | |||||
} | } | ||||
NSMutableAttributedString *bodyMutableAttributedText = [[NSMutableAttributedString alloc] initWithAttributedString:[%c(NSAttributedStringMarkdownParser) attributedStringUsingCurrentConfig:body]]; | NSMutableAttributedString *bodyMutableAttributedText = [[NSMutableAttributedString alloc] initWithAttributedString:[%c(NSAttributedStringMarkdownParser) attributedStringUsingCurrentConfig:body]]; | ||||
[bodyMutableAttributedText beginEditing]; | [bodyMutableAttributedText beginEditing]; | ||||
[bodyMutableAttributedText enumerateAttribute:NSForegroundColorAttributeName inRange:NSMakeRange(0, bodyMutableAttributedText.length) options:0 usingBlock:^(id _Nullable value, NSRange range, BOOL * _Nonnull stop) { | [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 removeAttribute:NSForegroundColorAttributeName range:range]; | |||||
[bodyMutableAttributedText addAttribute:NSForegroundColorAttributeName value:textColor range:range]; | [bodyMutableAttributedText addAttribute:NSForegroundColorAttributeName value:textColor range:range]; | ||||
}]; | }]; | ||||
[bodyMutableAttributedText endEditing]; | [bodyMutableAttributedText endEditing]; | ||||
[post setAuthor:author]; | [post setAuthor:author]; | ||||
[post setSelfPostRichTextAttributed:bodyMutableAttributedText]; | [post setSelfPostRichTextAttributed:bodyMutableAttributedText]; | ||||
[post setPreviewFeedPostTextString:bodyMutableAttributedText]; | [post setPreviewFeedPostTextString:bodyMutableAttributedText]; | ||||
if (firstVersionPart == 2020){ | |||||
if (firstVersionPart == 2020) { | |||||
[[[[[self postActionSheetDelegate] controller] feedPostDetailCellNode] contentNode] configureSelfTextNode]; | [[[[[self postActionSheetDelegate] controller] feedPostDetailCellNode] contentNode] configureSelfTextNode]; | ||||
} else { | } else { | ||||
if (secondVersionPart >= 44){ | |||||
if (secondVersionPart >= 44) { | |||||
[[[[[self postActionSheetDelegate] controller] feedPostDetailCellNode] contentNode] configureSelfTextNode]; | [[[[[self postActionSheetDelegate] controller] feedPostDetailCellNode] contentNode] configureSelfTextNode]; | ||||
} else if (secondVersionPart >= 38) { | } else if (secondVersionPart >= 38) { | ||||
[[[[self postActionSheetDelegate] controller] feedPostDetailCellNode] configureSelfTextNode]; | [[[[self postActionSheetDelegate] controller] feedPostDetailCellNode] configureSelfTextNode]; | ||||
[[[[[self postActionSheetDelegate] controller] feedPostDetailCellNode] titleNode] configureNodes]; | [[[[[self postActionSheetDelegate] controller] feedPostDetailCellNode] titleNode] configureNodes]; | ||||
} | } | ||||
} | } | ||||
[bodyMutableAttributedText release]; | [bodyMutableAttributedText release]; | ||||
} | } | ||||
%hook CommentsViewController | %hook CommentsViewController | ||||
%new | |||||
-(void) updateComments{ | |||||
%new | |||||
- (void)updateComments { | |||||
[self reloadCommentsWithNewCommentsHighlight:NO autoScroll:NO animated:NO]; | [self reloadCommentsWithNewCommentsHighlight:NO autoScroll:NO animated:NO]; | ||||
} | } | ||||
%new | |||||
-(void) updatePostText{ | |||||
%new | |||||
- (void)updatePostText { | |||||
if (secondVersionPart >= 2){ | if (secondVersionPart >= 2){ | ||||
[self reloadPostSection:YES]; | [self reloadPostSection:YES]; | ||||
} else { | } else { | ||||
[self feedPostViewDidUpdatePost:[self postData] shouldReloadFeed:NO]; | [self feedPostViewDidUpdatePost:[self postData] shouldReloadFeed:NO]; | ||||
} | |||||
} | |||||
} | } | ||||
%end | %end | ||||
%hook CommentActionSheetViewController | %hook CommentActionSheetViewController | ||||
-(void) setItems:(id) arg1{ | |||||
NSString *commentBody = [[self comment] bodyText]; | |||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]){ | |||||
- (void)setItems:(id)arg1 { | |||||
NSString *commentAuthor = [[self comment] author]; | |||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentAuthor isDeletedOnly:isTFDeletedOnly]) { | |||||
UIImage* origImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; | UIImage* origImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; | ||||
CGFloat scale = origImage.size.width / existingImageSize.width; | CGFloat scale = origImage.size.width / existingImageSize.width; | ||||
UIImage *newImage = [UIImage imageWithCGImage:[origImage CGImage] scale:scale orientation:origImage.imageOrientation]; | UIImage *newImage = [UIImage imageWithCGImage:[origImage CGImage] scale:scale orientation:origImage.imageOrientation]; | ||||
id undeleteItem; | id undeleteItem; | ||||
if (secondVersionPart >= 18) { | if (secondVersionPart >= 18) { | ||||
undeleteItem = [[%c(RUIActionSheetItem) alloc] initWithLeftIconImage:newImage text:@"TF did that say?" identifier:@"undeleteItemIdentifier" context:[self comment]]; | undeleteItem = [[%c(RUIActionSheetItem) alloc] initWithLeftIconImage:newImage text:@"TF did that say?" identifier:@"undeleteItemIdentifier" context:[self comment]]; | ||||
} else { | } else { | ||||
} | } | ||||
arg1 = [arg1 arrayByAddingObject:undeleteItem]; | arg1 = [arg1 arrayByAddingObject:undeleteItem]; | ||||
[undeleteItem release]; | [undeleteItem release]; | ||||
} | } | ||||
%orig; | %orig; | ||||
} | } | ||||
// >= 4.21 | // >= 4.21 | ||||
-(void) handleDidSelectActionSheetItem:(id) arg1{ | |||||
- (void)handleDidSelectActionSheetItem:(id)arg1 { | |||||
%orig; | %orig; | ||||
if ([[arg1 identifier] isEqualToString:@"undeleteItemIdentifier"]){ | |||||
[self dismissViewControllerAnimated:YES completion:nil]; | |||||
if ([[arg1 identifier] isEqualToString:@"undeleteItemIdentifier"]) { | |||||
[self dismissViewControllerAnimated:YES completion:nil]; | |||||
Comment *comment = [self comment]; | Comment *comment = [self comment]; | ||||
[%c(TFHelper) getUndeleteDataWithID:[[comment pk] componentsSeparatedByString:@"_"][1] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; | [%c(TFHelper) getUndeleteDataWithID:[[comment pk] componentsSeparatedByString:@"_"][1] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; | ||||
} | } | ||||
} | } | ||||
// <= 4.20 | // <= 4.20 | ||||
-(void) actionSheetViewController:(id) arg1 didSelectItem:(id) arg2{ | |||||
- (void)actionSheetViewController:(id)arg1 didSelectItem:(id)arg2 { | |||||
%orig; | %orig; | ||||
if ([[arg2 identifier] isEqualToString:@"undeleteItemIdentifier"]){ | if ([[arg2 identifier] isEqualToString:@"undeleteItemIdentifier"]){ | ||||
[self dismissViewControllerAnimated:YES completion:nil]; | |||||
[self dismissViewControllerAnimated:YES completion:nil]; | |||||
Comment *comment = [self comment]; | Comment *comment = [self comment]; | ||||
[%c(TFHelper) getUndeleteDataWithID:[[comment pk] componentsSeparatedByString:@"_"][1] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; | [%c(TFHelper) getUndeleteDataWithID:[[comment pk] componentsSeparatedByString:@"_"][1] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; | ||||
} | } | ||||
} | } | ||||
%new | |||||
-(void) completeUndeleteCommentAction:(NSDictionary *) data{ | |||||
%new | |||||
- (void)completeUndeleteCommentAction:(NSDictionary *)data { | |||||
Comment *comment = [self comment]; | Comment *comment = [self comment]; | ||||
NSString *body = data[@"body"]; | NSString *body = data[@"body"]; | ||||
NSMutableAttributedString *bodyMutableAttributedText = [[NSMutableAttributedString alloc] initWithAttributedString:[%c(NSAttributedStringMarkdownParser) attributedStringUsingCurrentConfig:body]]; | NSMutableAttributedString *bodyMutableAttributedText = [[NSMutableAttributedString alloc] initWithAttributedString:[%c(NSAttributedStringMarkdownParser) attributedStringUsingCurrentConfig:body]]; | ||||
[comment setAuthor:data[@"author"]]; | [comment setAuthor:data[@"author"]]; | ||||
[comment setBodyText:body]; | [comment setBodyText:body]; | ||||
[comment setBodyAttributedText:bodyMutableAttributedText]; | [comment setBodyAttributedText:bodyMutableAttributedText]; | ||||
%hook PostActionSheetViewController | %hook PostActionSheetViewController | ||||
-(void) setItems:(id) arg1{ | |||||
- (void)setItems:(id)arg1{ | |||||
Post *post = [self post]; | Post *post = [self post]; | ||||
NSString *postBody = [post selfText]; | NSString *postBody = [post selfText]; | ||||
if ([post isSelfPost]){ | |||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]){ | |||||
if ([post isSelfPost]) { | |||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]) { | |||||
UIImage* origImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; | UIImage* origImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; | ||||
CGFloat scale = origImage.size.width / existingImageSize.width; | CGFloat scale = origImage.size.width / existingImageSize.width; | ||||
UIImage *newImage = [UIImage imageWithCGImage:[origImage CGImage] scale:scale orientation:origImage.imageOrientation]; | UIImage *newImage = [UIImage imageWithCGImage:[origImage CGImage] scale:scale orientation:origImage.imageOrientation]; | ||||
id undeleteItem; | id undeleteItem; | ||||
if (secondVersionPart >= 18) { | if (secondVersionPart >= 18) { | ||||
undeleteItem = [[%c(RUIActionSheetItem) alloc] initWithLeftIconImage:newImage text:@"TF did that say?" identifier:@"undeleteItemIdentifier" context:[self post]]; | undeleteItem = [[%c(RUIActionSheetItem) alloc] initWithLeftIconImage:newImage text:@"TF did that say?" identifier:@"undeleteItemIdentifier" context:[self post]]; | ||||
} else { | } else { | ||||
} | } | ||||
arg1 = [arg1 arrayByAddingObject:undeleteItem]; | arg1 = [arg1 arrayByAddingObject:undeleteItem]; | ||||
[undeleteItem release]; | [undeleteItem release]; | ||||
} | } | ||||
} | } | ||||
%orig; | %orig; | ||||
} | } | ||||
// >= 4.21 | // >= 4.21 | ||||
-(void) handleDidSelectActionSheetItem:(id) arg1{ | |||||
- (void)handleDidSelectActionSheetItem:(id)arg1 { | |||||
%orig; | %orig; | ||||
if ([[arg1 identifier] isEqualToString:@"undeleteItemIdentifier"]){ | |||||
if ([[arg1 identifier] isEqualToString:@"undeleteItemIdentifier"]) { | |||||
[self dismissViewControllerAnimated:YES completion:nil]; | [self dismissViewControllerAnimated:YES completion:nil]; | ||||
Post *post = [self post]; | Post *post = [self post]; | ||||
if ([post isSelfPost]){ | |||||
if ([post isSelfPost]) { | |||||
[%c(TFHelper) getUndeleteDataWithID:[[post pk] componentsSeparatedByString:@"_"][1] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; | [%c(TFHelper) getUndeleteDataWithID:[[post pk] componentsSeparatedByString:@"_"][1] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; | ||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
// <= 4.20 | // <= 4.20 | ||||
-(void) actionSheetViewController:(id) arg1 didSelectItem:(id) arg2{ | |||||
- (void)actionSheetViewController:(id)arg1 didSelectItem:(id)arg2 { | |||||
%orig; | %orig; | ||||
if ([[arg2 identifier] isEqualToString:@"undeleteItemIdentifier"]){ | |||||
if ([[arg2 identifier] isEqualToString:@"undeleteItemIdentifier"]) { | |||||
[self dismissViewControllerAnimated:YES completion:nil]; | [self dismissViewControllerAnimated:YES completion:nil]; | ||||
Post *post = [self post]; | Post *post = [self post]; | ||||
if ([post isSelfPost]){ | if ([post isSelfPost]){ | ||||
[%c(TFHelper) getUndeleteDataWithID:[[post pk] componentsSeparatedByString:@"_"][1] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; | [%c(TFHelper) getUndeleteDataWithID:[[post pk] componentsSeparatedByString:@"_"][1] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:nil completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; | ||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
%new | %new | ||||
-(void) completeUndeletePostAction:(NSDictionary *) data{ | |||||
- (void)completeUndeletePostAction:(NSDictionary *)data { | |||||
Post *post = [self post]; | Post *post = [self post]; | ||||
NSString *body = data[@"body"]; | NSString *body = data[@"body"]; | ||||
NSMutableAttributedString *bodyMutableAttributedText = [[NSMutableAttributedString alloc] initWithAttributedString:[%c(NSAttributedStringMarkdownParser) attributedStringUsingCurrentConfig:body]]; | NSMutableAttributedString *bodyMutableAttributedText = [[NSMutableAttributedString alloc] initWithAttributedString:[%c(NSAttributedStringMarkdownParser) attributedStringUsingCurrentConfig:body]]; | ||||
[post setAuthor:data[@"author"]]; | [post setAuthor:data[@"author"]]; | ||||
[post setSelfText:body]; | [post setSelfText:body]; | ||||
[post setSelfTextAttributed:bodyMutableAttributedText]; | [post setSelfTextAttributed:bodyMutableAttributedText]; | ||||
if (secondVersionPart >= 8) { | if (secondVersionPart >= 8) { | ||||
[post setSelfPostRichTextAttributed:bodyMutableAttributedText]; | [post setSelfPostRichTextAttributed:bodyMutableAttributedText]; | ||||
} | } | ||||
if (secondVersionPart >= 15) { | if (secondVersionPart >= 15) { | ||||
[post setPreviewFeedPostTextString:bodyMutableAttributedText]; | [post setPreviewFeedPostTextString:bodyMutableAttributedText]; | ||||
} | |||||
} | |||||
[[self postActionSheetDelegate] updatePostText]; | [[self postActionSheetDelegate] updatePostText]; | ||||
[bodyMutableAttributedText release]; | [bodyMutableAttributedText release]; | ||||
} | } | ||||
%end | %end | ||||
//outdated and unchanged from first version of this tweak... | |||||
//outdated and unchanged from first version of this tweak... | |||||
//TODO: move button to menu, add post support, make async requests once I feel like doing it | //TODO: move button to menu, add post support, make async requests once I feel like doing it | ||||
%group Reddit_v3 | %group Reddit_v3 | ||||
NSString *body = @"[body]"; | NSString *body = @"[body]"; | ||||
if (data != nil && error == nil){ | if (data != nil && error == nil){ | ||||
id jsonData = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; | id jsonData = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; | ||||
author = [[jsonData objectForKey:@"data"][0] objectForKey:@"author"]; | author = [[jsonData objectForKey:@"data"][0] objectForKey:@"author"]; | ||||
body = [[jsonData objectForKey:@"data"][0] objectForKey:@"body"]; | body = [[jsonData objectForKey:@"data"][0] objectForKey:@"body"]; | ||||
if ([body isEqualToString:@"[deleted]"] || [body isEqualToString:@"[removed]"]){ | if ([body isEqualToString:@"[deleted]"] || [body isEqualToString:@"[removed]"]){ | ||||
body = @"[comment was unable to be archived]"; | body = @"[comment was unable to be archived]"; | ||||
} | } | ||||
} else if (error != nil || data == nil){ | } else if (error != nil || data == nil){ | ||||
body = @"[an error occured]"; | body = @"[an error occured]"; | ||||
} | } | ||||
[undeleteButton addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside]; | [undeleteButton addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside]; | ||||
UIImage* undeleteImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; | UIImage* undeleteImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"]; | ||||
[undeleteButton setImage:undeleteImage forState:UIControlStateNormal]; | [undeleteButton setImage:undeleteImage forState:UIControlStateNormal]; | ||||
[commandView setUndeleteButton:undeleteButton]; | [commandView setUndeleteButton:undeleteButton]; | ||||
static void loadPrefs(){ | static void loadPrefs(){ | ||||
NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/User/Library/Preferences/com.lint.undelete.prefs.plist"]; | NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/User/Library/Preferences/com.lint.undelete.prefs.plist"]; | ||||
if (prefs){ | if (prefs){ | ||||
if ([prefs objectForKey:@"isRedditEnabled"] != nil){ | |||||
isRedditEnabled = [[prefs objectForKey:@"isRedditEnabled"] boolValue]; | |||||
} else { | |||||
isRedditEnabled = YES; | |||||
} | |||||
if ([prefs objectForKey:@"isTFDeletedOnly"] != nil) { | |||||
isTFDeletedOnly = [[prefs objectForKey:@"isTFDeletedOnly"] boolValue]; | |||||
} else { | |||||
isTFDeletedOnly = YES; | |||||
} | |||||
if ([prefs objectForKey:@"requestTimeoutValue"] != nil){ | |||||
pushshiftRequestTimeoutValue = [[prefs objectForKey:@"requestTimeoutValue"] doubleValue]; | |||||
} else { | |||||
pushshiftRequestTimeoutValue = 10; | |||||
} | |||||
isEnabled = [prefs objectForKey:@"isEnabled"] ? [[prefs objectForKey:@"isEnabled"] boolValue] : YES; | |||||
isRedditEnabled = [prefs objectForKey:@"isRedditEnabled"] ? [[prefs objectForKey:@"isRedditEnabled"] boolValue] : YES; | |||||
isTFDeletedOnly = [prefs objectForKey:@"isTFDeletedOnly"] ? [[prefs objectForKey:@"isTFDeletedOnly"] boolValue] : YES; | |||||
pushshiftRequestTimeoutValue = [prefs objectForKey:@"requestTimeoutValue"] ? [[prefs objectForKey:@"requestTimeoutValue"] doubleValue] : 10; | |||||
} else { | } else { | ||||
isEnabled = YES; | |||||
isRedditEnabled = YES; | isRedditEnabled = YES; | ||||
isTFDeletedOnly = YES; | isTFDeletedOnly = YES; | ||||
pushshiftRequestTimeoutValue = 10; | pushshiftRequestTimeoutValue = 10; | ||||
%ctor{ | %ctor{ | ||||
loadPrefs(); | loadPrefs(); | ||||
NSString* processName = [[NSProcessInfo processInfo] processName]; | NSString* processName = [[NSProcessInfo processInfo] processName]; | ||||
@try{ | |||||
@try { | |||||
NSArray *redditVersion = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"] componentsSeparatedByString:@"."]; | NSArray *redditVersion = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"] componentsSeparatedByString:@"."]; | ||||
firstVersionPart = [redditVersion[0] intValue]; | firstVersionPart = [redditVersion[0] intValue]; | ||||
secondVersionPart = [redditVersion[1] intValue]; | secondVersionPart = [redditVersion[1] intValue]; | ||||
} | } | ||||
@catch (NSException *exc){ | |||||
@catch (NSException *exc) { | |||||
firstVersionPart = 2020; | firstVersionPart = 2020; | ||||
secondVersionPart = 0; | secondVersionPart = 0; | ||||
} | } | ||||
if ([processName isEqualToString:@"Reddit"]){ | if ([processName isEqualToString:@"Reddit"]){ | ||||
if (isRedditEnabled) { | |||||
if (isRedditEnabled && isEnabled) { | |||||
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)prefsChanged, CFSTR("com.lint.undelete.prefs.changed"), NULL, CFNotificationSuspensionBehaviorCoalesce); | |||||
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, prefsChanged, CFSTR("com.lint.undelete.prefs.changed"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); | |||||
if (firstVersionPart == 4 || firstVersionPart == 2020){ | |||||
if (secondVersionPart <= 32 && firstVersionPart != 2020){ | |||||
if (firstVersionPart == 4 || firstVersionPart == 2020) { | |||||
if (secondVersionPart <= 32 && firstVersionPart != 2020) { | |||||
%init(Reddit_v4_ios10); | %init(Reddit_v4_ios10); | ||||
} else{ | } else{ | ||||
%init(Reddit_v4_current); | %init(Reddit_v4_current); | ||||
} | |||||
} | |||||
} else if (firstVersionPart == 3) { | } else if (firstVersionPart == 3) { | ||||
%init(Reddit_v3); | %init(Reddit_v3); | ||||
} | } |
@end | @end | ||||
@interface CommentDepthCell | @interface CommentDepthCell | ||||
-(void) showMenu:(id) arg1; | |||||
- (void)showMenu:(id)arg1; | |||||
//custom elements | //custom elements | ||||
-(void) addUndeleteButtonToMenu; | |||||
- (void)addUndeleteButtonToMenu; | |||||
@end | @end | ||||
/* -- Post Interfaces -- */ | /* -- Post Interfaces -- */ | ||||
@end | @end | ||||
@interface CommentViewController : UIViewController | @interface CommentViewController : UIViewController | ||||
-(void) refresh:(id) arg1; | |||||
- (void)refresh:(id)arg1; | |||||
//custom elements | //custom elements | ||||
@property(strong, nonatomic) UIButton *undeleteButton; | @property(strong, nonatomic) UIButton *undeleteButton; | ||||
-(void) addUndeleteButtonToToolbar; | |||||
-(BOOL) shouldAddUndeleteButtonToToolbar; | |||||
- (void)addUndeleteButtonToToolbar; | |||||
- (BOOL)shouldAddUndeleteButtonToToolbar; | |||||
@end | @end | ||||
/* -- Utility Interfaces -- */ | /* -- Utility Interfaces -- */ | ||||
@interface UIColor () | @interface UIColor () | ||||
+(UIColor *) colorWithHex:(NSString *) arg1; | |||||
-(NSString *) hexString; | |||||
+ (UIColor *)colorWithHex:(NSString *)arg1; | |||||
- (NSString *)hexString; | |||||
@end | @end | ||||
@interface NSAttributedString () | @interface NSAttributedString () | ||||
-(void) yy_setTextHighlightRange:(NSRange) range color:(UIColor *) color backgroundColor:(UIColor *) backgroundColor userInfo:(NSDictionary *) userInfo; | |||||
- (void)yy_setTextHighlightRange:(NSRange)range color:(UIColor *)color backgroundColor:(UIColor *)backgroundColor userInfo:(NSDictionary *)userInfo; | |||||
@end | @end | ||||
@interface ColorUtil : NSObject | @interface ColorUtil : NSObject | ||||
+(UIColor *) accentColorForSub:(NSString *) arg1; | |||||
+(UIColor *) fontColorForTheme:(NSString *) arg1; | |||||
+(UIColor *) backgroundColorForTheme:(NSString *) arg1; | |||||
+ (UIColor *)accentColorForSub:(NSString *)arg1; | |||||
+ (UIColor *)fontColorForTheme:(NSString *)arg1; | |||||
+ (UIColor *)backgroundColorForTheme:(NSString *)arg1; | |||||
@end | @end | ||||
@interface DTHTMLAttributedStringBuilder | @interface DTHTMLAttributedStringBuilder | ||||
-(id) initWithHTML:(NSData *)data options:(NSDictionary *)options documentAttributes:(NSDictionary * __autoreleasing*)docAttributes; | |||||
-(NSAttributedString *) generatedAttributedString; | |||||
- (id) initWithHTML:(NSData *)data options:(NSDictionary *)options documentAttributes:(NSDictionary * __autoreleasing*)docAttributes; | |||||
- (NSAttributedString *)generatedAttributedString; | |||||
@end | @end | ||||
@interface FontGenerator : NSObject | @interface FontGenerator : NSObject | ||||
+(UIFont *) fontOfSize:(CGFloat) arg1 submission:(BOOL) arg2 willOffset:(BOOL) arg3; | |||||
+(UIFont *) boldFontOfSize:(CGFloat) arg1 submission:(BOOL) arg2 willOffset:(BOOL) arg3; | |||||
+(UIFont *) italicFontOfSize:(CGFloat) arg1 submission:(BOOL) arg2 willOffset:(BOOL) arg3; | |||||
@end | |||||
+ (UIFont *)fontOfSize:(CGFloat)arg1 submission:(BOOL)arg2 willOffset:(BOOL)arg3; | |||||
+ (UIFont *)boldFontOfSize:(CGFloat)arg1 submission:(BOOL)arg2 willOffset:(BOOL)arg3; | |||||
+ (UIFont *)italicFontOfSize:(CGFloat)arg1 submission:(BOOL)arg2 willOffset:(BOOL)arg3; | |||||
@end |
#import "assets/TFHelper.h" | #import "assets/TFHelper.h" | ||||
#import "assets/MMMarkdown/MMMarkdown.h" | #import "assets/MMMarkdown/MMMarkdown.h" | ||||
static BOOL isEnabled; | |||||
static BOOL isSlideEnabled; | static BOOL isSlideEnabled; | ||||
static BOOL isTFDeletedOnly; | static BOOL isTFDeletedOnly; | ||||
static CGFloat pushshiftRequestTimeoutValue; | static CGFloat pushshiftRequestTimeoutValue; | ||||
@implementation FontGenerator | @implementation FontGenerator | ||||
+(UIFont *) fontOfSize:(CGFloat) size submission:(BOOL) isSubmission willOffset:(BOOL) willOffset{ | |||||
+ (UIFont *)fontOfSize:(CGFloat)size submission:(BOOL)isSubmission willOffset:(BOOL)willOffset { | |||||
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; | ||||
NSString *fontName; | NSString *fontName; | ||||
CGFloat fontSize = size; | CGFloat fontSize = size; | ||||
if (willOffset){ | |||||
if (willOffset) { | |||||
if (isSubmission){ | if (isSubmission){ | ||||
fontSize += ([userDefaults objectForKey:@"POST_FONT_SIZE"] == nil) ? 0 : [userDefaults integerForKey:@"POST_FONT_SIZE"]; | fontSize += ([userDefaults objectForKey:@"POST_FONT_SIZE"] == nil) ? 0 : [userDefaults integerForKey:@"POST_FONT_SIZE"]; | ||||
} else { | } else { | ||||
fontSize += ([userDefaults objectForKey:@"COMMENT_FONT_SIZE"] == nil) ? -2 : [userDefaults integerForKey:@"COMMENT_FONT_SIZE"]; | fontSize += ([userDefaults objectForKey:@"COMMENT_FONT_SIZE"] == nil) ? -2 : [userDefaults integerForKey:@"COMMENT_FONT_SIZE"]; | ||||
} | |||||
} | |||||
} | } | ||||
if ([userDefaults stringForKey:(isSubmission ? @"postfont" : @"commentfont")] == nil){ | |||||
if ([userDefaults stringForKey:(isSubmission ? @"postfont" : @"commentfont")] == nil) { | |||||
fontName = isSubmission ? @"AvenirNext-DemiBold" : @"AvenirNext-Medium"; | fontName = isSubmission ? @"AvenirNext-DemiBold" : @"AvenirNext-Medium"; | ||||
} else { | } else { | ||||
fontName = [userDefaults stringForKey:(isSubmission ? @"postfont" : @"commentfont")]; | fontName = [userDefaults stringForKey:(isSubmission ? @"postfont" : @"commentfont")]; | ||||
} | } | ||||
UIFont *font = [UIFont fontWithName:fontName size:fontSize]; | |||||
if (!font){ | |||||
UIFont *font = [UIFont fontWithName:fontName size:fontSize]; | |||||
if (!font) { | |||||
font = [UIFont systemFontOfSize:fontSize]; | font = [UIFont systemFontOfSize:fontSize]; | ||||
} | } | ||||
return font; | return font; | ||||
} | } | ||||
+(UIFont *) boldFontOfSize:(CGFloat) size submission:(BOOL) isSubmission willOffset:(BOOL) willOffset { | |||||
+ (UIFont *)boldFontOfSize:(CGFloat)size submission:(BOOL)isSubmission willOffset:(BOOL)willOffset { | |||||
UIFont *font = [self fontOfSize:size submission:isSubmission willOffset:willOffset]; | UIFont *font = [self fontOfSize:size submission:isSubmission willOffset:willOffset]; | ||||
if ([font.fontName isEqualToString:[UIFont systemFontOfSize:10].fontName]){ | if ([font.fontName isEqualToString:[UIFont systemFontOfSize:10].fontName]){ | ||||
return [UIFont boldSystemFontOfSize:font.pointSize]; | return [UIFont boldSystemFontOfSize:font.pointSize]; | ||||
} else { | } else { | ||||
UIFontDescriptor *desc = [font.fontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitBold]; | UIFontDescriptor *desc = [font.fontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitBold]; | ||||
if (desc == nil){ | if (desc == nil){ | ||||
return font; | return font; | ||||
} else { | } else { | ||||
} | } | ||||
} | } | ||||
+(UIFont *) italicFontOfSize:(CGFloat) size submission:(BOOL) isSubmission willOffset:(BOOL) willOffset { | |||||
+ (UIFont *)italicFontOfSize:(CGFloat)size submission:(BOOL)isSubmission willOffset:(BOOL)willOffset { | |||||
UIFont *font = [self fontOfSize:size submission:isSubmission willOffset:willOffset]; | UIFont *font = [self fontOfSize:size submission:isSubmission willOffset:willOffset]; | ||||
if ([font.fontName isEqualToString:[UIFont systemFontOfSize:10].fontName]){ | |||||
if ([font.fontName isEqualToString:[UIFont systemFontOfSize:10].fontName]) { | |||||
return [UIFont italicSystemFontOfSize:font.pointSize]; | return [UIFont italicSystemFontOfSize:font.pointSize]; | ||||
} else { | } else { | ||||
UIFontDescriptor *desc = [font.fontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitItalic]; | UIFontDescriptor *desc = [font.fontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitItalic]; | ||||
if (desc == nil){ | |||||
if (desc == nil) { | |||||
return font; | return font; | ||||
} else { | } else { | ||||
return [UIFont fontWithDescriptor:desc size: 0]; | return [UIFont fontWithDescriptor:desc size: 0]; | ||||
@end | @end | ||||
@implementation ColorUtil | |||||
@implementation ColorUtil | |||||
+(UIColor *) accentColorForSub:(NSString *) subreddit{ | |||||
+ (UIColor *)accentColorForSub:(NSString *)subreddit { | |||||
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; | ||||
NSData *colorData = [userDefaults dataForKey:[NSString stringWithFormat:@"accent+%@", subreddit]]; | NSData *colorData = [userDefaults dataForKey:[NSString stringWithFormat:@"accent+%@", subreddit]]; | ||||
UIColor *color = [NSKeyedUnarchiver unarchiveObjectWithData:colorData]; | UIColor *color = [NSKeyedUnarchiver unarchiveObjectWithData:colorData]; | ||||
return color; | return color; | ||||
} else { | } else { | ||||
UIColor *baseAccentColor = [NSKeyedUnarchiver unarchiveObjectWithData:[userDefaults dataForKey:@"accentcolor"]]; | UIColor *baseAccentColor = [NSKeyedUnarchiver unarchiveObjectWithData:[userDefaults dataForKey:@"accentcolor"]]; | ||||
if (baseAccentColor){ | |||||
if (baseAccentColor) { | |||||
return baseAccentColor; | return baseAccentColor; | ||||
} else { | } else { | ||||
return [UIColor colorWithRed:0.161 green:0.475 blue:1.0 alpha:1.0]; | return [UIColor colorWithRed:0.161 green:0.475 blue:1.0 alpha:1.0]; | ||||
} | } | ||||
} | } | ||||
+(UIColor *) fontColorForTheme:(NSString *)theme{ | |||||
+ (UIColor *)fontColorForTheme:(NSString *)theme { | |||||
UIColor *fontColor; | UIColor *fontColor; | ||||
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; | ||||
//if only switch blocks worked with strings... | //if only switch blocks worked with strings... | ||||
if ([theme isEqualToString:@"light"]) { | if ([theme isEqualToString:@"light"]) { | ||||
fontColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.87]; | fontColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.87]; | ||||
} else if ([theme isEqualToString:@"blue"]) { | } else if ([theme isEqualToString:@"blue"]) { | ||||
fontColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.87]; | fontColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.87]; | ||||
} else if ([theme isEqualToString:@"sepia"]) { | } else if ([theme isEqualToString:@"sepia"]) { | ||||
fontColor = [UIColor colorWithRed:0.243 green:.239 blue:.212 alpha:0.87]; | |||||
fontColor = [UIColor colorWithRed:0.243 green:.239 blue:.212 alpha:0.87]; | |||||
} else if ([theme isEqualToString:@"red"]) { | } else if ([theme isEqualToString:@"red"]) { | ||||
fontColor = [UIColor colorWithRed:1.0 green:0.969 blue:0.929 alpha:0.87]; | |||||
fontColor = [UIColor colorWithRed:1.0 green:0.969 blue:0.929 alpha:0.87]; | |||||
} else if ([theme isEqualToString:@"deep"]) { | } else if ([theme isEqualToString:@"deep"]) { | ||||
fontColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.87]; | fontColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.87]; | ||||
} else if ([theme isEqualToString:@"mint"]) { | } else if ([theme isEqualToString:@"mint"]) { | ||||
NSString *customThemeString = [[userDefaults stringForKey:[NSString stringWithFormat:@"Theme+%@", theme]] stringByRemovingPercentEncoding]; | NSString *customThemeString = [[userDefaults stringForKey:[NSString stringWithFormat:@"Theme+%@", theme]] stringByRemovingPercentEncoding]; | ||||
if (customThemeString) { | if (customThemeString) { | ||||
NSString *customFontColorHex = [customThemeString componentsSeparatedByString:@"#"][4]; | NSString *customFontColorHex = [customThemeString componentsSeparatedByString:@"#"][4]; | ||||
fontColor = [UIColor colorWithHex:customFontColorHex]; | |||||
fontColor = [UIColor colorWithHex:customFontColorHex]; | |||||
} else { | } else { | ||||
fontColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.87]; | fontColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.87]; | ||||
} | } | ||||
} | } | ||||
return fontColor; | return fontColor; | ||||
} | } | ||||
+(UIColor *) backgroundColorForTheme:(NSString *) theme{ | |||||
+ (UIColor *)backgroundColorForTheme:(NSString *)theme { | |||||
UIColor *backgroundColor; | UIColor *backgroundColor; | ||||
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; | ||||
} else if ([theme isEqualToString:@"blue"]) { | } else if ([theme isEqualToString:@"blue"]) { | ||||
backgroundColor = [UIColor colorWithRed:0.071 green:0.094 blue:0.106 alpha:1.0]; | backgroundColor = [UIColor colorWithRed:0.071 green:0.094 blue:0.106 alpha:1.0]; | ||||
} else if ([theme isEqualToString:@"sepia"]) { | } else if ([theme isEqualToString:@"sepia"]) { | ||||
backgroundColor = [UIColor colorWithRed:0.310 green:0.302 blue:0.267 alpha:1.0]; | |||||
backgroundColor = [UIColor colorWithRed:0.310 green:0.302 blue:0.267 alpha:1.0]; | |||||
} else if ([theme isEqualToString:@"red"]) { | } else if ([theme isEqualToString:@"red"]) { | ||||
backgroundColor = [UIColor colorWithRed:0.075 green:0.055 blue:0.051 alpha:1.0]; | |||||
backgroundColor = [UIColor colorWithRed:0.075 green:0.055 blue:0.051 alpha:1.0]; | |||||
} else if ([theme isEqualToString:@"deep"]) { | } else if ([theme isEqualToString:@"deep"]) { | ||||
backgroundColor = [UIColor colorWithRed:0.035 green:0.035 blue:0.043 alpha:1.0]; | backgroundColor = [UIColor colorWithRed:0.035 green:0.035 blue:0.043 alpha:1.0]; | ||||
} else if ([theme isEqualToString:@"mint"]) { | } else if ([theme isEqualToString:@"mint"]) { | ||||
NSString *customThemeString = [[userDefaults stringForKey:[NSString stringWithFormat:@"Theme+%@", theme]] stringByRemovingPercentEncoding]; | NSString *customThemeString = [[userDefaults stringForKey:[NSString stringWithFormat:@"Theme+%@", theme]] stringByRemovingPercentEncoding]; | ||||
if (customThemeString) { | if (customThemeString) { | ||||
NSString *customFontColorHex = [customThemeString componentsSeparatedByString:@"#"][3]; | NSString *customFontColorHex = [customThemeString componentsSeparatedByString:@"#"][3]; | ||||
backgroundColor = [UIColor colorWithHex:customFontColorHex]; | |||||
backgroundColor = [UIColor colorWithHex:customFontColorHex]; | |||||
} else { | } else { | ||||
backgroundColor = [UIColor colorWithRed:0.352 green:0.352 blue:0.352 alpha:1.0]; | backgroundColor = [UIColor colorWithRed:0.352 green:0.352 blue:0.352 alpha:1.0]; | ||||
} | } | ||||
} | |||||
} | |||||
return backgroundColor; | return backgroundColor; | ||||
} | } | ||||
static UIButton *createUndeleteButton(){ | static UIButton *createUndeleteButton(){ | ||||
UIButton *undeleteButton = [UIButton buttonWithType:UIButtonTypeCustom]; | |||||
UIButton *undeleteButton = [UIButton buttonWithType:UIButtonTypeCustom]; | |||||
UIImage *undeleteImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160white.png"]; | UIImage *undeleteImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160white.png"]; | ||||
UIGraphicsBeginImageContextWithOptions(CGSizeMake(20, 20), NO, 0); | UIGraphicsBeginImageContextWithOptions(CGSizeMake(20, 20), NO, 0); | ||||
[undeleteImage drawInRect:CGRectMake(0, 0, 20, 20)]; | [undeleteImage drawInRect:CGRectMake(0, 0, 20, 20)]; | ||||
undeleteImage = UIGraphicsGetImageFromCurrentImageContext(); | undeleteImage = UIGraphicsGetImageFromCurrentImageContext(); | ||||
UIGraphicsEndImageContext(); | UIGraphicsEndImageContext(); | ||||
UIGraphicsBeginImageContextWithOptions(CGSizeMake(35, 35), NO, 0); | UIGraphicsBeginImageContextWithOptions(CGSizeMake(35, 35), NO, 0); | ||||
CGContextRef context = UIGraphicsGetCurrentContext(); | CGContextRef context = UIGraphicsGetCurrentContext(); | ||||
UIGraphicsPushContext(context); | UIGraphicsPushContext(context); | ||||
[undeleteButton setImage:undeleteImage forState:UIControlStateNormal]; | [undeleteButton setImage:undeleteImage forState:UIControlStateNormal]; | ||||
undeleteButton.imageView.contentMode = UIViewContentModeScaleAspectFit; | undeleteButton.imageView.contentMode = UIViewContentModeScaleAspectFit; | ||||
return undeleteButton; | return undeleteButton; | ||||
} | } | ||||
%hook UIColor | %hook UIColor | ||||
%new | %new | ||||
+(UIColor *) colorWithHex:(NSString *) arg1 { | |||||
+ (UIColor *)colorWithHex:(NSString *)arg1 { | |||||
if (!arg1){ | if (!arg1){ | ||||
NSString *firstChar = [arg1 substringToIndex:1]; | NSString *firstChar = [arg1 substringToIndex:1]; | ||||
if ([firstChar isEqualToString:@"#"]){ | if ([firstChar isEqualToString:@"#"]){ | ||||
arg1 = [arg1 substringWithRange:NSMakeRange(1, [arg1 length]-1)]; | arg1 = [arg1 substringWithRange:NSMakeRange(1, [arg1 length]-1)]; | ||||
} | } | ||||
unsigned rgbValue = 0; | unsigned rgbValue = 0; | ||||
NSScanner *scanner = [NSScanner scannerWithString:arg1]; | NSScanner *scanner = [NSScanner scannerWithString:arg1]; | ||||
[scanner scanHexInt:&rgbValue]; | [scanner scanHexInt:&rgbValue]; | ||||
return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 green:((rgbValue & 0xFF00) >> 8)/255.0 blue:(rgbValue & 0xFF)/255.0 alpha:0.87]; | return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 green:((rgbValue & 0xFF00) >> 8)/255.0 blue:(rgbValue & 0xFF)/255.0 alpha:0.87]; | ||||
} else { | } else { | ||||
return nil; | return nil; | ||||
} | } | ||||
} | } | ||||
%new | |||||
-(NSString *) hexString { | |||||
%new | |||||
- (NSString *)hexString { | |||||
const CGFloat *components = CGColorGetComponents(self.CGColor); | const CGFloat *components = CGColorGetComponents(self.CGColor); | ||||
CGFloat r = components[0]; | CGFloat r = components[0]; | ||||
%hook CommentDepthCell | %hook CommentDepthCell | ||||
-(void) doShortClick{ | |||||
- (void)doShortClick { | |||||
%orig; | %orig; | ||||
[self addUndeleteButtonToMenu]; | [self addUndeleteButtonToMenu]; | ||||
} | } | ||||
-(void) doLongClick { | |||||
- (void)doLongClick { | |||||
%orig; | %orig; | ||||
[self addUndeleteButtonToMenu]; | [self addUndeleteButtonToMenu]; | ||||
} | } | ||||
%new | |||||
-(void) addUndeleteButtonToMenu{ | |||||
%new | |||||
- (void)addUndeleteButtonToMenu { | |||||
NSString *commentBody = [MSHookIvar<id>(self, "comment") body]; | NSString *commentBody = [MSHookIvar<id>(self, "comment") body]; | ||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]){ | |||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:commentBody isDeletedOnly:isTFDeletedOnly]) { | |||||
id controller = MSHookIvar<id>(self, "parent"); | id controller = MSHookIvar<id>(self, "parent"); | ||||
if (MSHookIvar<id>(controller, "menuCell")){ | |||||
if (MSHookIvar<id>(controller, "menuCell")) { | |||||
UIStackView *menu = MSHookIvar<UIStackView *>(self, "menu"); | UIStackView *menu = MSHookIvar<UIStackView *>(self, "menu"); | ||||
if (![[[[menu arrangedSubviews] lastObject] actionsForTarget:self forControlEvent:UIControlEventTouchUpInside] containsObject:@"handleUndeleteComment:"]){ | |||||
if (![[[[menu arrangedSubviews] lastObject] actionsForTarget:self forControlEvent:UIControlEventTouchUpInside] containsObject:@"handleUndeleteComment:"]) { | |||||
UIButton *undeleteButton = createUndeleteButton(); | UIButton *undeleteButton = createUndeleteButton(); | ||||
[undeleteButton addTarget:self action:@selector(handleUndeleteComment:) forControlEvents:UIControlEventTouchUpInside]; | [undeleteButton addTarget:self action:@selector(handleUndeleteComment:) forControlEvents:UIControlEventTouchUpInside]; | ||||
[menu addArrangedSubview:undeleteButton]; | [menu addArrangedSubview:undeleteButton]; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
%new | %new | ||||
-(void) handleUndeleteComment:(id) sender{ | |||||
- (void)handleUndeleteComment:(id)sender { | |||||
[sender setEnabled:NO]; | [sender setEnabled:NO]; | ||||
id comment = MSHookIvar<id>(self, "comment"); | id comment = MSHookIvar<id>(self, "comment"); | ||||
[%c(TFHelper) getUndeleteDataWithID:[[comment id] componentsSeparatedByString:@"_"][1] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:@{@"sender" : sender} completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; | [%c(TFHelper) getUndeleteDataWithID:[[comment id] componentsSeparatedByString:@"_"][1] isComment:YES timeout:pushshiftRequestTimeoutValue extraData:@{@"sender" : sender} completionTarget:self completionSelector:@selector(completeUndeleteCommentAction:)]; | ||||
} | } | ||||
%new | %new | ||||
-(void) completeUndeleteCommentAction:(NSDictionary *) data{ | |||||
- (void)completeUndeleteCommentAction:(NSDictionary *)data { | |||||
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; | ||||
id textStackDisplayView = MSHookIvar<id>(self, "commentBody"); | id textStackDisplayView = MSHookIvar<id>(self, "commentBody"); | ||||
id comment = MSHookIvar<id>(self, "comment"); | id comment = MSHookIvar<id>(self, "comment"); | ||||
NSString *author = data[@"author"]; | NSString *author = data[@"author"]; | ||||
NSString *body = data[@"body"]; | NSString *body = data[@"body"]; | ||||
//Attributed string generation rewrote from Slide_for_Reddit.TextDisplayStackView.createAttributedChunk(...) | |||||
//Attributed string generation rewrote from Slide_for_Reddit.TextDisplayStackView.createAttributedChunk(...) | |||||
UIFont *font = [%c(FontGenerator) fontOfSize:MSHookIvar<CGFloat>(textStackDisplayView, "fontSize") submission:NO willOffset:YES]; | UIFont *font = [%c(FontGenerator) fontOfSize:MSHookIvar<CGFloat>(textStackDisplayView, "fontSize") submission:NO willOffset:YES]; | ||||
NSString *themeName = [userDefaults stringForKey:@"theme"]; | NSString *themeName = [userDefaults stringForKey:@"theme"]; | ||||
UIColor *fontColor = [%c(ColorUtil) fontColorForTheme:themeName]; | UIColor *fontColor = [%c(ColorUtil) fontColorForTheme:themeName]; | ||||
UIColor *accentColor = [%c(ColorUtil) accentColorForSub:[comment subreddit]]; | UIColor *accentColor = [%c(ColorUtil) accentColorForSub:[comment subreddit]]; | ||||
NSString *html = [%c(MMMarkdown) HTMLStringWithMarkdown:body extensions:MMMarkdownExtensionsGitHubFlavored error:nil]; | NSString *html = [%c(MMMarkdown) HTMLStringWithMarkdown:body extensions:MMMarkdownExtensionsGitHubFlavored error:nil]; | ||||
html = [[html stringByReplacingOccurrencesOfString:@"<sup>" withString:@"<font size=\"1\">"] stringByReplacingOccurrencesOfString:@"</sup>" withString:@"</font>"]; | html = [[html stringByReplacingOccurrencesOfString:@"<sup>" withString:@"<font size=\"1\">"] stringByReplacingOccurrencesOfString:@"</sup>" withString:@"</font>"]; | ||||
html = [[html stringByReplacingOccurrencesOfString:@"<del>" withString:@"<font color=\"green\">"] stringByReplacingOccurrencesOfString:@"</del>" withString:@"</font>"]; | html = [[html stringByReplacingOccurrencesOfString:@"<del>" withString:@"<font color=\"green\">"] stringByReplacingOccurrencesOfString:@"</del>" withString:@"</font>"]; | ||||
html = [[html stringByReplacingOccurrencesOfString:@"<code>" withString:@"<font color=\"blue\">"] stringByReplacingOccurrencesOfString:@"</code>" withString:@"</font>"]; | html = [[html stringByReplacingOccurrencesOfString:@"<code>" withString:@"<font color=\"blue\">"] stringByReplacingOccurrencesOfString:@"</code>" withString:@"</font>"]; | ||||
html = [html stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; | html = [html stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; | ||||
DTHTMLAttributedStringBuilder *dthtmlBuilder = [[%c(DTHTMLAttributedStringBuilder) alloc] initWithHTML:[html dataUsingEncoding:NSUTF8StringEncoding] options:@{@"DTUseiOS6Attributes": @YES, @"DTDefaultTextColor": fontColor, @"DTDefaultFontSize": @([font pointSize])} documentAttributes:nil]; | DTHTMLAttributedStringBuilder *dthtmlBuilder = [[%c(DTHTMLAttributedStringBuilder) alloc] initWithHTML:[html dataUsingEncoding:NSUTF8StringEncoding] options:@{@"DTUseiOS6Attributes": @YES, @"DTDefaultTextColor": fontColor, @"DTDefaultFontSize": @([font pointSize])} documentAttributes:nil]; | ||||
NSMutableAttributedString *htmlAttributedString = [[NSMutableAttributedString alloc] initWithAttributedString:[dthtmlBuilder generatedAttributedString]]; | NSMutableAttributedString *htmlAttributedString = [[NSMutableAttributedString alloc] initWithAttributedString:[dthtmlBuilder generatedAttributedString]]; | ||||
NSRange htmlStringRange = NSMakeRange(0, [htmlAttributedString length]); | NSRange htmlStringRange = NSMakeRange(0, [htmlAttributedString length]); | ||||
[[htmlAttributedString mutableString] replaceOccurrencesOfString:@"\t•\t" withString:@" • " options:0 range: htmlStringRange]; | [[htmlAttributedString mutableString] replaceOccurrencesOfString:@"\t•\t" withString:@" • " options:0 range: htmlStringRange]; | ||||
[[htmlAttributedString mutableString] replaceOccurrencesOfString:@"\t◦\t" withString:@" ◦ " options:0 range: htmlStringRange]; | [[htmlAttributedString mutableString] replaceOccurrencesOfString:@"\t◦\t" withString:@" ◦ " options:0 range: htmlStringRange]; | ||||
[[htmlAttributedString mutableString] replaceOccurrencesOfString:@"\t▪\t" withString:@" ▪ " options:0 range: htmlStringRange]; | [[htmlAttributedString mutableString] replaceOccurrencesOfString:@"\t▪\t" withString:@" ▪ " options:0 range: htmlStringRange]; | ||||
[htmlAttributedString removeAttribute:@"CTForegroundColorFromContext" range:htmlStringRange]; | [htmlAttributedString removeAttribute:@"CTForegroundColorFromContext" range:htmlStringRange]; | ||||
[htmlAttributedString enumerateAttributesInRange:htmlStringRange options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired usingBlock:^(NSDictionary *attributes, NSRange range, BOOL *stop) { | [htmlAttributedString enumerateAttributesInRange:htmlStringRange options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired usingBlock:^(NSDictionary *attributes, NSRange range, BOOL *stop) { | ||||
for (NSString *key in attributes){ | |||||
if ([(UIColor *) attributes[key] isKindOfClass:[UIColor class]]){ | |||||
for (NSString *key in attributes) { | |||||
if ([(UIColor *) attributes[key] isKindOfClass:[UIColor class]]) { | |||||
UIColor *attrColor = (UIColor *) attributes[key]; | UIColor *attrColor = (UIColor *) attributes[key]; | ||||
if ([[attrColor hexString] isEqualToString:@"#0000FF"]){ | |||||
if ([[attrColor hexString] isEqualToString:@"#0000FF"]) { | |||||
UIFont *tempFont = [UIFont fontWithName:@"Courier" size:font.pointSize]; | UIFont *tempFont = [UIFont fontWithName:@"Courier" size:font.pointSize]; | ||||
[htmlAttributedString setAttributes:@{NSForegroundColorAttributeName: accentColor, NSBackgroundColorAttributeName: [%c(ColorUtil) backgroundColorForTheme:themeName], NSFontAttributeName: (tempFont ? tempFont : font)} range:range]; | [htmlAttributedString setAttributes:@{NSForegroundColorAttributeName: accentColor, NSBackgroundColorAttributeName: [%c(ColorUtil) backgroundColorForTheme:themeName], NSFontAttributeName: (tempFont ? tempFont : font)} range:range]; | ||||
} else if ([[attrColor hexString] isEqualToString:@"#008000"]) { | } else if ([[attrColor hexString] isEqualToString:@"#008000"]) { | ||||
[htmlAttributedString setAttributes:@{NSForegroundColorAttributeName: fontColor, NSFontAttributeName:font} range:range]; | [htmlAttributedString setAttributes:@{NSForegroundColorAttributeName: fontColor, NSFontAttributeName:font} range:range]; | ||||
} | } | ||||
} else if ([(NSURL *) attributes[key] isKindOfClass:[NSURL class]]){ | |||||
} else if ([(NSURL *) attributes[key] isKindOfClass:[NSURL class]]) { | |||||
NSURL *attrUrl = (NSURL *)attributes[key]; | NSURL *attrUrl = (NSURL *)attributes[key]; | ||||
if (([userDefaults objectForKey:@"ENLARGE_LINKS"] == nil) ? YES : [userDefaults boolForKey:@"ENLARGE_LINKS"]){ | |||||
if (([userDefaults objectForKey:@"ENLARGE_LINKS"] == nil) ? YES : [userDefaults boolForKey:@"ENLARGE_LINKS"]) { | |||||
[htmlAttributedString addAttribute:NSFontAttributeName value:[%c(FontGenerator) boldFontOfSize:18 submission:NO willOffset:YES] range:range]; | [htmlAttributedString addAttribute:NSFontAttributeName value:[%c(FontGenerator) boldFontOfSize:18 submission:NO willOffset:YES] range:range]; | ||||
} | } | ||||
[htmlAttributedString addAttribute:NSForegroundColorAttributeName value:accentColor range:range]; | |||||
[htmlAttributedString addAttribute:NSForegroundColorAttributeName value:accentColor range:range]; | |||||
[htmlAttributedString addAttribute:NSUnderlineColorAttributeName value:[UIColor clearColor] range:range]; | [htmlAttributedString addAttribute:NSUnderlineColorAttributeName value:[UIColor clearColor] range:range]; | ||||
//skipping showLinkContentType b/c not necessary and spoilers b/c MMMarkdown doesn't support them | //skipping showLinkContentType b/c not necessary and spoilers b/c MMMarkdown doesn't support them | ||||
[htmlAttributedString yy_setTextHighlightRange:range color: accentColor backgroundColor:nil userInfo:@{@"url": attrUrl}]; | [htmlAttributedString yy_setTextHighlightRange:range color: accentColor backgroundColor:nil userInfo:@{@"url": attrUrl}]; | ||||
break; | |||||
} | |||||
break; | |||||
} | |||||
} | } | ||||
}]; | }]; | ||||
[htmlAttributedString beginEditing]; | [htmlAttributedString beginEditing]; | ||||
[htmlAttributedString enumerateAttribute:NSFontAttributeName inRange:NSMakeRange(0, [htmlAttributedString length]) options:0 usingBlock:^(id value, NSRange range, BOOL *stop){ | |||||
[htmlAttributedString enumerateAttribute:NSFontAttributeName inRange:NSMakeRange(0, [htmlAttributedString length]) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) { | |||||
UIFont *attrFont = (UIFont *)value; | UIFont *attrFont = (UIFont *)value; | ||||
BOOL isBold = (attrFont.fontDescriptor.symbolicTraits & UIFontDescriptorTraitBold) != 0; | BOOL isBold = (attrFont.fontDescriptor.symbolicTraits & UIFontDescriptorTraitBold) != 0; | ||||
BOOL isItalic = (attrFont.fontDescriptor.symbolicTraits & UIFontDescriptorTraitItalic) != 0; | BOOL isItalic = (attrFont.fontDescriptor.symbolicTraits & UIFontDescriptorTraitItalic) != 0; | ||||
UIFont *newFont = font; | UIFont *newFont = font; | ||||
if (isBold){ | if (isBold){ | ||||
newFont = [%c(FontGenerator) boldFontOfSize:attrFont.pointSize submission:NO willOffset:NO]; | newFont = [%c(FontGenerator) boldFontOfSize:attrFont.pointSize submission:NO willOffset:NO]; | ||||
} else if (isItalic){ | } else if (isItalic){ | ||||
newFont = [%c(FontGenerator) italicFontOfSize:attrFont.pointSize submission:NO willOffset:NO]; | newFont = [%c(FontGenerator) italicFontOfSize:attrFont.pointSize submission:NO willOffset:NO]; | ||||
} | } | ||||
[htmlAttributedString removeAttribute:NSFontAttributeName range:range]; | [htmlAttributedString removeAttribute:NSFontAttributeName range:range]; | ||||
[htmlAttributedString addAttribute:NSFontAttributeName value:newFont range:range]; | |||||
[htmlAttributedString addAttribute:NSFontAttributeName value:newFont range:range]; | |||||
}]; | }]; | ||||
[htmlAttributedString endEditing]; | [htmlAttributedString endEditing]; | ||||
NSMutableAttributedString *newCommentText = [MSHookIvar<NSMutableAttributedString *>(self, "cellContent") initWithAttributedString:htmlAttributedString]; | NSMutableAttributedString *newCommentText = [MSHookIvar<NSMutableAttributedString *>(self, "cellContent") initWithAttributedString:htmlAttributedString]; | ||||
NSAttributedString *tempAttributedString = [[NSAttributedString alloc] initWithString:@""]; | NSAttributedString *tempAttributedString = [[NSAttributedString alloc] initWithString:@""]; | ||||
[newCommentText appendAttributedString:tempAttributedString]; //to keep the compiler happy | [newCommentText appendAttributedString:tempAttributedString]; //to keep the compiler happy | ||||
[comment setAuthor:author]; | [comment setAuthor:author]; | ||||
[comment setBody:body]; | |||||
[comment setBody:body]; | |||||
id controller = MSHookIvar<id>(self, "parent"); | id controller = MSHookIvar<id>(self, "parent"); | ||||
[self showMenu:nil]; | [self showMenu:nil]; | ||||
[MSHookIvar<id>(controller, "tableView") reloadData]; | [MSHookIvar<id>(controller, "tableView") reloadData]; | ||||
[data[@"sender"] setEnabled:YES]; | [data[@"sender"] setEnabled:YES]; | ||||
} | } | ||||
%hook RSubmission | %hook RSubmission | ||||
-(id) author{ | |||||
- (id)author { | |||||
if (shouldSlideOverridePostInfo){ | if (shouldSlideOverridePostInfo){ | ||||
return slidePostOverrideAuthor; | return slidePostOverrideAuthor; | ||||
} else { | } else { | ||||
} | } | ||||
} | } | ||||
-(id) htmlBody{ | |||||
- (id)htmlBody { | |||||
if (shouldSlideOverridePostInfo){ | if (shouldSlideOverridePostInfo){ | ||||
return slidePostOverrideBodyHtml; | return slidePostOverrideBodyHtml; | ||||
} | } | ||||
%hook CommentViewController | %hook CommentViewController | ||||
%property(strong, nonatomic) UIButton *undeleteButton; | %property(strong, nonatomic) UIButton *undeleteButton; | ||||
-(void) viewDidLoad { | |||||
- (void)viewDidLoad { | |||||
%orig; | %orig; | ||||
shouldSlideOverridePostInfo = NO; | shouldSlideOverridePostInfo = NO; | ||||
slidePostOverrideAuthor = nil; | slidePostOverrideAuthor = nil; | ||||
slidePostOverrideBodyHtml = nil; | slidePostOverrideBodyHtml = nil; | ||||
UIButton *undeleteButton = createUndeleteButton(); | UIButton *undeleteButton = createUndeleteButton(); | ||||
[undeleteButton setImage:[[undeleteButton currentImage] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; | [undeleteButton setImage:[[undeleteButton currentImage] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; | ||||
[undeleteButton addTarget:self action:@selector(handleUndeletePost:) forControlEvents:UIControlEventTouchUpInside]; | [undeleteButton addTarget:self action:@selector(handleUndeletePost:) forControlEvents:UIControlEventTouchUpInside]; | ||||
[self setUndeleteButton:undeleteButton]; | [self setUndeleteButton:undeleteButton]; | ||||
} | } | ||||
-(void) viewDidLayoutSubviews{ | |||||
- (void)viewDidLayoutSubviews { | |||||
%orig; | %orig; | ||||
if ([self undeleteButton]){ | |||||
if ([self shouldAddUndeleteButtonToToolbar]){ | |||||
if ([self undeleteButton]) { | |||||
if ([self shouldAddUndeleteButtonToToolbar]) { | |||||
[self addUndeleteButtonToToolbar]; | [self addUndeleteButtonToToolbar]; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
-(void) loadAll:(id) arg1{ | |||||
- (void)loadAll:(id)arg1 { | |||||
%orig; | %orig; | ||||
if ([self undeleteButton]){ | if ([self undeleteButton]){ | ||||
if ([self shouldAddUndeleteButtonToToolbar]){ | if ([self shouldAddUndeleteButtonToToolbar]){ | ||||
[self addUndeleteButtonToToolbar]; | [self addUndeleteButtonToToolbar]; | ||||
} | } | ||||
%new | %new | ||||
-(BOOL) shouldAddUndeleteButtonToToolbar{ | |||||
- (BOOL)shouldAddUndeleteButtonToToolbar { | |||||
id post = MSHookIvar<id>(self, "submission"); | id post = MSHookIvar<id>(self, "submission"); | ||||
if ([post isSelf]){ | |||||
if ([post isSelf]) { | |||||
NSString *postBody = [post body]; | NSString *postBody = [post body]; | ||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]){ | |||||
if ([%c(TFHelper) shouldShowUndeleteButtonWithInfo:postBody isDeletedOnly:isTFDeletedOnly]) { | |||||
return YES; | return YES; | ||||
} | } | ||||
} | } | ||||
return NO; | return NO; | ||||
} | } | ||||
%new | %new | ||||
-(void) addUndeleteButtonToToolbar{ | |||||
- (void)addUndeleteButtonToToolbar { | |||||
UIToolbar *toolbar = [[self navigationController] toolbar]; | UIToolbar *toolbar = [[self navigationController] toolbar]; | ||||
NSMutableArray *toolbarItems = [[toolbar items] mutableCopy]; | NSMutableArray *toolbarItems = [[toolbar items] mutableCopy]; | ||||
UIView *firstView = [toolbarItems[0] customView]; | UIView *firstView = [toolbarItems[0] customView]; | ||||
if (firstView){ | |||||
if (firstView) { | |||||
UIColor *tintColor = [toolbar tintColor]; | UIColor *tintColor = [toolbar tintColor]; | ||||
UIButton *undeleteButton = [self undeleteButton]; | UIButton *undeleteButton = [self undeleteButton]; | ||||
[undeleteButton setTintColor:tintColor]; | [undeleteButton setTintColor:tintColor]; | ||||
if ([firstView isMemberOfClass:[UIView class]]){ | |||||
if ([firstView isMemberOfClass:[UIView class]]) { | |||||
if (![undeleteButton isDescendantOfView:firstView]){ | if (![undeleteButton isDescendantOfView:firstView]){ | ||||
[firstView addSubview:undeleteButton]; | [firstView addSubview:undeleteButton]; | ||||
[undeleteButton setFrame:firstView.bounds]; | [undeleteButton setFrame:firstView.bounds]; | ||||
} | } | ||||
} else if ([firstView isMemberOfClass:[UIButton class]] && undeleteButton != firstView){ | |||||
} else if ([firstView isMemberOfClass:[UIButton class]] && undeleteButton != firstView) { | |||||
UIBarButtonItem *undeleteItem = [[UIBarButtonItem alloc] initWithCustomView:undeleteButton]; | UIBarButtonItem *undeleteItem = [[UIBarButtonItem alloc] initWithCustomView:undeleteButton]; | ||||
[toolbarItems insertObject:toolbarItems[1] atIndex:0]; | [toolbarItems insertObject:toolbarItems[1] atIndex:0]; | ||||
[toolbarItems insertObject:undeleteItem atIndex:0]; | [toolbarItems insertObject:undeleteItem atIndex:0]; | ||||
[toolbar setItems:toolbarItems animated:NO]; | [toolbar setItems:toolbarItems animated:NO]; | ||||
} | } | ||||
%new | %new | ||||
-(void) handleUndeletePost:(id) sender{ | |||||
- (void)handleUndeletePost:(id)sender { | |||||
shouldSlideOverridePostInfo = YES; | shouldSlideOverridePostInfo = YES; | ||||
[sender setEnabled:NO]; | [sender setEnabled:NO]; | ||||
[%c(TFHelper) getUndeleteDataWithID:[MSHookIvar<id>(self, "submission") name] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:@{@"sender" : sender} completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; | |||||
[%c(TFHelper) getUndeleteDataWithID:[MSHookIvar<id>(self, "submission") name] isComment:NO timeout:pushshiftRequestTimeoutValue extraData:@{@"sender" : sender} completionTarget:self completionSelector:@selector(completeUndeletePostAction:)]; | |||||
} | } | ||||
%new | %new | ||||
-(void) completeUndeletePostAction:(NSDictionary *) data{ | |||||
- (void)completeUndeletePostAction:(NSDictionary *)data { | |||||
slidePostOverrideAuthor = data[@"author"]; | slidePostOverrideAuthor = data[@"author"]; | ||||
slidePostOverrideBodyHtml = [%c(MMMarkdown) HTMLStringWithMarkdown:data[@"body"] extensions:MMMarkdownExtensionsGitHubFlavored error:nil]; | slidePostOverrideBodyHtml = [%c(MMMarkdown) HTMLStringWithMarkdown:data[@"body"] extensions:MMMarkdownExtensionsGitHubFlavored error:nil]; | ||||
[self refresh:nil]; | [self refresh:nil]; | ||||
[data[@"sender"] setEnabled:YES]; | [data[@"sender"] setEnabled:YES]; | ||||
} | } | ||||
static void loadPrefs(){ | static void loadPrefs(){ | ||||
NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/User/Library/Preferences/com.lint.undelete.prefs.plist"]; | NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/User/Library/Preferences/com.lint.undelete.prefs.plist"]; | ||||
if (prefs){ | if (prefs){ | ||||
if ([prefs objectForKey:@"isSlideEnabled"] != nil){ | |||||
isSlideEnabled = [[prefs objectForKey:@"isSlideEnabled"] boolValue]; | |||||
} else { | |||||
isSlideEnabled = YES; | |||||
} | |||||
if ([prefs objectForKey:@"isTFDeletedOnly"] != nil){ | |||||
isTFDeletedOnly = [[prefs objectForKey:@"isTFDeletedOnly"] boolValue]; | |||||
} else { | |||||
isTFDeletedOnly = YES; | |||||
} | |||||
if ([prefs objectForKey:@"requestTimeoutValue"] != nil){ | |||||
pushshiftRequestTimeoutValue = [[prefs objectForKey:@"requestTimeoutValue"] doubleValue]; | |||||
} else { | |||||
pushshiftRequestTimeoutValue = 10; | |||||
} | |||||
isEnabled = [prefs objectForKey:@"isEnabled"] ? [[prefs objectForKey:@"isEnabled"] boolValue] : YES; | |||||
isSlideEnabled = [prefs objectForKey:@"isSlideEnabled"] ? [[prefs objectForKey:@"isSlideEnabled"] boolValue] : YES; | |||||
isTFDeletedOnly = [prefs objectForKey:@"isTFDeletedOnly"] ? [[prefs objectForKey:@"isTFDeletedOnly"] boolValue] : YES; | |||||
pushshiftRequestTimeoutValue = [prefs objectForKey:@"requestTimeoutValue"] ? [[prefs objectForKey:@"requestTimeoutValue"] doubleValue] : 10; | |||||
} else { | } else { | ||||
isEnabled = YES; | |||||
isSlideEnabled = YES; | isSlideEnabled = YES; | ||||
isTFDeletedOnly = YES; | isTFDeletedOnly = YES; | ||||
pushshiftRequestTimeoutValue = 10; | pushshiftRequestTimeoutValue = 10; | ||||
} | |||||
} | |||||
} | } | ||||
static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { | static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) { | ||||
%ctor { | %ctor { | ||||
loadPrefs(); | loadPrefs(); | ||||
NSString* processName = [[NSProcessInfo processInfo] processName]; | NSString* processName = [[NSProcessInfo processInfo] processName]; | ||||
if ([processName isEqualToString:@"Slide for Reddit"]){ | if ([processName isEqualToString:@"Slide for Reddit"]){ | ||||
if (isSlideEnabled){ | |||||
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, prefsChanged, CFSTR("com.lint.undelete.prefs.changed"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately); | |||||
if (isSlideEnabled && isEnabled){ | |||||
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)prefsChanged, CFSTR("com.lint.undelete.prefs.changed"), NULL, CFNotificationSuspensionBehaviorCoalesce); | |||||
%init(Slide, CommentDepthCell = objc_getClass("Slide_for_Reddit.CommentDepthCell"), RSubmission = objc_getClass("Slide_for_Reddit.RSubmission"), CommentViewController = objc_getClass("Slide_for_Reddit.CommentViewController")); | %init(Slide, CommentDepthCell = objc_getClass("Slide_for_Reddit.CommentDepthCell"), RSubmission = objc_getClass("Slide_for_Reddit.RSubmission"), CommentViewController = objc_getClass("Slide_for_Reddit.CommentViewController")); | ||||
} | } | ||||
} | } |
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) | |||||
@interface TFHelper : NSObject | @interface TFHelper : NSObject | ||||
+(void) getUndeleteDataWithID:(NSString *) ident isComment:(BOOL) isComment timeout:(CGFloat) timeout extraData:(NSDictionary *) extra completionTarget:(id) target completionSelector:(SEL) sel; | |||||
+(BOOL) shouldShowUndeleteButtonWithInfo:(NSString *) content isDeletedOnly:(BOOL) isDeletedOnly; | |||||
+ (void)getUndeleteDataWithID:(NSString *)ident isComment:(BOOL)isComment timeout:(CGFloat)timeout extraData:(NSDictionary *)extra completionTarget:(id)target completionSelector:(SEL)sel; | |||||
+ (BOOL)shouldShowUndeleteButtonWithInfo:(NSString *)content isDeletedOnly:(BOOL)isDeletedOnly; | |||||
@end | @end |
@implementation TFHelper | @implementation TFHelper | ||||
+(void) getUndeleteDataWithID:(NSString *) ident isComment:(BOOL) isComment timeout:(CGFloat) timeout extraData:(NSDictionary *) extra completionTarget:(id) target completionSelector:(SEL) sel{ | |||||
+ (void)getUndeleteDataWithID:(NSString *)ident isComment:(BOOL)isComment timeout:(CGFloat)timeout extraData:(NSDictionary *)extra completionTarget:(id)target completionSelector:(SEL)sel { | |||||
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; | NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; | ||||
NSOperationQueue *queue = [[NSOperationQueue alloc] init]; | NSOperationQueue *queue = [[NSOperationQueue alloc] init]; | ||||
if (isComment){ | if (isComment){ | ||||
[request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://api.pushshift.io/reddit/search/comment/?ids=%@&fields=author,body", ident]]]; | [request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://api.pushshift.io/reddit/search/comment/?ids=%@&fields=author,body", ident]]]; | ||||
} else { | } else { | ||||
[request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://api.pushshift.io/reddit/search/submission/?ids=%@&fields=author,selftext", ident]]]; | [request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://api.pushshift.io/reddit/search/submission/?ids=%@&fields=author,selftext", ident]]]; | ||||
} | } | ||||
[request setHTTPMethod:@"GET"]; | [request setHTTPMethod:@"GET"]; | ||||
[request setTimeoutInterval:timeout]; | [request setTimeoutInterval:timeout]; | ||||
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { | [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { | ||||
NSString *author = @"[author]"; | NSString *author = @"[author]"; | ||||
NSString *body = @"[body]"; | NSString *body = @"[body]"; | ||||
} else if (error != nil || data == nil){ | } else if (error != nil || data == nil){ | ||||
body = [NSString stringWithFormat:@"[an error occured while attempting to contact pushshift api (%@)]", [error localizedDescription]]; | body = [NSString stringWithFormat:@"[an error occured while attempting to contact pushshift api (%@)]", [error localizedDescription]]; | ||||
} | } | ||||
NSMutableDictionary *result = [@{@"author" : author, @"body" : body} mutableCopy]; | NSMutableDictionary *result = [@{@"author" : author, @"body" : body} mutableCopy]; | ||||
if (extra){ | if (extra){ | ||||
[result addEntriesFromDictionary:extra]; | [result addEntriesFromDictionary:extra]; | ||||
} | } | ||||
[target performSelectorOnMainThread:sel withObject:result waitUntilDone:NO]; | [target performSelectorOnMainThread:sel withObject:result waitUntilDone:NO]; | ||||
}]; | }]; | ||||
} | } | ||||
+(BOOL) shouldShowUndeleteButtonWithInfo:(NSString *) content isDeletedOnly:(BOOL) isDeletedOnly{ | +(BOOL) shouldShowUndeleteButtonWithInfo:(NSString *) content isDeletedOnly:(BOOL) isDeletedOnly{ | ||||
if (!isDeletedOnly){ | if (!isDeletedOnly){ | ||||
return YES; | return YES; | ||||
} else { | } else { | ||||
return YES; | return YES; | ||||
} | } | ||||
} | } | ||||
return NO; | return NO; | ||||
} | } | ||||