//
// StoryDetailViewController.m
// NewsBlur
//
// Created by Samuel Clay on 6/24/10.
// Copyright 2010 __MyCompanyName__. All rights reserved.
//
#import "StoryDetailViewController.h"
#import "NewsBlurAppDelegate.h"
#import "NewsBlurViewController.h"
#import "FeedDetailViewController.h"
#import "FontSettingsViewController.h"
#import "UserProfileViewController.h"
#import "ShareViewController.h"
#import "ASIHTTPRequest.h"
#import "ASIFormDataRequest.h"
#import "Base64.h"
#import "Utilities.h"
#import "NSString+HTML.h"
#import "NBContainerViewController.h"
#import "DataUtilities.h"
#import "JSON.h"
@interface StoryDetailViewController ()
@property (readwrite) CGFloat inTouchMove;
@property (nonatomic) MBProgressHUD *storyHUD;
@end
@implementation StoryDetailViewController
@synthesize appDelegate;
@synthesize activeStoryId;
@synthesize progressView;
@synthesize progressViewContainer;
@synthesize innerView;
@synthesize webView;
@synthesize toolbar;
@synthesize buttonPrevious;
@synthesize buttonNext;
@synthesize buttonAction;
@synthesize activity;
@synthesize loadingIndicator;
@synthesize feedTitleGradient;
@synthesize buttonNextStory;
@synthesize popoverController;
@synthesize fontSettingsButton;
@synthesize originalStoryButton;
@synthesize subscribeButton;
@synthesize noStorySelectedLabel;
@synthesize buttonBack;
@synthesize bottomPlaceholderToolbar;
// private
@synthesize inTouchMove;
@synthesize storyHUD;
#pragma mark -
#pragma mark View boilerplate
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
popoverClass = [WEPopoverController class];
// adding HUD for progress bar
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapProgressBar:)];
[self.progressViewContainer addGestureRecognizer:tap];
self.progressViewContainer.hidden = YES;
// settings button to right
// UIImage *settingsImage = [UIImage imageNamed:@"settings.png"];
// UIButton *settings = [UIButton buttonWithType:UIButtonTypeCustom];
// settings.bounds = CGRectMake(0, 0, 32, 32);
// [settings addTarget:self action:@selector(toggleFontSize:) forControlEvents:UIControlEventTouchUpInside];
// [settings setImage:settingsImage forState:UIControlStateNormal];
//
// UIBarButtonItem *settingsButton = [[UIBarButtonItem alloc]
// initWithCustomView:settings];
UIBarButtonItem *settingsButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"settings.png"] style:UIBarButtonItemStylePlain target:self action:@selector(toggleFontSize:)];
self.fontSettingsButton = settingsButton;
// original button for iPhone
UIBarButtonItem *originalButton = [[UIBarButtonItem alloc]
initWithTitle:@"Original"
style:UIBarButtonItemStyleBordered
target:self
action:@selector(showOriginalSubview:)
];
self.originalStoryButton = originalButton;
UIBarButtonItem *subscribeBtn = [[UIBarButtonItem alloc]
initWithTitle:@"Follow User"
style:UIBarButtonSystemItemAction
target:self
action:@selector(subscribeToBlurblog)
];
self.subscribeButton = subscribeBtn;
// back button
UIBarButtonItem *backButton = [[UIBarButtonItem alloc]
initWithTitle:@"Back" style:UIBarButtonItemStyleBordered target:self action:@selector(transitionFromFeedDetail)];
self.buttonBack = backButton;
// loading indicator
self.loadingIndicator = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.webView.scalesPageToFit = NO;
self.webView.multipleTouchEnabled = NO;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
UIButton *backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
backBtn.frame = CGRectMake(0, 0, 51, 31);
[backBtn setImage:[UIImage imageNamed:@"nav_btn_back.png"] forState:UIControlStateNormal];
[backBtn addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *back = [[UIBarButtonItem alloc] initWithCustomView:backBtn];
self.navigationItem.backBarButtonItem = back;
self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects: originalButton, settingsButton, nil];
} else {
self.navigationController.navigationBar.tintColor = [UIColor colorWithRed:0.16f green:0.36f blue:0.46 alpha:0.9];
self.bottomPlaceholderToolbar.tintColor = [UIColor colorWithRed:0.16f green:0.36f blue:0.46 alpha:0.9];
}
}
- (void)transitionFromFeedDetail {
[self performSelector:@selector(clearStory) withObject:self afterDelay:0.5];
[appDelegate.masterContainerViewController transitionFromFeedDetail];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[appDelegate adjustStoryDetailWebView];
[self setActiveStory];
}
- (void)viewDidAppear:(BOOL)animated {
// set the subscribeButton flag
if (appDelegate.isTryFeedView) {
self.subscribeButton.title = [NSString stringWithFormat:@"Follow %@", [appDelegate.activeFeed objectForKey:@"username"]];
self.navigationItem.leftBarButtonItem = self.subscribeButton;
// self.subscribeButton.tintColor = UIColorFromRGB(0x0a6720);
}
appDelegate.isTryFeedView = NO;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad && UIInterfaceOrientationIsPortrait(orientation)) {
UITouch *theTouch = [touches anyObject];
if ([theTouch.view isKindOfClass: UIToolbar.class] || [theTouch.view isKindOfClass: UIView.class]) {
self.inTouchMove = YES;
CGPoint touchLocation = [theTouch locationInView:self.view];
CGFloat y = touchLocation.y;
[appDelegate.masterContainerViewController dragStoryToolbar:y];
}
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad && UIInterfaceOrientationIsPortrait(orientation)) {
UITouch *theTouch = [touches anyObject];
if (([theTouch.view isKindOfClass: UIToolbar.class] || [theTouch.view isKindOfClass: UIView.class]) && self.inTouchMove) {
self.inTouchMove = NO;
[appDelegate.masterContainerViewController adjustFeedDetailScreenForStoryTitles];
}
}
}
- (void)viewDidUnload {
[self setButtonNextStory:nil];
[self setInnerView:nil];
[self setBottomPlaceholderToolbar:nil];
[self setProgressViewContainer:nil];
[self setNoStorySelectedLabel:nil];
[super viewDidUnload];
}
- (void)initStory {
id storyId = [appDelegate.activeStory objectForKey:@"id"];
[appDelegate pushReadStory:storyId];
[self showStory];
self.webView.scalesPageToFit = YES;
[self.loadingIndicator stopAnimating];
}
- (void)clearStory {
[self.webView loadHTMLString:@"
" baseURL:nil];
self.noStorySelectedLabel.hidden = NO;
}
- (void)viewDidDisappear:(BOOL)animated {
// Class viewClass = [appDelegate.navigationController.visibleViewController class];
// if (viewClass == [appDelegate.feedDetailViewController class] ||
// viewClass == [appDelegate.feedsViewController class]) {
//// self.activeStoryId = nil;
// [webView loadHTMLString:@"" baseURL:[NSURL URLWithString:@""]];
// }
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[appDelegate adjustStoryDetailWebView];
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
// [appDelegate.shareViewController.commentField resignFirstResponder];
}
#pragma mark -
#pragma mark Story layout
- (NSString *)getAvatars:(BOOL)areFriends {
NSString *avatarString = @"";
NSArray *share_user_ids;
if (areFriends) {
share_user_ids = [appDelegate.activeStory objectForKey:@"shared_by_friends"];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// only if your friends are sharing to do you see the shared label
if ([share_user_ids count]) {
avatarString = [avatarString stringByAppendingString:@
""];
}
}
} else {
share_user_ids = [appDelegate.activeStory objectForKey:@"shared_by_public"];
}
for (int i = 0; i < share_user_ids.count; i++) {
NSDictionary *user = [self getUser:[[share_user_ids objectAtIndex:i] intValue]];
NSString *avatar = [NSString stringWithFormat:@
"
"
"

"
"
",
[user objectForKey:@"user_id"],
[user objectForKey:@"user_id"],
[user objectForKey:@"photo_url"]];
avatarString = [avatarString stringByAppendingString:avatar];
}
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
if (areFriends && [share_user_ids count]) {
avatarString = [avatarString stringByAppendingString:@"
"];
}
}
return avatarString;
}
- (NSString *)getComments {
NSString *comments = @""]];
}
return comments;
}
- (NSString *)getShareBar {
NSString *comments = @"";
if ([appDelegate.activeStory objectForKey:@"share_count"] != [NSNull null] &&
[[appDelegate.activeStory objectForKey:@"share_count"] intValue] > 0) {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
comments = [comments stringByAppendingString:[NSString stringWithFormat:@
""]];
}
}
NSString *storyHeader = [NSString stringWithFormat:@
"",
[story_tags length] ?
[appDelegate.activeStory
objectForKey:@"long_parsed_date"] :
[appDelegate.activeStory
objectForKey:@"short_parsed_date"],
[appDelegate.activeStory objectForKey:@"story_title"],
story_author,
story_tags];
NSString *htmlString = [NSString stringWithFormat:@
""
"%@" // header string
""
" %@" // storyHeader
" %@" // shareBar
"
" // font-style
" %@" // share
" "
" %@"
""
"",
headerString,
contentWidthClass,
storyHeader,
shareBarString,
fontStyleClass,
fontSizeClass,
[appDelegate.activeStory objectForKey:@"story_content"],
sharingHtmlString,
commentString,
footerString
];
NSLog(@"\n\n\n\nhtmlString:\n\n\n%@\n\n\n", htmlString);
NSString *path = [[NSBundle mainBundle] bundlePath];
NSURL *baseURL = [NSURL fileURLWithPath:path];
[webView loadHTMLString:htmlString
//baseURL:[NSURL URLWithString:feed_link]];
baseURL:baseURL];
NSDictionary *feed;
NSString *feedIdStr = [NSString stringWithFormat:@"%@",
[appDelegate.activeStory
objectForKey:@"story_feed_id"]];
if (appDelegate.isSocialView) {
feed = [appDelegate.dictActiveFeeds objectForKey:feedIdStr];
// this is to catch when a user is already subscribed
if (!feed) {
feed = [appDelegate.dictFeeds objectForKey:feedIdStr];
}
} else {
feed = [appDelegate.dictFeeds objectForKey:feedIdStr];
}
self.feedTitleGradient = [appDelegate makeFeedTitleGradient:feed
withRect:CGRectMake(0, -1, 1024, 21)]; // 1024 hack for self.webView.frame.size.width
self.feedTitleGradient.tag = FEED_TITLE_GRADIENT_TAG; // Not attached yet. Remove old gradients, first.
for (UIView *subview in self.webView.subviews) {
if (subview.tag == FEED_TITLE_GRADIENT_TAG) {
[subview removeFromSuperview];
}
}
for (NSObject *aSubView in [self.webView subviews]) {
if ([aSubView isKindOfClass:[UIScrollView class]]) {
UIScrollView * theScrollView = (UIScrollView *)aSubView;
if (appDelegate.isRiverView || appDelegate.isSocialView) {
theScrollView.contentInset = UIEdgeInsetsMake(19, 0, 0, 0);
theScrollView.scrollIndicatorInsets = UIEdgeInsetsMake(19, 0, 0, 0);
} else {
theScrollView.contentInset = UIEdgeInsetsMake(9, 0, 0, 0);
theScrollView.scrollIndicatorInsets = UIEdgeInsetsMake(9, 0, 0, 0);
}
[self.webView insertSubview:feedTitleGradient aboveSubview:theScrollView];
[theScrollView setContentOffset:CGPointMake(0, (appDelegate.isRiverView || appDelegate.isSocialView) ? -19 : -9) animated:NO];
break;
}
}
[self setNextPreviousButtons];
}
- (void)setActiveStory {
self.activeStoryId = [appDelegate.activeStory objectForKey:@"id"];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
if (!appDelegate.isSocialView) {
NSString *feedIdStr = [NSString stringWithFormat:@"%@", [appDelegate.activeStory objectForKey:@"story_feed_id"]];
UIImage *titleImage = appDelegate.isRiverView ?
[UIImage imageNamed:@"folder_white.png"] :
[Utilities getImage:feedIdStr];
UIImageView *titleImageView = [[UIImageView alloc] initWithImage:titleImage];
titleImageView.frame = CGRectMake(0.0, 2.0, 16.0, 16.0);
titleImageView.hidden = YES;
self.navigationItem.titleView = titleImageView;
titleImageView.hidden = NO;
} else {
NSString *feedIdStr = [NSString stringWithFormat:@"%@", [appDelegate.activeFeed objectForKey:@"id"]];
UIImage *titleImage = [Utilities getImage:feedIdStr];
titleImage = [Utilities roundCorneredImage:titleImage radius:6];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectZero];
imageView.frame = CGRectMake(0.0, 0.0, 28.0, 28.0);
[imageView setImage:titleImage];
self.navigationItem.titleView = imageView;
}
}
}
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType {
NSURL *url = [request URL];
NSArray *urlComponents = [url pathComponents];
NSString *action = @"";
if ([urlComponents count] > 1) {
action = [NSString stringWithFormat:@"%@", [urlComponents objectAtIndex:1]];
}
// HACK: Using ios.newsblur.com to intercept the javascript share, reply, and edit events.
// the pathComponents do not work correctly unless it is a correctly formed url
// Is there a better way? Someone show me the light
if ([[url host] isEqualToString: @"ios.newsblur.com"]){
// reset the active comment
appDelegate.activeComment = nil;
appDelegate.activeShareType = action;
if ([action isEqualToString:@"reply"] ||
[action isEqualToString:@"edit-reply"] ||
[action isEqualToString:@"edit-share"] ||
[action isEqualToString:@"like-comment"] ||
[action isEqualToString:@"unlike-comment"]) {
// search for the comment from friends comments
NSArray *friendComments = [appDelegate.activeStory objectForKey:@"friend_comments"];
for (int i = 0; i < friendComments.count; i++) {
NSString *userId = [NSString stringWithFormat:@"%@",
[[friendComments objectAtIndex:i] objectForKey:@"user_id"]];
if([userId isEqualToString:[NSString stringWithFormat:@"%@",
[urlComponents objectAtIndex:2]]]){
appDelegate.activeComment = [friendComments objectAtIndex:i];
}
}
if (appDelegate.activeComment == nil) {
NSArray *publicComments = [appDelegate.activeStory objectForKey:@"public_comments"];
for (int i = 0; i < publicComments.count; i++) {
NSString *userId = [NSString stringWithFormat:@"%@",
[[publicComments objectAtIndex:i] objectForKey:@"user_id"]];
if([userId isEqualToString:[NSString stringWithFormat:@"%@",
[urlComponents objectAtIndex:2]]]){
appDelegate.activeComment = [publicComments objectAtIndex:i];
}
}
}
if (appDelegate.activeComment == nil) {
NSLog(@"PROBLEM! the active comment was not found in friend or public comments");
return NO;
}
if ([action isEqualToString:@"reply"]) {
[appDelegate showShareView:@"reply"
setUserId:[NSString stringWithFormat:@"%@", [urlComponents objectAtIndex:2]]
setUsername:[NSString stringWithFormat:@"%@", [urlComponents objectAtIndex:3]]
setReplyId:nil];
} else if ([action isEqualToString:@"edit-reply"]) {
[appDelegate showShareView:@"edit-reply"
setUserId:[NSString stringWithFormat:@"%@", [urlComponents objectAtIndex:2]]
setUsername:nil
setReplyId:[NSString stringWithFormat:@"%@", [urlComponents objectAtIndex:4]]];
} else if ([action isEqualToString:@"edit-share"]) {
[appDelegate showShareView:@"edit-share"
setUserId:nil
setUsername:nil
setReplyId:nil];
} else if ([action isEqualToString:@"like-comment"]) {
[self toggleLikeComment:YES];
} else if ([action isEqualToString:@"unlike-comment"]) {
[self toggleLikeComment:NO];
}
return NO;
} else if ([action isEqualToString:@"share"]) {
// test to see if the user has commented
// search for the comment from friends comments
NSArray *friendComments = [appDelegate.activeStory objectForKey:@"friend_comments"];
NSString *currentUserId = [NSString stringWithFormat:@"%@", [appDelegate.dictUserProfile objectForKey:@"user_id"]];
for (int i = 0; i < friendComments.count; i++) {
NSString *userId = [NSString stringWithFormat:@"%@",
[[friendComments objectAtIndex:i] objectForKey:@"user_id"]];
if([userId isEqualToString:currentUserId]){
appDelegate.activeComment = [friendComments objectAtIndex:i];
}
}
if (appDelegate.activeComment == nil) {
[appDelegate showShareView:@"share"
setUserId:nil
setUsername:nil
setReplyId:nil];
} else {
[appDelegate showShareView:@"edit-share"
setUserId:nil
setUsername:nil
setReplyId:nil];
}
return NO;
} else if ([action isEqualToString:@"show-profile"]) {
appDelegate.activeUserProfileId = [NSString stringWithFormat:@"%@", [urlComponents objectAtIndex:2]];
for (int i = 0; i < appDelegate.activeFeedUserProfiles.count; i++) {
NSString *userId = [NSString stringWithFormat:@"%@", [[appDelegate.activeFeedUserProfiles objectAtIndex:i] objectForKey:@"user_id"]];
if ([userId isEqualToString:appDelegate.activeUserProfileId]){
appDelegate.activeUserProfileName = [NSString stringWithFormat:@"%@", [[appDelegate.activeFeedUserProfiles objectAtIndex:i] objectForKey:@"username"]];
break;
}
}
[self showUserProfile:[urlComponents objectAtIndex:2]
xCoordinate:[[urlComponents objectAtIndex:3] intValue]
yCoordinate:[[urlComponents objectAtIndex:4] intValue]
width:[[urlComponents objectAtIndex:5] intValue]
height:[[urlComponents objectAtIndex:6] intValue]];
return NO;
}
}
if (navigationType == UIWebViewNavigationTypeLinkClicked) {
[appDelegate showOriginalStory:url];
return NO;
}
return YES;
}
- (void)showUserProfile:(NSString *)userId xCoordinate:(int)x yCoordinate:(int)y width:(int)width height:(int)height {
CGRect frame = CGRectZero;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// only adjust for the bar if user is scrolling
if (appDelegate.isRiverView || appDelegate.isSocialView) {
if (self.webView.scrollView.contentOffset.y == -19) {
y = y + 19;
}
} else {
if (self.webView.scrollView.contentOffset.y == -9) {
y = y + 9;
}
}
frame = CGRectMake(x, y, width, height);
}
[appDelegate showUserProfileModal:[NSValue valueWithCGRect:frame]];
}
- (void)webViewDidStartLoad:(UIWebView *)webView {
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
if ([userPreferences integerForKey:@"fontSizing"]){
[self changeFontSize:[userPreferences stringForKey:@"fontSizing"]];
}
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
[MBProgressHUD hideHUDForView:self.view animated:YES];
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
if ([userPreferences integerForKey:@"fontSizing"]){
[self changeFontSize:[userPreferences stringForKey:@"fontSizing"]];
}
// see if it's a tryfeed for animation
if (appDelegate.tryFeedCategory) {
if ([appDelegate.tryFeedCategory isEqualToString:@"comment_like"] ||
[appDelegate.tryFeedCategory isEqualToString:@"comment_reply"]) {
NSString *currentUserId = [NSString stringWithFormat:@"%@", [appDelegate.dictUserProfile objectForKey:@"user_id"]];
NSString *jsFlashString = [[NSString alloc] initWithFormat:@"slideToComment('%@', true, true);", currentUserId];
[self.webView stringByEvaluatingJavaScriptFromString:jsFlashString];
} else if ([appDelegate.tryFeedCategory isEqualToString:@"story_reshare"]) {
NSString *blurblogUserId = [NSString stringWithFormat:@"%@", [appDelegate.activeStory objectForKey:@"social_user_id"]];
NSString *jsFlashString = [[NSString alloc] initWithFormat:@"slideToComment('%@', true);", blurblogUserId];
[self.webView stringByEvaluatingJavaScriptFromString:jsFlashString];
}
appDelegate.tryFeedCategory = nil;
}
}
#pragma mark -
#pragma mark Actions
- (IBAction)tapProgressBar:(id)sender {
[MBProgressHUD hideHUDForView:self.view animated:NO];
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.mode = MBProgressHUDModeText;
hud.removeFromSuperViewOnHide = YES;
int unreadCount = appDelegate.unreadCount;
if (unreadCount == 0) {
hud.labelText = @"No unread stories";
} else if (unreadCount == 1) {
hud.labelText = @"1 story left";
} else {
hud.labelText = [NSString stringWithFormat:@"%i stories left", unreadCount];
}
[hud hide:YES afterDelay:0.8];
}
- (void)setNextPreviousButtons {
// setting up the PREV BUTTON
int readStoryCount = [appDelegate.readStories count];
if (readStoryCount == 0 ||
(readStoryCount == 1 &&
[appDelegate.readStories lastObject] == [appDelegate.activeStory objectForKey:@"id"])) {
[buttonPrevious setStyle:UIBarButtonItemStyleBordered];
[buttonPrevious setTitle:@"Previous"];
[buttonPrevious setEnabled:NO];
} else {
[buttonPrevious setStyle:UIBarButtonItemStyleBordered];
[buttonPrevious setTitle:@"Previous"];
[buttonPrevious setEnabled:YES];
}
// setting up the NEXT UNREAD STORY BUTTON
int nextIndex = [appDelegate indexOfNextUnreadStory];
int unreadCount = [appDelegate unreadCount];
if (nextIndex == -1 && unreadCount > 0) {
[buttonNext setStyle:UIBarButtonItemStyleBordered];
[buttonNext setTitle:@"Next Unread"];
} else if (nextIndex == -1) {
[buttonNext setStyle:UIBarButtonItemStyleDone];
[buttonNext setTitle:@"Done"];
} else {
[buttonNext setStyle:UIBarButtonItemStyleBordered];
[buttonNext setTitle:@"Next Unread"];
}
float unreads = (float)[appDelegate unreadCount];
float total = [appDelegate originalStoryCount];
float progress = (total - unreads) / total;
[progressView setProgress:progress];
}
- (void)markStoryAsRead {
// NSLog(@"[appDelegate.activeStory objectForKey:@read_status] intValue] %i", [[appDelegate.activeStory objectForKey:@"read_status"] intValue]);
if ([[appDelegate.activeStory objectForKey:@"read_status"] intValue] != 1) {
[appDelegate markActiveStoryRead];
NSString *urlString;
if (appDelegate.isSocialView) {
urlString = [NSString stringWithFormat:@"http://%@/reader/mark_social_stories_as_read",
NEWSBLUR_URL];
} else {
urlString = [NSString stringWithFormat:@"http://%@/reader/mark_story_as_read",
NEWSBLUR_URL];
}
NSURL *url = [NSURL URLWithString:urlString];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
if (appDelegate.isSocialView) {
NSArray *storyId = [NSArray arrayWithObject:[appDelegate.activeStory objectForKey:@"id"]];
NSDictionary *feedStory = [NSDictionary dictionaryWithObject:storyId
forKey:[NSString stringWithFormat:@"%@",
[appDelegate.activeStory objectForKey:@"story_feed_id"]]];
NSDictionary *usersFeedsStories = [NSDictionary dictionaryWithObject:feedStory
forKey:[NSString stringWithFormat:@"%@",
[appDelegate.activeStory objectForKey:@"social_user_id"]]];
[request setPostValue:[usersFeedsStories JSONRepresentation] forKey:@"users_feeds_stories"];
} else {
[request setPostValue:[appDelegate.activeStory
objectForKey:@"id"]
forKey:@"story_id"];
[request setPostValue:[appDelegate.activeStory
objectForKey:@"story_feed_id"]
forKey:@"feed_id"];
}
[request setDidFinishSelector:@selector(finishMarkAsRead:)];
[request setDidFailSelector:@selector(finishedWithError:)];
[request setDelegate:self];
[request startAsynchronous];
}
}
- (void)toggleLikeComment:(BOOL)likeComment {
[self showShareHUD];
NSString *urlString;
if (likeComment) {
urlString = [NSString stringWithFormat:@"http://%@/social/like_comment",
NEWSBLUR_URL];
} else {
urlString = [NSString stringWithFormat:@"http://%@/social/remove_like_comment",
NEWSBLUR_URL];
}
NSURL *url = [NSURL URLWithString:urlString];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:[appDelegate.activeStory
objectForKey:@"id"]
forKey:@"story_id"];
[request setPostValue:[appDelegate.activeStory
objectForKey:@"story_feed_id"]
forKey:@"story_feed_id"];
[request setPostValue:[appDelegate.activeComment objectForKey:@"user_id"] forKey:@"comment_user_id"];
[request setDidFinishSelector:@selector(finishLikeComment:)];
[request setDidFailSelector:@selector(finishedWithError:)];
[request setDelegate:self];
[request startAsynchronous];
}
- (void)finishLikeComment:(ASIHTTPRequest *)request {
NSString *responseString = [request responseString];
NSData *responseData=[responseString dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
NSDictionary *results = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
// add the comment into the activeStory dictionary
NSDictionary *newStory = [DataUtilities updateComment:results for:appDelegate];
// update the current story and the activeFeedStories
appDelegate.activeStory = newStory;
NSMutableArray *newActiveFeedStories = [[NSMutableArray alloc] init];
for (int i = 0; i < appDelegate.activeFeedStories.count; i++) {
NSDictionary *feedStory = [appDelegate.activeFeedStories objectAtIndex:i];
NSString *storyId = [NSString stringWithFormat:@"%@", [feedStory objectForKey:@"id"]];
NSString *currentStoryId = [NSString stringWithFormat:@"%@", [appDelegate.activeStory objectForKey:@"id"]];
if ([storyId isEqualToString: currentStoryId]){
[newActiveFeedStories addObject:newStory];
} else {
[newActiveFeedStories addObject:[appDelegate.activeFeedStories objectAtIndex:i]];
}
}
appDelegate.activeFeedStories = [NSArray arrayWithArray:newActiveFeedStories];
[self refreshComments:@"like"];
}
- (void)requestFailed:(ASIHTTPRequest *)request {
NSLog(@"Error in mark as read is %@", [request error]);
}
- (void)finishMarkAsRead:(ASIHTTPRequest *)request {
NSString *responseString = [request responseString];
NSDictionary *results = [[NSDictionary alloc]
initWithDictionary:[responseString JSONValue]];
NSLog(@"results in mark as read is %@", results);
}
# pragma mark
# pragma mark Subscribing to blurblog
- (void)subscribeToBlurblog {
[self showFollowingHUD];
NSString *urlString = [NSString stringWithFormat:@"http://%@/social/follow",
NEWSBLUR_URL];
NSURL *url = [NSURL URLWithString:urlString];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:[appDelegate.activeFeed
objectForKey:@"user_id"]
forKey:@"user_id"];
[request setDidFinishSelector:@selector(finishSubscribeToBlurblog:)];
[request setDidFailSelector:@selector(requestFailed:)];
[request setDelegate:self];
[request startAsynchronous];
}
- (void)finishSubscribeToBlurblog:(ASIHTTPRequest *)request {
self.storyHUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"37x-Checkmark.png"]];
self.storyHUD.mode = MBProgressHUDModeCustomView;
self.storyHUD.removeFromSuperViewOnHide = YES;
self.storyHUD.labelText = @"Followed";
[self.storyHUD hide:YES afterDelay:1];
self.navigationItem.leftBarButtonItem = nil;
[appDelegate reloadFeedsView:NO];
// [appDelegate.feedDetailViewController resetFeedDetail];
// [appDelegate.feedDetailViewController fetchFeedDetail:1 withCallback:nil];
}
- (void)showShareHUD {
[MBProgressHUD hideHUDForView:self.view animated:NO];
self.storyHUD = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
self.storyHUD.labelText = @"Saving";
self.storyHUD.margin = 20.0f;
}
- (void)showFollowingHUD {
[MBProgressHUD hideHUDForView:self.view animated:NO];
self.storyHUD = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
self.storyHUD.labelText = @"Following";
self.storyHUD.margin = 20.0f;
}
- (void)showFindingStoryHUD {
[MBProgressHUD hideHUDForView:self.view animated:NO];
self.storyHUD = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
self.storyHUD.labelText = @"Loading Story";
self.storyHUD.margin = 20.0f;
self.noStorySelectedLabel.hidden = YES;
}
- (void)refreshComments:(NSString *)replyId {
NSString *commentString = [self getComments];
NSString *jsString = [[NSString alloc] initWithFormat:@
"document.getElementById('NB-comments-wrapper').innerHTML = '%@';",
commentString];
NSString *shareType = appDelegate.activeShareType;
[self.webView stringByEvaluatingJavaScriptFromString:jsString];
if (!replyId) {
NSString *currentUserId = [NSString stringWithFormat:@"%@", [appDelegate.dictUserProfile objectForKey:@"user_id"]];
NSString *jsFlashString = [[NSString alloc] initWithFormat:@"slideToComment('%@', true);", currentUserId];
[self.webView stringByEvaluatingJavaScriptFromString:jsFlashString];
} else if ([replyId isEqualToString:@"like"]) {
} else {
NSString *jsFlashString = [[NSString alloc] initWithFormat:@"slideToComment('%@', true);", replyId];
[self.webView stringByEvaluatingJavaScriptFromString:jsFlashString];
}
// // adding in a simulated delay
// sleep(4);
self.storyHUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"37x-Checkmark.png"]];
self.storyHUD.mode = MBProgressHUDModeCustomView;
self.storyHUD.removeFromSuperViewOnHide = YES;
if ([shareType isEqualToString:@"reply"]) {
self.storyHUD.labelText = @"Replied";
} else if ([shareType isEqualToString:@"edit-reply"]) {
self.storyHUD.labelText = @"Edited Reply";
} else if ([shareType isEqualToString:@"edit-share"]) {
self.storyHUD.labelText = @"Edited Comment";
} else if ([shareType isEqualToString:@"share"]) {
self.storyHUD.labelText = @"Shared";
} else if ([shareType isEqualToString:@"like-comment"]) {
self.storyHUD.labelText = @"Favorited";
} else if ([shareType isEqualToString:@"unlike-comment"]) {
self.storyHUD.labelText = @"Unfavorited";
}
[self.storyHUD hide:YES afterDelay:1];
}
- (void)scrolltoComment {
NSString *currentUserId = [NSString stringWithFormat:@"%@", [appDelegate.dictUserProfile objectForKey:@"user_id"]];
NSString *jsFlashString = [[NSString alloc] initWithFormat:@"slideToComment('%@', true);", currentUserId];
[self.webView stringByEvaluatingJavaScriptFromString:jsFlashString];
}
- (IBAction)doNextUnreadStory {
int nextIndex = [appDelegate indexOfNextUnreadStory];
int unreadCount = [appDelegate unreadCount];
[self.loadingIndicator stopAnimating];
if (self.appDelegate.feedDetailViewController.pageFetching) {
return;
}
if (nextIndex == -1 && unreadCount > 0 &&
self.appDelegate.feedDetailViewController.feedPage < 50 &&
!self.appDelegate.feedDetailViewController.pageFinished &&
!self.appDelegate.feedDetailViewController.pageFetching) {
// Fetch next page and see if it has the unreads.
[self.loadingIndicator startAnimating];
self.activity.customView = self.loadingIndicator;
[self.appDelegate.feedDetailViewController fetchNextPage:^() {
[self doNextUnreadStory];
}];
} else if (nextIndex == -1) {
[appDelegate.navigationController
popToViewController:[appDelegate.navigationController.viewControllers
objectAtIndex:0]
animated:YES];
[appDelegate hideStoryDetailView];
} else {
[appDelegate setActiveStory:[[appDelegate activeFeedStories]
objectAtIndex:nextIndex]];
[appDelegate pushReadStory:[appDelegate.activeStory objectForKey:@"id"]];
[self setActiveStory];
[self showStory];
[appDelegate changeActiveFeedDetailRow];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:.5];
[UIView setAnimationBeginsFromCurrentState:NO];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp
forView:self.webView
cache:NO];
[UIView commitAnimations];
}
}
- (IBAction)doNextStory {
int nextIndex = [appDelegate indexOfNextStory];
NSLog(@"nextIndex is %i", nextIndex);
[self.loadingIndicator stopAnimating];
if (self.appDelegate.feedDetailViewController.pageFetching) {
return;
}
if (nextIndex == -1 &&
self.appDelegate.feedDetailViewController.feedPage < 50 &&
!self.appDelegate.feedDetailViewController.pageFinished &&
!self.appDelegate.feedDetailViewController.pageFetching) {
// Fetch next page and see if it has the unreads.
[self.loadingIndicator startAnimating];
self.activity.customView = self.loadingIndicator;
[self.appDelegate.feedDetailViewController fetchNextPage:^() {
[self doNextStory];
}];
} else if (nextIndex == -1) {
[MBProgressHUD hideHUDForView:self.view animated:NO];
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.mode = MBProgressHUDModeText;
hud.removeFromSuperViewOnHide = YES;
hud.labelText = @"No stories left";
[hud hide:YES afterDelay:0.8];
} else {
[appDelegate setActiveStory:[[appDelegate activeFeedStories]
objectAtIndex:nextIndex]];
[appDelegate pushReadStory:[appDelegate.activeStory objectForKey:@"id"]];
[self setActiveStory];
[self showStory];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[appDelegate changeActiveFeedDetailRow];
}
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:.5];
[UIView setAnimationBeginsFromCurrentState:NO];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp
forView:self.webView
cache:NO];
[UIView commitAnimations];
}
}
- (IBAction)doPreviousStory {
[self.loadingIndicator stopAnimating];
id previousStoryId = [appDelegate popReadStory];
if (!previousStoryId || previousStoryId == [appDelegate.activeStory objectForKey:@"id"]) {
[appDelegate.navigationController
popToViewController:[appDelegate.navigationController.viewControllers
objectAtIndex:0]
animated:YES];
[appDelegate hideStoryDetailView];
} else {
int previousIndex = [appDelegate locationOfStoryId:previousStoryId];
if (previousIndex == -1) {
return [self doPreviousStory];
}
[appDelegate setActiveStory:[[appDelegate activeFeedStories]
objectAtIndex:previousIndex]];
[self setActiveStory];
[self showStory];
[appDelegate changeActiveFeedDetailRow];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:.5];
[UIView setAnimationBeginsFromCurrentState:NO];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown
forView:self.webView
cache:NO];
[UIView commitAnimations];
}
}
- (void)changeWebViewWidth:(int)width {
int contentWidth = self.view.frame.size.width;
NSString *contentWidthClass;
if (contentWidth > 740) {
contentWidthClass = @"NB-ipad-wide";
} else if (contentWidth > 500) {
contentWidthClass = @"NB-ipad-narrow";
} else {
contentWidthClass = @"NB-iphone";
}
NSString *jsString = [[NSString alloc] initWithFormat:
@"document.getElementsByTagName('body')[0].setAttribute('class', '%@');"
"document.getElementById(\"viewport\").setAttribute(\"content\", \"width=%i;initial-scale=1; maximum-scale=1.0; user-scalable=0;\");",
contentWidthClass,
contentWidth];
[self.webView stringByEvaluatingJavaScriptFromString:jsString];
}
- (IBAction)toggleFontSize:(id)sender {
// if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// if (popoverController == nil) {
// popoverController = [[UIPopoverController alloc]
// initWithContentViewController:appDelegate.fontSettingsViewController];
//
// popoverController.delegate = self;
// } else {
// if (popoverController.isPopoverVisible) {
// [popoverController dismissPopoverAnimated:YES];
// return;
// }
//
// [popoverController setContentViewController:appDelegate.fontSettingsViewController];
// }
//
// [popoverController setPopoverContentSize:CGSizeMake(274.0, 130.0)];
// UIBarButtonItem *settingsButton = [[UIBarButtonItem alloc]
// initWithCustomView:sender];
//
// [popoverController presentPopoverFromBarButtonItem:settingsButton
// permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
// } else {
// FontSettingsViewController *fontSettings = [[FontSettingsViewController alloc] init];
// appDelegate.fontSettingsViewController = fontSettings;
// UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:appDelegate.fontSettingsViewController];
//
// // adding Done button
// UIBarButtonItem *donebutton = [[UIBarButtonItem alloc]
// initWithTitle:@"Done"
// style:UIBarButtonItemStyleDone
// target:self
// action:@selector(hideToggleFontSize)];
//
// appDelegate.fontSettingsViewController.navigationItem.rightBarButtonItem = donebutton;
// appDelegate.fontSettingsViewController.navigationItem.title = @"Style";
// navController.navigationBar.tintColor = [UIColor colorWithRed:0.16f green:0.36f blue:0.46 alpha:0.9];
// [self presentModalViewController:navController animated:YES];
//
// }
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[appDelegate.masterContainerViewController showFontSettingsPopover:sender];
} else {
if (self.popoverController == nil) {
self.popoverController = [[WEPopoverController alloc]
initWithContentViewController:appDelegate.fontSettingsViewController];
self.popoverController.delegate = self;
} else {
[self.popoverController dismissPopoverAnimated:YES];
self.popoverController = nil;
}
if ([self.popoverController respondsToSelector:@selector(setContainerViewProperties:)]) {
[self.popoverController setContainerViewProperties:[self improvedContainerViewProperties]];
}
[self.popoverController setPopoverContentSize:CGSizeMake(274, 130)];
[self.popoverController presentPopoverFromBarButtonItem:self.fontSettingsButton
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
}
- (void)changeFontSize:(NSString *)fontSize {
NSString *jsString = [[NSString alloc] initWithFormat:@"document.getElementById('NB-font-size').setAttribute('class', '%@')",
fontSize];
[self.webView stringByEvaluatingJavaScriptFromString:jsString];
}
- (void)setFontStyle:(NSString *)fontStyle {
NSString *jsString;
NSString *fontStyleStr;
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
if ([fontStyle isEqualToString:@"Helvetica"]) {
[userPreferences setObject:@"NB-san-serif" forKey:@"fontStyle"];
fontStyleStr = @"NB-san-serif";
} else {
[userPreferences setObject:@"NB-serif" forKey:@"fontStyle"];
fontStyleStr = @"NB-serif";
}
[userPreferences synchronize];
jsString = [NSString stringWithFormat:@
"document.getElementById('NB-font-style').setAttribute('class', '%@')",
fontStyleStr];
[self.webView stringByEvaluatingJavaScriptFromString:jsString];
}
- (IBAction)showOriginalSubview:(id)sender {
NSURL *url = [NSURL URLWithString:[appDelegate.activeStory
objectForKey:@"story_permalink"]];
[appDelegate showOriginalStory:url];
}
- (NSString *)textToHtml:(NSString*)htmlString {
htmlString = [htmlString stringByReplacingOccurrencesOfString:@"'" withString:@"'"];
return htmlString;
}
#pragma mark -
#pragma mark WEPopoverControllerDelegate implementation
- (void)popoverControllerDidDismissPopover:(WEPopoverController *)thePopoverController {
//Safe to release the popover here
self.popoverController = nil;
}
- (BOOL)popoverControllerShouldDismissPopover:(WEPopoverController *)thePopoverController {
//The popover is automatically dismissed if you click outside it, unless you return NO here
return YES;
}
/**
Thanks to Paul Solt for supplying these background images and container view properties
*/
- (WEPopoverContainerViewProperties *)improvedContainerViewProperties {
WEPopoverContainerViewProperties *props = [WEPopoverContainerViewProperties alloc];
NSString *bgImageName = nil;
CGFloat bgMargin = 0.0;
CGFloat bgCapSize = 0.0;
CGFloat contentMargin = 5.0;
bgImageName = @"popoverBg.png";
// These constants are determined by the popoverBg.png image file and are image dependent
bgMargin = 13; // margin width of 13 pixels on all sides popoverBg.png (62 pixels wide - 36 pixel background) / 2 == 26 / 2 == 13
bgCapSize = 31; // ImageSize/2 == 62 / 2 == 31 pixels
props.leftBgMargin = bgMargin;
props.rightBgMargin = bgMargin;
props.topBgMargin = bgMargin;
props.bottomBgMargin = bgMargin;
props.leftBgCapSize = bgCapSize;
props.topBgCapSize = bgCapSize;
props.bgImageName = bgImageName;
props.leftContentMargin = contentMargin;
props.rightContentMargin = contentMargin - 1; // Need to shift one pixel for border to look correct
props.topContentMargin = contentMargin;
props.bottomContentMargin = contentMargin;
props.arrowMargin = 4.0;
props.upArrowImageName = @"popoverArrowUp.png";
props.downArrowImageName = @"popoverArrowDown.png";
props.leftArrowImageName = @"popoverArrowLeft.png";
props.rightArrowImageName = @"popoverArrowRight.png";
return props;
}
@end