2011-08-25 12:09:41 -07:00
|
|
|
//
|
2010-06-20 11:04:23 -04:00
|
|
|
// NewsBlurViewController.m
|
|
|
|
// NewsBlur
|
|
|
|
//
|
|
|
|
// Created by Samuel Clay on 6/16/10.
|
|
|
|
// Copyright NewsBlur 2010. All rights reserved.
|
|
|
|
//
|
|
|
|
|
2012-06-19 11:48:51 -07:00
|
|
|
#import "NewsBlurViewController.h"
|
2010-06-21 17:17:26 -04:00
|
|
|
#import "NewsBlurAppDelegate.h"
|
2012-07-25 17:29:29 -07:00
|
|
|
#import "NBContainerViewController.h"
|
2012-07-10 16:48:05 -07:00
|
|
|
#import "DashboardViewController.h"
|
2013-02-21 16:53:37 -08:00
|
|
|
#import "InteractionsModule.h"
|
|
|
|
#import "ActivityModule.h"
|
2011-07-18 09:56:48 -07:00
|
|
|
#import "FeedTableCell.h"
|
2012-06-19 13:51:48 -07:00
|
|
|
#import "FeedsMenuViewController.h"
|
2012-10-12 13:58:26 -04:00
|
|
|
#import "FeedDetailMenuViewController.h"
|
2012-07-12 00:10:42 -07:00
|
|
|
#import "UserProfileViewController.h"
|
2012-07-24 16:03:16 -07:00
|
|
|
#import "StoryDetailViewController.h"
|
2012-11-06 17:26:08 -08:00
|
|
|
#import "StoryPageControl.h"
|
2011-08-04 17:58:28 -07:00
|
|
|
#import "ASIHTTPRequest.h"
|
|
|
|
#import "PullToRefreshView.h"
|
2011-08-13 23:00:51 -07:00
|
|
|
#import "MBProgressHUD.h"
|
2011-08-03 10:00:41 -07:00
|
|
|
#import "Base64.h"
|
2011-10-17 09:28:40 -07:00
|
|
|
#import "Utilities.h"
|
2012-07-31 13:10:26 -07:00
|
|
|
#import "UIBarButtonItem+WEPopover.h"
|
2013-03-03 17:37:54 -08:00
|
|
|
#import "AddSiteViewController.h"
|
2012-07-31 13:10:26 -07:00
|
|
|
|
2012-10-15 14:57:20 -07:00
|
|
|
#define kPhoneTableViewRowHeight 31;
|
|
|
|
#define kTableViewRowHeight 31;
|
2012-11-28 12:36:48 -08:00
|
|
|
#define kBlurblogTableViewRowHeight 32;
|
|
|
|
#define kPhoneBlurblogTableViewRowHeight 32;
|
2012-10-02 15:39:18 -07:00
|
|
|
static const CGFloat kFolderTitleHeight = 28;
|
2011-07-19 09:38:49 -07:00
|
|
|
|
2012-08-09 10:18:15 -07:00
|
|
|
@interface NewsBlurViewController ()
|
|
|
|
|
|
|
|
@property (nonatomic, strong) NSMutableDictionary *updatedDictSocialFeeds_;
|
|
|
|
@property (nonatomic, strong) NSMutableDictionary *updatedDictFeeds_;
|
2012-08-16 20:10:50 -07:00
|
|
|
@property (readwrite) BOOL inPullToRefresh_;
|
2012-08-09 10:18:15 -07:00
|
|
|
|
|
|
|
@end
|
|
|
|
|
2012-06-19 11:48:51 -07:00
|
|
|
@implementation NewsBlurViewController
|
2010-06-21 17:17:26 -04:00
|
|
|
|
|
|
|
@synthesize appDelegate;
|
2012-07-14 01:16:35 -07:00
|
|
|
@synthesize innerView;
|
2011-08-02 09:16:54 -07:00
|
|
|
@synthesize feedTitlesTable;
|
2010-06-20 11:04:23 -04:00
|
|
|
@synthesize feedViewToolbar;
|
2010-06-21 17:17:26 -04:00
|
|
|
@synthesize feedScoreSlider;
|
2012-06-19 10:55:46 -07:00
|
|
|
@synthesize homeButton;
|
2011-08-02 09:16:54 -07:00
|
|
|
@synthesize intelligenceControl;
|
2011-08-02 10:13:06 -07:00
|
|
|
@synthesize activeFeedLocations;
|
2011-10-31 10:10:38 -07:00
|
|
|
@synthesize stillVisibleFeeds;
|
2012-12-20 12:21:44 -08:00
|
|
|
@synthesize visibleFolders;
|
2011-08-04 17:27:31 -07:00
|
|
|
@synthesize viewShowingAllFeeds;
|
2011-08-04 17:58:28 -07:00
|
|
|
@synthesize pull;
|
|
|
|
@synthesize lastUpdate;
|
2011-10-14 09:51:27 -07:00
|
|
|
@synthesize imageCache;
|
2012-06-19 13:51:48 -07:00
|
|
|
@synthesize popoverController;
|
2012-07-15 16:46:46 -07:00
|
|
|
@synthesize currentRowAtIndexPath;
|
2012-08-15 19:31:34 -07:00
|
|
|
@synthesize noFocusMessage;
|
|
|
|
@synthesize toolbarLeftMargin;
|
2012-08-09 10:18:15 -07:00
|
|
|
@synthesize updatedDictFeeds_;
|
|
|
|
@synthesize updatedDictSocialFeeds_;
|
2012-08-16 20:10:50 -07:00
|
|
|
@synthesize inPullToRefresh_;
|
2013-02-20 17:00:01 -08:00
|
|
|
@synthesize addBarButton;
|
|
|
|
@synthesize settingsBarButton;
|
2013-02-26 19:39:13 -08:00
|
|
|
@synthesize activitiesButton;
|
2010-06-20 11:04:23 -04:00
|
|
|
|
2010-06-21 17:17:26 -04:00
|
|
|
#pragma mark -
|
2011-08-24 21:44:16 -07:00
|
|
|
#pragma mark Globals
|
2010-06-21 17:17:26 -04:00
|
|
|
|
2010-06-20 11:04:23 -04:00
|
|
|
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
|
2010-06-21 17:17:26 -04:00
|
|
|
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
|
2010-06-20 11:04:23 -04:00
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)viewDidLoad {
|
2012-07-31 13:10:26 -07:00
|
|
|
[super viewDidLoad];
|
|
|
|
popoverClass = [WEPopoverController class];
|
|
|
|
|
2013-02-14 15:36:21 -08:00
|
|
|
self.navigationController.navigationBar.tintColor = UIColorFromRGB(0xE8EBE4);
|
2011-08-24 21:44:16 -07:00
|
|
|
pull = [[PullToRefreshView alloc] initWithScrollView:self.feedTitlesTable];
|
2011-08-04 17:58:28 -07:00
|
|
|
[pull setDelegate:self];
|
|
|
|
[self.feedTitlesTable addSubview:pull];
|
2011-08-24 21:44:16 -07:00
|
|
|
|
2011-08-26 09:34:30 -07:00
|
|
|
[[NSNotificationCenter defaultCenter]
|
|
|
|
addObserver:self
|
|
|
|
selector:@selector(returnToApp)
|
|
|
|
name:UIApplicationWillEnterForegroundNotification
|
|
|
|
object:nil];
|
2011-08-24 21:44:16 -07:00
|
|
|
|
2011-10-14 09:51:27 -07:00
|
|
|
imageCache = [[NSCache alloc] init];
|
|
|
|
[imageCache setDelegate:self];
|
2012-08-09 16:34:59 -07:00
|
|
|
|
2013-02-26 19:39:13 -08:00
|
|
|
[self.intelligenceControl setWidth:36 forSegmentAtIndex:0];
|
|
|
|
[self.intelligenceControl setWidth:64 forSegmentAtIndex:1];
|
2012-08-15 19:31:34 -07:00
|
|
|
[self.intelligenceControl setWidth:62 forSegmentAtIndex:2];
|
|
|
|
self.intelligenceControl.hidden = YES;
|
2013-02-26 19:39:13 -08:00
|
|
|
|
|
|
|
UIImage *unselectedBackgroundImage = [[UIImage imageNamed:@"segment_inactive"]
|
|
|
|
resizableImageWithCapInsets:UIEdgeInsetsMake(6, 6, 6, 6)];
|
|
|
|
[[UISegmentedControl appearance] setBackgroundImage:unselectedBackgroundImage
|
|
|
|
forState:UIControlStateNormal
|
|
|
|
barMetrics:UIBarMetricsDefault];
|
|
|
|
UIImage *selectedBackgroundImage = [[UIImage imageNamed:@"segment_active"]
|
|
|
|
resizableImageWithCapInsets:UIEdgeInsetsMake(6, 6, 6, 6)];
|
|
|
|
[[UISegmentedControl appearance] setBackgroundImage:selectedBackgroundImage
|
|
|
|
forState:UIControlStateSelected
|
|
|
|
barMetrics:UIBarMetricsDefault];
|
|
|
|
UIImage *bothUnselectedImage = [[UIImage imageNamed:@"segment_unselected"]
|
|
|
|
resizableImageWithCapInsets:UIEdgeInsetsMake(6, 6, 6, 6)];
|
|
|
|
[[UISegmentedControl appearance] setDividerImage:bothUnselectedImage
|
|
|
|
forLeftSegmentState:UIControlStateNormal
|
|
|
|
rightSegmentState:UIControlStateNormal
|
|
|
|
barMetrics:UIBarMetricsDefault];
|
|
|
|
UIImage *leftSelectedImage = [[UIImage imageNamed:@"segment_left_selected"]
|
|
|
|
resizableImageWithCapInsets:UIEdgeInsetsMake(6, 6, 6, 6)];
|
|
|
|
[[UISegmentedControl appearance] setDividerImage:leftSelectedImage
|
|
|
|
forLeftSegmentState:UIControlStateSelected
|
|
|
|
rightSegmentState:UIControlStateNormal
|
|
|
|
barMetrics:UIBarMetricsDefault];
|
|
|
|
UIImage *rightSelectedImage = [[UIImage imageNamed:@"segment_right_selected"]
|
|
|
|
resizableImageWithCapInsets:UIEdgeInsetsMake(6, 6, 6, 6)];
|
|
|
|
[[UISegmentedControl appearance] setDividerImage:rightSelectedImage
|
|
|
|
forLeftSegmentState:UIControlStateNormal
|
|
|
|
rightSegmentState:UIControlStateSelected
|
|
|
|
barMetrics:UIBarMetricsDefault];
|
|
|
|
[[UISegmentedControl appearance]
|
|
|
|
setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
[UIFont boldSystemFontOfSize:11.0f], UITextAttributeFont,
|
|
|
|
UIColorFromRGB(0x505050), UITextAttributeTextColor,
|
|
|
|
UIColorFromRGB(0xF0F0F0), UITextAttributeTextShadowColor,
|
|
|
|
[NSValue valueWithUIOffset:UIOffsetMake(0, -1)], UITextAttributeTextShadowOffset,
|
|
|
|
nil]
|
|
|
|
forState:UIControlStateNormal];
|
|
|
|
[[UISegmentedControl appearance]
|
|
|
|
setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
[UIFont boldSystemFontOfSize:11.0f], UITextAttributeFont,
|
|
|
|
UIColorFromRGB(0x505050), UITextAttributeTextColor,
|
|
|
|
UIColorFromRGB(0xF0F0F0), UITextAttributeTextShadowColor,
|
|
|
|
[NSValue valueWithUIOffset:UIOffsetMake(0, -1)], UITextAttributeTextShadowOffset,
|
|
|
|
nil]
|
|
|
|
forState:UIControlStateSelected];
|
|
|
|
[[UISegmentedControl appearance] setContentPositionAdjustment:UIOffsetMake(4, 0) forSegmentType:UISegmentedControlSegmentLeft barMetrics:UIBarMetricsDefault];
|
|
|
|
[[UISegmentedControl appearance] setContentPositionAdjustment:UIOffsetMake(-4, 0) forSegmentType:UISegmentedControlSegmentRight barMetrics:UIBarMetricsDefault];
|
2012-07-31 13:10:26 -07:00
|
|
|
|
2013-02-26 19:39:13 -08:00
|
|
|
|
2013-02-27 19:25:57 -08:00
|
|
|
UIImage *i1 = [[UIImage imageNamed:@"back_button_background.png"]
|
|
|
|
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 18, 0, 6)];
|
|
|
|
UIImage *i2 = [[UIImage imageNamed:@"back_button_landscape_background.png"]
|
|
|
|
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 18, 0, 6)];
|
|
|
|
UIImage *i3 = [[UIImage imageNamed:@"back_button_selected_background.png"]
|
|
|
|
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 18, 0, 6)];
|
|
|
|
UIImage *i4 = [[UIImage imageNamed:@"back_button_landscape_selected_background.png"]
|
|
|
|
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 18, 0, 6)];
|
|
|
|
|
|
|
|
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:i1
|
|
|
|
forState:UIControlStateNormal
|
|
|
|
barMetrics:UIBarMetricsDefault];
|
|
|
|
|
|
|
|
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:i2
|
|
|
|
forState:UIControlStateNormal
|
|
|
|
barMetrics:UIBarMetricsLandscapePhone];
|
|
|
|
|
|
|
|
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:i3
|
|
|
|
forState:UIControlStateHighlighted
|
|
|
|
barMetrics:UIBarMetricsDefault];
|
|
|
|
|
|
|
|
[[UIBarButtonItem appearance] setBackButtonBackgroundImage:i4
|
|
|
|
forState:UIControlStateHighlighted
|
|
|
|
barMetrics:UIBarMetricsLandscapePhone];
|
2013-02-28 17:07:51 -08:00
|
|
|
|
|
|
|
UIImage *b1 = [[UIImage imageNamed:@"button.png"]
|
|
|
|
resizableImageWithCapInsets:UIEdgeInsetsMake(6, 6, 6, 6)];
|
|
|
|
UIImage *b2 = [[UIImage imageNamed:@"button_selected.png"]
|
|
|
|
resizableImageWithCapInsets:UIEdgeInsetsMake(6, 6, 6, 6)];
|
2013-03-02 19:15:08 -08:00
|
|
|
UIImage *b3 = [[UIImage imageNamed:@"toolbar_button_landscape.png"]
|
|
|
|
resizableImageWithCapInsets:UIEdgeInsetsMake(6, 6, 6, 6)];
|
|
|
|
UIImage *b4 = [[UIImage imageNamed:@"toolbar_button_landscape_selected.png"]
|
|
|
|
resizableImageWithCapInsets:UIEdgeInsetsMake(6, 6, 6, 6)];
|
2013-02-28 17:07:51 -08:00
|
|
|
|
|
|
|
[[UIBarButtonItem appearance] setBackgroundImage:b1
|
|
|
|
forState:UIControlStateNormal
|
|
|
|
barMetrics:UIBarMetricsDefault];
|
|
|
|
[[UIBarButtonItem appearance] setBackgroundImage:b2
|
|
|
|
forState:UIControlStateHighlighted
|
|
|
|
barMetrics:UIBarMetricsDefault];
|
2013-03-02 19:15:08 -08:00
|
|
|
[[UIBarButtonItem appearance] setBackgroundImage:b3
|
|
|
|
forState:UIControlStateNormal
|
|
|
|
barMetrics:UIBarMetricsLandscapePhone];
|
|
|
|
[[UIBarButtonItem appearance] setBackgroundImage:b4
|
|
|
|
forState:UIControlStateHighlighted
|
|
|
|
barMetrics:UIBarMetricsLandscapePhone];
|
2013-02-28 17:07:51 -08:00
|
|
|
|
|
|
|
[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil]
|
|
|
|
setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
UIColorFromRGB(0x404040), UITextAttributeTextColor,
|
|
|
|
UIColorFromRGB(0xFAFAFA), UITextAttributeTextShadowColor,
|
|
|
|
[NSValue valueWithUIOffset:UIOffsetMake(0, -1)], UITextAttributeTextShadowOffset,
|
|
|
|
nil]
|
|
|
|
forState:UIControlStateNormal];
|
2013-02-27 19:25:57 -08:00
|
|
|
[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil]
|
|
|
|
setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
UIColorFromRGB(0xF0F0F0), UITextAttributeTextColor,
|
|
|
|
UIColorFromRGB(0x202020), UITextAttributeTextShadowColor,
|
|
|
|
[NSValue valueWithUIOffset:UIOffsetMake(0, -1)], UITextAttributeTextShadowOffset,
|
|
|
|
nil]
|
|
|
|
forState:UIControlStateHighlighted];
|
|
|
|
|
|
|
|
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
|
|
|
|
[self layoutForInterfaceOrientation:orientation];
|
|
|
|
|
2012-12-11 11:50:06 -08:00
|
|
|
appDelegate.activeClassifiers = [NSMutableDictionary dictionary];
|
2010-06-20 11:04:23 -04:00
|
|
|
}
|
|
|
|
|
2010-06-25 18:36:01 -04:00
|
|
|
- (void)viewWillAppear:(BOOL)animated {
|
2012-07-26 19:15:25 -07:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
|
|
|
[appDelegate.masterContainerViewController transitionFromFeedDetail];
|
2012-08-02 18:00:48 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
|
|
|
|
[self setUserAvatarLayout:orientation];
|
2012-07-26 19:15:25 -07:00
|
|
|
|
2012-07-15 16:46:46 -07:00
|
|
|
[super viewWillAppear:animated];
|
2012-07-16 19:45:14 -07:00
|
|
|
|
|
|
|
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
|
|
|
|
|
|
|
|
if ([userPreferences integerForKey:@"selectedIntelligence"] == 1) {
|
|
|
|
self.viewShowingAllFeeds = NO;
|
|
|
|
[self.intelligenceControl setSelectedSegmentIndex:2];
|
|
|
|
[appDelegate setSelectedIntelligence:1];
|
|
|
|
} else if ([userPreferences integerForKey:@"selectedIntelligence"] == 0) {
|
|
|
|
self.viewShowingAllFeeds = NO;
|
|
|
|
[self.intelligenceControl setSelectedSegmentIndex:1];
|
|
|
|
[appDelegate setSelectedIntelligence:0];
|
2012-08-16 20:10:50 -07:00
|
|
|
} else { // default state, ALL BLURBLOG STORIES
|
2012-07-16 19:45:14 -07:00
|
|
|
self.viewShowingAllFeeds = YES;
|
|
|
|
[self.intelligenceControl setSelectedSegmentIndex:0];
|
|
|
|
[appDelegate setSelectedIntelligence:0];
|
|
|
|
}
|
|
|
|
|
2012-07-18 21:41:38 -07:00
|
|
|
// self.feedTitlesTable.separatorStyle = UITableViewCellSeparatorStyleNone; // DO NOT USE. THIS BREAKS SHIT.
|
|
|
|
UIColor *bgColor = [UIColor colorWithRed:0.95 green:0.95 blue:0.95 alpha:1.0];
|
|
|
|
self.feedTitlesTable.backgroundColor = bgColor;
|
2012-07-18 12:17:55 -07:00
|
|
|
|
2012-07-20 19:55:38 -07:00
|
|
|
self.feedTitlesTable.separatorColor = [UIColor clearColor];
|
|
|
|
|
2012-07-16 19:45:14 -07:00
|
|
|
// reset all feed detail specific data
|
|
|
|
appDelegate.activeFeed = nil;
|
|
|
|
appDelegate.isSocialView = NO;
|
|
|
|
appDelegate.isRiverView = NO;
|
2012-07-29 20:55:11 -07:00
|
|
|
appDelegate.inFindingStoryMode = NO;
|
2012-11-06 17:26:08 -08:00
|
|
|
[MBProgressHUD hideHUDForView:appDelegate.storyPageControl.view animated:NO];
|
2012-07-16 19:45:14 -07:00
|
|
|
|
2011-11-29 17:57:20 -08:00
|
|
|
if (appDelegate.activeFeed || appDelegate.isRiverView) {
|
2011-08-24 21:44:16 -07:00
|
|
|
NSInteger previousLevel = [self.intelligenceControl selectedSegmentIndex] - 1;
|
|
|
|
NSInteger newLevel = [appDelegate selectedIntelligence];
|
|
|
|
if (newLevel != previousLevel) {
|
2011-08-27 15:53:51 -07:00
|
|
|
[appDelegate setSelectedIntelligence:newLevel];
|
2012-12-20 12:08:35 -08:00
|
|
|
[self calculateFeedLocations];
|
|
|
|
[self.feedTitlesTable beginUpdates];
|
|
|
|
[self.feedTitlesTable endUpdates];
|
2011-08-27 15:53:51 -07:00
|
|
|
[self redrawUnreadCounts];
|
2011-08-24 21:44:16 -07:00
|
|
|
}
|
|
|
|
}
|
2012-07-15 16:46:46 -07:00
|
|
|
|
2012-08-02 18:00:48 -07:00
|
|
|
// perform these only if coming from the feed detail view
|
|
|
|
if (appDelegate.inFeedDetail) {
|
|
|
|
appDelegate.inFeedDetail = NO;
|
|
|
|
// reload the data and then set the highlight again
|
|
|
|
[self.feedTitlesTable reloadData];
|
2013-02-15 16:41:20 -08:00
|
|
|
[self refreshHeaderCounts];
|
2012-08-02 18:00:48 -07:00
|
|
|
[self redrawUnreadCounts];
|
|
|
|
[self.feedTitlesTable selectRowAtIndexPath:self.currentRowAtIndexPath
|
|
|
|
animated:NO
|
|
|
|
scrollPosition:UITableViewScrollPositionNone];
|
|
|
|
}
|
|
|
|
|
2010-06-25 18:36:01 -04:00
|
|
|
}
|
|
|
|
|
2010-06-21 17:17:26 -04:00
|
|
|
- (void)viewDidAppear:(BOOL)animated {
|
2012-07-27 19:42:19 -07:00
|
|
|
// [self.feedTitlesTable selectRowAtIndexPath:self.currentRowAtIndexPath
|
|
|
|
// animated:NO
|
|
|
|
// scrollPosition:UITableViewScrollPositionNone];
|
|
|
|
|
2011-08-24 21:44:16 -07:00
|
|
|
[super viewDidAppear:animated];
|
2012-10-04 15:44:25 -07:00
|
|
|
[self performSelector:@selector(fadeSelectedCell) withObject:self afterDelay:0.2];
|
2012-08-15 19:31:34 -07:00
|
|
|
self.navigationController.navigationBar.backItem.title = @"All Sites";
|
2012-07-27 19:42:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)fadeSelectedCell {
|
2012-07-18 17:23:57 -07:00
|
|
|
[self.feedTitlesTable deselectRowAtIndexPath:[self.feedTitlesTable indexPathForSelectedRow]
|
|
|
|
animated:YES];
|
2010-06-21 17:17:26 -04:00
|
|
|
}
|
2012-07-31 15:57:56 -07:00
|
|
|
|
2010-06-21 17:17:26 -04:00
|
|
|
- (void)viewWillDisappear:(BOOL)animated {
|
2012-07-31 13:10:26 -07:00
|
|
|
[self.popoverController dismissPopoverAnimated:YES];
|
|
|
|
self.popoverController = nil;
|
2012-06-19 14:27:35 -07:00
|
|
|
[super viewWillDisappear:animated];
|
|
|
|
}
|
|
|
|
|
2012-06-08 10:37:51 -07:00
|
|
|
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
|
|
|
|
// Return YES for supported orientations
|
2012-06-08 19:21:10 -07:00
|
|
|
return YES;
|
2012-06-07 11:42:29 -07:00
|
|
|
}
|
|
|
|
|
2012-06-29 23:25:56 -07:00
|
|
|
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
|
2012-08-02 18:00:48 -07:00
|
|
|
[self setUserAvatarLayout:toInterfaceOrientation];
|
2013-02-27 19:25:57 -08:00
|
|
|
[self layoutForInterfaceOrientation:toInterfaceOrientation];
|
2013-03-03 15:41:59 -08:00
|
|
|
[self refreshHeaderCounts:toInterfaceOrientation];
|
2012-08-02 18:00:48 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setUserAvatarLayout:(UIInterfaceOrientation)orientation {
|
2012-07-29 22:14:08 -07:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
|
2012-08-02 18:00:48 -07:00
|
|
|
if (UIInterfaceOrientationIsPortrait(orientation)) {
|
2012-07-29 22:14:08 -07:00
|
|
|
UIButton *avatar = (UIButton *)self.navigationItem.leftBarButtonItem.customView;
|
|
|
|
CGRect buttonFrame = avatar.frame;
|
|
|
|
buttonFrame.size = CGSizeMake(32, 32);
|
|
|
|
avatar.frame = buttonFrame;
|
|
|
|
} else {
|
|
|
|
UIButton *avatar = (UIButton *)self.navigationItem.leftBarButtonItem.customView;
|
|
|
|
CGRect buttonFrame = avatar.frame;
|
|
|
|
buttonFrame.size = CGSizeMake(28, 28);
|
|
|
|
avatar.frame = buttonFrame;
|
|
|
|
}
|
|
|
|
}
|
2012-06-29 23:25:56 -07:00
|
|
|
}
|
|
|
|
|
2012-07-20 22:00:30 -07:00
|
|
|
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
|
|
|
|
[self.feedTitlesTable reloadData];
|
|
|
|
}
|
|
|
|
|
2010-06-20 11:04:23 -04:00
|
|
|
- (void)didReceiveMemoryWarning {
|
2011-08-24 21:44:16 -07:00
|
|
|
// Releases the view if it doesn't have a superview.
|
2010-06-20 11:04:23 -04:00
|
|
|
[super didReceiveMemoryWarning];
|
2011-08-24 21:44:16 -07:00
|
|
|
|
|
|
|
// Release any cached data, images, etc that aren't in use.
|
2010-06-20 11:04:23 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)viewDidUnload {
|
2012-08-15 19:31:34 -07:00
|
|
|
[self setToolbarLeftMargin:nil];
|
|
|
|
[self setNoFocusMessage:nil];
|
2012-07-14 01:16:35 -07:00
|
|
|
[self setInnerView:nil];
|
2011-08-24 21:44:16 -07:00
|
|
|
// Release any retained subviews of the main view.
|
|
|
|
// e.g. self.myOutlet = nil;
|
2010-06-20 11:04:23 -04:00
|
|
|
}
|
|
|
|
|
2013-02-27 19:25:57 -08:00
|
|
|
- (void) layoutForInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
|
|
|
|
CGSize toolbarSize = [self.feedViewToolbar sizeThatFits:self.view.bounds.size];
|
2013-03-03 15:08:23 -08:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
|
|
|
self.feedViewToolbar.frame = CGRectMake(-10.0f,
|
|
|
|
CGRectGetHeight(self.view.bounds) - toolbarSize.height,
|
|
|
|
toolbarSize.width + 20, toolbarSize.height);
|
|
|
|
} else {
|
|
|
|
self.feedViewToolbar.frame = (CGRect){CGPointMake(0.f, CGRectGetHeight(self.view.bounds) - toolbarSize.height), toolbarSize};
|
|
|
|
}
|
2013-02-27 19:25:57 -08:00
|
|
|
self.innerView.frame = (CGRect){CGPointZero, CGSizeMake(CGRectGetWidth(self.view.bounds), CGRectGetMinY(self.feedViewToolbar.frame))};
|
2013-03-01 15:48:18 -08:00
|
|
|
|
|
|
|
int height = 16;
|
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone &&
|
|
|
|
UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
|
|
|
|
height = 8;
|
|
|
|
}
|
|
|
|
|
2013-02-27 19:25:57 -08:00
|
|
|
self.intelligenceControl.frame = CGRectMake(self.intelligenceControl.frame.origin.x,
|
|
|
|
self.intelligenceControl.frame.origin.y,
|
|
|
|
self.intelligenceControl.frame.size.width,
|
|
|
|
self.feedViewToolbar.frame.size.height -
|
2013-03-01 15:48:18 -08:00
|
|
|
height);
|
2013-03-03 15:41:59 -08:00
|
|
|
[self refreshHeaderCounts];
|
2013-02-27 19:25:57 -08:00
|
|
|
}
|
2010-06-20 11:04:23 -04:00
|
|
|
|
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
#pragma mark Initialization
|
|
|
|
|
2011-08-18 21:48:30 -07:00
|
|
|
- (void)returnToApp {
|
2011-10-18 17:44:05 -07:00
|
|
|
NSDate *decayDate = [[NSDate alloc] initWithTimeIntervalSinceNow:(BACKGROUND_REFRESH_SECONDS)];
|
2011-08-24 21:44:16 -07:00
|
|
|
NSLog(@"Last Update: %@ - %f", self.lastUpdate, [self.lastUpdate timeIntervalSinceDate:decayDate]);
|
|
|
|
if ([self.lastUpdate timeIntervalSinceDate:decayDate] < 0) {
|
2012-08-09 10:18:15 -07:00
|
|
|
[self fetchFeedList:YES];
|
2011-08-24 21:44:16 -07:00
|
|
|
}
|
2012-07-11 20:19:42 -07:00
|
|
|
|
2011-08-18 21:48:30 -07:00
|
|
|
}
|
|
|
|
|
2012-08-09 10:18:15 -07:00
|
|
|
-(void)fetchFeedList:(BOOL)showLoader {
|
2011-09-07 09:56:54 -07:00
|
|
|
if (showLoader && appDelegate.navigationController.topViewController == appDelegate.feedsViewController) {
|
2011-09-16 09:26:22 -07:00
|
|
|
[MBProgressHUD hideHUDForView:self.view animated:YES];
|
2011-08-24 21:44:16 -07:00
|
|
|
MBProgressHUD *HUD = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
|
|
|
|
HUD.labelText = @"On its way...";
|
|
|
|
}
|
2012-07-02 11:42:06 -07:00
|
|
|
|
2012-08-16 20:10:50 -07:00
|
|
|
NSURL *urlFeedList;
|
|
|
|
|
|
|
|
if (self.inPullToRefresh_) {
|
|
|
|
urlFeedList = [NSURL URLWithString:
|
|
|
|
[NSString stringWithFormat:@"http://%@/reader/feeds?flat=true",
|
|
|
|
NEWSBLUR_URL]];
|
|
|
|
} else {
|
|
|
|
urlFeedList = [NSURL URLWithString:
|
|
|
|
[NSString stringWithFormat:@"http://%@/reader/feeds?flat=true&update_counts=false",
|
|
|
|
NEWSBLUR_URL]];
|
|
|
|
}
|
|
|
|
|
2011-09-05 22:06:31 -07:00
|
|
|
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:urlFeedList];
|
2011-10-15 17:48:10 -07:00
|
|
|
[[NSHTTPCookieStorage sharedHTTPCookieStorage]
|
|
|
|
setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
|
2011-09-05 22:06:31 -07:00
|
|
|
[request setDelegate:self];
|
|
|
|
[request setResponseEncoding:NSUTF8StringEncoding];
|
|
|
|
[request setDefaultResponseEncoding:NSUTF8StringEncoding];
|
|
|
|
[request setDidFinishSelector:@selector(finishLoadingFeedList:)];
|
|
|
|
[request setDidFailSelector:@selector(finishedWithError:)];
|
|
|
|
[request setTimeOutSeconds:30];
|
|
|
|
[request startAsynchronous];
|
2012-10-17 15:07:53 -07:00
|
|
|
|
2011-08-24 21:44:16 -07:00
|
|
|
self.lastUpdate = [NSDate date];
|
2010-06-20 11:04:23 -04:00
|
|
|
}
|
|
|
|
|
2011-10-14 17:15:48 -07:00
|
|
|
- (void)finishedWithError:(ASIHTTPRequest *)request {
|
2011-08-24 21:44:16 -07:00
|
|
|
[MBProgressHUD hideHUDForView:self.view animated:YES];
|
|
|
|
[pull finishedLoading];
|
|
|
|
|
|
|
|
// User clicking on another link before the page loads is OK.
|
2011-10-27 09:44:58 -07:00
|
|
|
[self informError:[request error]];
|
2012-08-16 20:10:50 -07:00
|
|
|
self.inPullToRefresh_ = NO;
|
2010-11-13 13:42:20 -05:00
|
|
|
}
|
|
|
|
|
2011-09-05 22:06:31 -07:00
|
|
|
- (void)finishLoadingFeedList:(ASIHTTPRequest *)request {
|
|
|
|
if ([request responseStatusCode] == 403) {
|
2011-11-30 09:38:31 -08:00
|
|
|
return [appDelegate showLogin];
|
2012-11-13 12:28:16 -08:00
|
|
|
} else if ([request responseStatusCode] == 404 ||
|
2012-12-27 18:37:05 -08:00
|
|
|
[request responseStatusCode] == 429 ||
|
2012-11-13 12:28:16 -08:00
|
|
|
[request responseStatusCode] >= 500) {
|
2011-11-30 09:38:31 -08:00
|
|
|
[pull finishedLoading];
|
2012-12-27 18:37:05 -08:00
|
|
|
if ([request responseStatusCode] == 429) {
|
|
|
|
return [self informError:@"Slow down. You're rate-limited."];
|
|
|
|
}
|
2011-11-30 09:38:31 -08:00
|
|
|
return [self informError:@"The server barfed!"];
|
2011-09-05 22:06:31 -07:00
|
|
|
}
|
|
|
|
|
2012-10-02 15:39:18 -07:00
|
|
|
appDelegate.hasNoSites = NO;
|
2012-07-27 16:10:13 -07:00
|
|
|
NSString *responseString = [request responseString];
|
|
|
|
NSData *responseData=[responseString dataUsingEncoding:NSUTF8StringEncoding];
|
|
|
|
NSError *error;
|
|
|
|
NSDictionary *results = [NSJSONSerialization
|
|
|
|
JSONObjectWithData:responseData
|
|
|
|
options:kNilOptions
|
|
|
|
error:&error];
|
2012-10-17 15:07:53 -07:00
|
|
|
appDelegate.savedStoriesCount = [[results objectForKey:@"starred_count"] intValue];
|
|
|
|
|
2012-08-11 18:03:28 -07:00
|
|
|
// NSLog(@"results are %@", results);
|
2011-08-24 21:44:16 -07:00
|
|
|
[MBProgressHUD hideHUDForView:self.view animated:YES];
|
|
|
|
self.stillVisibleFeeds = [NSMutableDictionary dictionary];
|
|
|
|
[pull finishedLoading];
|
|
|
|
[self loadFavicons];
|
2012-06-26 11:45:42 -07:00
|
|
|
|
2011-09-05 22:06:31 -07:00
|
|
|
appDelegate.activeUsername = [results objectForKey:@"user"];
|
2012-07-15 17:18:23 -07:00
|
|
|
|
2013-02-15 16:41:20 -08:00
|
|
|
// // set title only if on currestont controller
|
|
|
|
// if (appDelegate.feedsViewController.view.window && [results objectForKey:@"user"]) {
|
|
|
|
// [appDelegate setTitle:[results objectForKey:@"user"]];
|
|
|
|
// }
|
2012-07-11 10:33:39 -07:00
|
|
|
|
2012-07-11 18:08:07 -07:00
|
|
|
// adding user avatar to left
|
2012-07-11 10:33:39 -07:00
|
|
|
NSString *url = [NSString stringWithFormat:@"%@", [[results objectForKey:@"social_profile"] objectForKey:@"photo_url"]];
|
|
|
|
NSURL * imageURL = [NSURL URLWithString:url];
|
|
|
|
NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
|
|
|
|
UIImage * userAvatarImage = [UIImage imageWithData:imageData];
|
2012-07-11 18:08:07 -07:00
|
|
|
userAvatarImage = [Utilities roundCorneredImage:userAvatarImage radius:6];
|
2012-07-11 10:33:39 -07:00
|
|
|
UIButton *userAvatarButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
2012-08-02 18:00:48 -07:00
|
|
|
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
|
2012-07-11 10:33:39 -07:00
|
|
|
userAvatarButton.bounds = CGRectMake(0, 0, 32, 32);
|
2013-02-15 16:41:20 -08:00
|
|
|
userAvatarButton.frame = CGRectMake(0, 0, 32, 32);
|
2012-07-25 17:29:29 -07:00
|
|
|
[userAvatarButton addTarget:self action:@selector(showUserProfile) forControlEvents:UIControlEventTouchUpInside];
|
2012-07-11 10:33:39 -07:00
|
|
|
[userAvatarButton setImage:userAvatarImage forState:UIControlStateNormal];
|
2013-02-15 16:41:20 -08:00
|
|
|
UIBarButtonItem *userInfoBarButton = [[UIBarButtonItem alloc]
|
|
|
|
initWithCustomView:userAvatarButton];
|
2012-07-11 10:33:39 -07:00
|
|
|
|
2013-02-15 16:41:20 -08:00
|
|
|
self.navigationItem.leftBarButtonItem = userInfoBarButton;
|
2012-08-02 18:00:48 -07:00
|
|
|
[self setUserAvatarLayout:orientation];
|
2012-08-11 18:03:28 -07:00
|
|
|
|
2013-02-20 17:00:01 -08:00
|
|
|
UIImage *addImage = [UIImage imageNamed:@"nav_icn_add.png"];
|
|
|
|
UIButton *addButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
2013-02-28 17:07:51 -08:00
|
|
|
addButton.bounds = CGRectMake(0, 0, 34, 44);
|
2013-02-20 17:00:01 -08:00
|
|
|
[addButton setImage:addImage forState:UIControlStateNormal];
|
|
|
|
[addButton addTarget:self action:@selector(tapAddSite:) forControlEvents:UIControlEventTouchUpInside];
|
|
|
|
[addBarButton setCustomView:addButton];
|
2013-03-03 15:06:43 -08:00
|
|
|
|
2013-02-20 17:00:01 -08:00
|
|
|
UIImage *settingsImage = [UIImage imageNamed:@"nav_icn_settings.png"];
|
|
|
|
UIButton *settingsButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
2013-02-28 17:07:51 -08:00
|
|
|
settingsButton.bounds = CGRectMake(0, 0, 34, 44);
|
2013-02-20 17:00:01 -08:00
|
|
|
[settingsButton setImage:settingsImage forState:UIControlStateNormal];
|
|
|
|
[settingsButton addTarget:self action:@selector(showSettingsPopover:) forControlEvents:UIControlEventTouchUpInside];
|
2013-02-28 17:07:51 -08:00
|
|
|
[settingsBarButton setCustomView:settingsButton];
|
2013-02-22 12:13:01 -08:00
|
|
|
|
2013-03-01 15:48:18 -08:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
|
|
|
|
UIBarButtonItem *spacer = [[UIBarButtonItem alloc]
|
|
|
|
initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
|
|
|
|
target:nil action:nil];
|
|
|
|
spacer.width = 12;
|
|
|
|
UIImage *activityImage = [UIImage imageNamed:@"nav_icn_activity_hover.png"];
|
|
|
|
UIButton *activityButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
|
|
|
[activityButton setImage:activityImage forState:UIControlStateNormal];
|
|
|
|
[activityButton sizeToFit];
|
|
|
|
[activityButton addTarget:self action:@selector(showInteractionsPopover:) forControlEvents:UIControlEventTouchUpInside];
|
|
|
|
activitiesButton = [[UIBarButtonItem alloc]
|
|
|
|
initWithCustomView:activityButton];
|
|
|
|
self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:spacer, activitiesButton, nil];
|
|
|
|
}
|
2012-07-12 11:35:32 -07:00
|
|
|
|
2011-09-05 22:06:31 -07:00
|
|
|
NSMutableDictionary *sortedFolders = [[NSMutableDictionary alloc] init];
|
2011-10-14 17:15:48 -07:00
|
|
|
NSArray *sortedArray;
|
2011-09-05 22:06:31 -07:00
|
|
|
|
2012-07-26 23:07:47 -07:00
|
|
|
// Set up dictUserProfile and userActivitiesArray
|
2012-07-01 18:26:39 -07:00
|
|
|
appDelegate.dictUserProfile = [results objectForKey:@"social_profile"];
|
2012-07-26 23:07:47 -07:00
|
|
|
appDelegate.userActivitiesArray = [results objectForKey:@"activities"];
|
2012-08-11 18:03:28 -07:00
|
|
|
|
2012-08-13 17:07:26 -07:00
|
|
|
// Only update the dashboard if there is a social profile
|
2012-08-11 18:03:28 -07:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
|
|
|
[appDelegate.dashboardViewController refreshInteractions];
|
|
|
|
[appDelegate.dashboardViewController refreshActivity];
|
|
|
|
}
|
|
|
|
|
2012-06-26 12:29:37 -07:00
|
|
|
// Set up dictSocialFeeds
|
2012-06-26 11:45:42 -07:00
|
|
|
NSArray *socialFeedsArray = [results objectForKey:@"social_feeds"];
|
2012-06-25 15:02:20 -07:00
|
|
|
NSMutableArray *socialFolder = [[NSMutableArray alloc] init];
|
|
|
|
NSMutableDictionary *socialDict = [[NSMutableDictionary alloc] init];
|
2012-07-15 15:06:06 -07:00
|
|
|
NSMutableDictionary *tempActiveFeeds = [[NSMutableDictionary alloc] init];
|
|
|
|
appDelegate.dictActiveFeeds = tempActiveFeeds;
|
2012-06-25 15:02:20 -07:00
|
|
|
|
2012-06-26 11:45:42 -07:00
|
|
|
for (int i = 0; i < socialFeedsArray.count; i++) {
|
2012-06-25 15:02:20 -07:00
|
|
|
NSString *userKey = [NSString stringWithFormat:@"%@",
|
2012-06-26 11:45:42 -07:00
|
|
|
[[socialFeedsArray objectAtIndex:i] objectForKey:@"id"]];
|
|
|
|
[socialFolder addObject: [[socialFeedsArray objectAtIndex:i] objectForKey:@"id"]];
|
|
|
|
[socialDict setObject:[socialFeedsArray objectAtIndex:i]
|
2012-06-25 15:02:20 -07:00
|
|
|
forKey:userKey];
|
|
|
|
}
|
2012-07-01 18:26:39 -07:00
|
|
|
|
2012-06-25 15:02:20 -07:00
|
|
|
appDelegate.dictSocialFeeds = socialDict;
|
2012-06-26 11:45:42 -07:00
|
|
|
[self loadAvatars];
|
2012-07-10 16:48:05 -07:00
|
|
|
|
2012-06-26 12:29:37 -07:00
|
|
|
// set up dictFolders
|
2012-08-02 19:43:55 -07:00
|
|
|
NSMutableDictionary * allFolders = [[NSMutableDictionary alloc] init];
|
|
|
|
|
|
|
|
if (![[results objectForKey:@"flat_folders"] isKindOfClass:[NSArray class]]) {
|
|
|
|
allFolders = [[results objectForKey:@"flat_folders"] mutableCopy];
|
|
|
|
}
|
|
|
|
|
2012-10-03 15:46:02 -07:00
|
|
|
[allFolders setValue:socialFolder forKey:@"river_blurblogs"];
|
2012-12-07 15:17:22 -08:00
|
|
|
[allFolders setValue:[[NSMutableArray alloc] init] forKey:@"river_global"];
|
|
|
|
|
2012-10-17 15:07:53 -07:00
|
|
|
if (appDelegate.savedStoriesCount) {
|
|
|
|
[allFolders setValue:[[NSArray alloc] init] forKey:@"saved_stories"];
|
|
|
|
}
|
|
|
|
|
2012-06-26 12:29:37 -07:00
|
|
|
appDelegate.dictFolders = allFolders;
|
|
|
|
|
|
|
|
// set up dictFeeds
|
2012-07-27 16:10:13 -07:00
|
|
|
appDelegate.dictFeeds = [[results objectForKey:@"feeds"] mutableCopy];
|
2012-06-26 12:29:37 -07:00
|
|
|
|
|
|
|
// sort all the folders
|
|
|
|
appDelegate.dictFoldersArray = [NSMutableArray array];
|
|
|
|
for (id f in appDelegate.dictFolders) {
|
|
|
|
NSArray *folder = [appDelegate.dictFolders objectForKey:f];
|
2012-10-14 17:33:07 -04:00
|
|
|
NSString *folderTitle;
|
|
|
|
if ([f isEqualToString:@" "]) {
|
|
|
|
folderTitle = @"everything";
|
|
|
|
} else {
|
|
|
|
folderTitle = f;
|
|
|
|
}
|
|
|
|
[appDelegate.dictFoldersArray addObject:folderTitle];
|
2012-06-26 12:29:37 -07:00
|
|
|
sortedArray = [folder sortedArrayUsingComparator:^NSComparisonResult(id id1, id id2) {
|
|
|
|
NSString *feedTitleA;
|
|
|
|
NSString *feedTitleB;
|
|
|
|
|
|
|
|
if ([appDelegate isSocialFeed:[NSString stringWithFormat:@"%@", id1]]) {
|
|
|
|
feedTitleA = [[appDelegate.dictSocialFeeds
|
|
|
|
objectForKey:[NSString stringWithFormat:@"%@", id1]]
|
|
|
|
objectForKey:@"feed_title"];
|
|
|
|
feedTitleB = [[appDelegate.dictSocialFeeds
|
|
|
|
objectForKey:[NSString stringWithFormat:@"%@", id2]]
|
|
|
|
objectForKey:@"feed_title"];
|
|
|
|
} else {
|
|
|
|
feedTitleA = [[appDelegate.dictFeeds
|
|
|
|
objectForKey:[NSString stringWithFormat:@"%@", id1]]
|
|
|
|
objectForKey:@"feed_title"];
|
|
|
|
feedTitleB = [[appDelegate.dictFeeds
|
|
|
|
objectForKey:[NSString stringWithFormat:@"%@", id2]]
|
|
|
|
objectForKey:@"feed_title"];
|
|
|
|
}
|
|
|
|
return [feedTitleA caseInsensitiveCompare:feedTitleB];
|
|
|
|
}];
|
2012-10-14 17:33:07 -04:00
|
|
|
[sortedFolders setValue:sortedArray forKey:folderTitle];
|
2012-06-26 12:29:37 -07:00
|
|
|
}
|
2011-10-14 17:15:48 -07:00
|
|
|
appDelegate.dictFolders = sortedFolders;
|
2011-10-04 18:01:35 -07:00
|
|
|
[appDelegate.dictFoldersArray sortUsingSelector:@selector(caseInsensitiveCompare:)];
|
2012-10-03 15:46:02 -07:00
|
|
|
|
2012-12-07 15:17:22 -08:00
|
|
|
|
2012-10-03 15:46:02 -07:00
|
|
|
// Move River Blurblog and Everything to the top
|
2012-12-07 15:17:22 -08:00
|
|
|
if ([appDelegate.dictFoldersArray containsObject:@"river_global"]) {
|
|
|
|
[appDelegate.dictFoldersArray removeObject:@"river_global"];
|
|
|
|
[appDelegate.dictFoldersArray insertObject:@"river_global" atIndex:0];
|
|
|
|
}
|
2012-10-03 15:46:02 -07:00
|
|
|
if ([appDelegate.dictFoldersArray containsObject:@"river_blurblogs"]) {
|
|
|
|
[appDelegate.dictFoldersArray removeObject:@"river_blurblogs"];
|
2012-12-07 15:17:22 -08:00
|
|
|
[appDelegate.dictFoldersArray insertObject:@"river_blurblogs" atIndex:1];
|
2012-10-03 15:46:02 -07:00
|
|
|
}
|
|
|
|
if ([appDelegate.dictFoldersArray containsObject:@"everything"]) {
|
|
|
|
[appDelegate.dictFoldersArray removeObject:@"everything"];
|
2012-12-07 15:17:22 -08:00
|
|
|
[appDelegate.dictFoldersArray insertObject:@"everything" atIndex:2];
|
2012-10-03 15:46:02 -07:00
|
|
|
}
|
2012-10-17 15:07:53 -07:00
|
|
|
|
|
|
|
// Add Saved Stories folder
|
|
|
|
if (appDelegate.savedStoriesCount) {
|
|
|
|
[appDelegate.dictFoldersArray removeObject:@"saved_stories"];
|
|
|
|
[appDelegate.dictFoldersArray insertObject:@"saved_stories" atIndex:appDelegate.dictFoldersArray.count];
|
|
|
|
}
|
2012-06-25 15:02:20 -07:00
|
|
|
|
2012-08-02 19:43:55 -07:00
|
|
|
|
2012-12-20 12:08:35 -08:00
|
|
|
// test for empty
|
2012-08-02 19:43:55 -07:00
|
|
|
if ([[appDelegate.dictFeeds allKeys] count] == 0 &&
|
|
|
|
[[appDelegate.dictSocialFeeds allKeys] count] == 0) {
|
2012-10-02 15:39:18 -07:00
|
|
|
appDelegate.hasNoSites = YES;
|
2012-08-02 19:43:55 -07:00
|
|
|
}
|
|
|
|
|
2012-12-20 12:08:35 -08:00
|
|
|
[self calculateFeedLocations];
|
2011-09-05 22:06:31 -07:00
|
|
|
[self.feedTitlesTable reloadData];
|
2013-02-15 16:41:20 -08:00
|
|
|
[self refreshHeaderCounts];
|
2012-06-27 10:04:44 -07:00
|
|
|
|
2012-08-14 17:20:45 -07:00
|
|
|
// assign categories for FTUX
|
|
|
|
|
|
|
|
if (![[results objectForKey:@"categories"] isKindOfClass:[NSNull class]]){
|
|
|
|
appDelegate.categories = [[results objectForKey:@"categories"] objectForKey:@"categories"];
|
|
|
|
appDelegate.categoryFeeds = [[results objectForKey:@"categories"] objectForKey:@"feeds"];
|
|
|
|
}
|
2011-09-05 22:06:31 -07:00
|
|
|
|
2012-06-27 10:04:44 -07:00
|
|
|
// test for latest version of app
|
2012-06-09 09:38:32 -07:00
|
|
|
NSString *serveriPhoneVersion = [results objectForKey:@"iphone_version"];
|
2011-12-07 09:57:33 -08:00
|
|
|
NSString *currentiPhoneVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
|
2012-06-07 12:45:11 -07:00
|
|
|
|
|
|
|
float serveriPhoneVersionFloat = [serveriPhoneVersion floatValue];
|
|
|
|
float currentiPhoneVersionFloat = [currentiPhoneVersion floatValue];
|
|
|
|
|
|
|
|
if (currentiPhoneVersionFloat < serveriPhoneVersionFloat) {
|
|
|
|
NSLog(@"Version: %f - %f", serveriPhoneVersionFloat, currentiPhoneVersionFloat);
|
2012-06-26 11:45:42 -07:00
|
|
|
NSString *title = [NSString stringWithFormat:@
|
|
|
|
"You should download the new version of NewsBlur.\n\nNew version: v%@\nYou have: v%@",
|
|
|
|
serveriPhoneVersion,
|
|
|
|
currentiPhoneVersion];
|
|
|
|
UIAlertView *upgradeConfirm = [[UIAlertView alloc] initWithTitle:title
|
|
|
|
message:nil
|
|
|
|
delegate:self
|
|
|
|
cancelButtonTitle:@"Cancel"
|
|
|
|
otherButtonTitles:@"Upgrade!", nil];
|
2011-12-07 09:57:33 -08:00
|
|
|
[upgradeConfirm show];
|
|
|
|
[upgradeConfirm setTag:2];
|
|
|
|
}
|
2012-08-09 10:18:15 -07:00
|
|
|
|
2012-08-16 20:10:50 -07:00
|
|
|
if (!self.inPullToRefresh_) {
|
|
|
|
[self refreshFeedList];
|
|
|
|
} else {
|
|
|
|
self.inPullToRefresh_ = NO;
|
|
|
|
}
|
2012-08-12 16:50:34 -07:00
|
|
|
|
|
|
|
// start up the first time user experience
|
|
|
|
if ([[results objectForKey:@"social_feeds"] count] == 0 &&
|
|
|
|
[[[results objectForKey:@"feeds"] allKeys] count] == 0) {
|
|
|
|
[appDelegate showFirstTimeUser];
|
|
|
|
return;
|
|
|
|
}
|
2012-08-15 19:31:34 -07:00
|
|
|
|
|
|
|
BOOL hasFocusStory = NO;
|
|
|
|
for (id feedId in appDelegate.dictFeeds) {
|
|
|
|
NSDictionary *feed = [appDelegate.dictFeeds objectForKey:feedId];
|
|
|
|
if ([[feed objectForKey:@"ps"] intValue] > 0) {
|
|
|
|
hasFocusStory = YES;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hasFocusStory) {
|
|
|
|
[self.intelligenceControl removeSegmentAtIndex:2 animated:NO];
|
|
|
|
[self.intelligenceControl setWidth:90 forSegmentAtIndex:0];
|
|
|
|
[self.intelligenceControl setWidth:90 forSegmentAtIndex:1];
|
|
|
|
} else {
|
|
|
|
UIImage *green = [UIImage imageNamed:@"green_focus.png"];
|
|
|
|
if (self.intelligenceControl.numberOfSegments == 2) {
|
|
|
|
[self.intelligenceControl insertSegmentWithImage:green atIndex:2 animated:NO];
|
|
|
|
[self.intelligenceControl setWidth:50 forSegmentAtIndex:0];
|
|
|
|
[self.intelligenceControl setWidth:68 forSegmentAtIndex:1];
|
|
|
|
[self.intelligenceControl setWidth:62 forSegmentAtIndex:2];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
self.intelligenceControl.hidden = NO;
|
2010-11-11 23:48:27 -05:00
|
|
|
}
|
|
|
|
|
2012-07-25 17:29:29 -07:00
|
|
|
- (void)showUserProfile {
|
2012-07-12 00:10:42 -07:00
|
|
|
appDelegate.activeUserProfileId = [NSString stringWithFormat:@"%@", [appDelegate.dictUserProfile objectForKey:@"user_id"]];
|
2012-08-09 10:18:15 -07:00
|
|
|
appDelegate.activeUserProfileName = [NSString stringWithFormat:@"%@", [appDelegate.dictUserProfile objectForKey:@"username"]];
|
|
|
|
// appDelegate.activeUserProfileName = @"You";
|
2012-07-28 12:56:51 -07:00
|
|
|
[appDelegate showUserProfileModal:self.navigationItem.leftBarButtonItem];
|
2012-07-12 00:10:42 -07:00
|
|
|
}
|
|
|
|
|
2012-07-31 15:57:56 -07:00
|
|
|
- (IBAction)tapAddSite:(id)sender {
|
2013-03-03 17:37:54 -08:00
|
|
|
[appDelegate.addSiteViewController reload];
|
|
|
|
|
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
|
|
|
[appDelegate.masterContainerViewController showSitePopover:self.addBarButton];
|
|
|
|
} else {
|
|
|
|
if (self.popoverController == nil) {
|
|
|
|
self.popoverController = [[WEPopoverController alloc]
|
|
|
|
initWithContentViewController:appDelegate.addSiteViewController];
|
|
|
|
|
|
|
|
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(self.view.frame.size.width - 36,
|
|
|
|
self.view.frame.size.height - 28)];
|
|
|
|
[self.popoverController presentPopoverFromBarButtonItem:self.addBarButton
|
|
|
|
permittedArrowDirections:UIPopoverArrowDirectionDown
|
|
|
|
animated:YES];
|
|
|
|
}
|
2012-07-31 15:57:56 -07:00
|
|
|
}
|
|
|
|
|
2013-02-20 17:00:01 -08:00
|
|
|
- (IBAction)showSettingsPopover:(id)sender {
|
2012-06-19 13:51:48 -07:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
2013-03-01 15:48:18 -08:00
|
|
|
[appDelegate.masterContainerViewController showFeedMenuPopover:self.settingsBarButton];
|
2012-07-31 13:10:26 -07:00
|
|
|
} else {
|
|
|
|
if (self.popoverController == nil) {
|
|
|
|
self.popoverController = [[WEPopoverController alloc]
|
|
|
|
initWithContentViewController:appDelegate.feedsMenuViewController];
|
2012-06-19 13:51:48 -07:00
|
|
|
|
2012-07-31 13:10:26 -07:00
|
|
|
self.popoverController.delegate = self;
|
2012-07-12 00:10:42 -07:00
|
|
|
} else {
|
2012-07-31 13:10:26 -07:00
|
|
|
[self.popoverController dismissPopoverAnimated:YES];
|
|
|
|
self.popoverController = nil;
|
2012-06-19 13:51:48 -07:00
|
|
|
}
|
|
|
|
|
2012-07-31 13:10:26 -07:00
|
|
|
if ([self.popoverController respondsToSelector:@selector(setContainerViewProperties:)]) {
|
|
|
|
[self.popoverController setContainerViewProperties:[self improvedContainerViewProperties]];
|
|
|
|
}
|
2012-10-14 19:39:24 -04:00
|
|
|
[self.popoverController setPopoverContentSize:CGSizeMake(200, 76)];
|
2013-02-20 17:00:01 -08:00
|
|
|
[self.popoverController presentPopoverFromBarButtonItem:self.settingsBarButton
|
|
|
|
permittedArrowDirections:UIPopoverArrowDirectionDown
|
2012-08-01 23:16:04 -07:00
|
|
|
animated:YES];
|
2012-06-19 13:51:48 -07:00
|
|
|
}
|
2011-08-21 21:39:29 -07:00
|
|
|
}
|
|
|
|
|
2013-02-21 16:53:37 -08:00
|
|
|
- (IBAction)showInteractionsPopover:(id)sender {
|
|
|
|
if (self.popoverController == nil) {
|
|
|
|
self.popoverController = [[WEPopoverController alloc]
|
|
|
|
initWithContentViewController:appDelegate.dashboardViewController];
|
|
|
|
|
|
|
|
self.popoverController.delegate = self;
|
|
|
|
} else {
|
|
|
|
[self.popoverController dismissPopoverAnimated:YES];
|
|
|
|
self.popoverController = nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ([self.popoverController respondsToSelector:@selector(setContainerViewProperties:)]) {
|
|
|
|
[self.popoverController setContainerViewProperties:[self improvedContainerViewProperties]];
|
|
|
|
}
|
2013-03-03 17:37:54 -08:00
|
|
|
[self.popoverController setPopoverContentSize:CGSizeMake(self.view.frame.size.width - 36,
|
|
|
|
self.view.frame.size.height - 60)];
|
2013-02-26 19:39:13 -08:00
|
|
|
[self.popoverController presentPopoverFromBarButtonItem:self.activitiesButton
|
2013-02-21 16:53:37 -08:00
|
|
|
permittedArrowDirections:UIPopoverArrowDirectionUp
|
|
|
|
animated:YES];
|
|
|
|
|
|
|
|
[appDelegate.dashboardViewController refreshInteractions];
|
|
|
|
[appDelegate.dashboardViewController refreshActivity];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-08-21 21:39:29 -07:00
|
|
|
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
|
2012-06-19 10:55:46 -07:00
|
|
|
if (alertView.tag == 2) {
|
2011-12-07 09:57:33 -08:00
|
|
|
if (buttonIndex == 0) {
|
|
|
|
return;
|
|
|
|
} else {
|
2012-06-07 12:45:11 -07:00
|
|
|
// this doesn't work in simulator!!! because simulator has no app store
|
2011-12-07 09:57:33 -08:00
|
|
|
NSURL *url = [NSURL URLWithString:@"http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=463981119&mt=8"];
|
|
|
|
[[UIApplication sharedApplication] openURL:url];
|
|
|
|
}
|
2011-08-24 21:44:16 -07:00
|
|
|
}
|
2010-11-13 13:42:20 -05:00
|
|
|
}
|
2010-11-11 23:48:27 -05:00
|
|
|
|
2010-06-20 11:04:23 -04:00
|
|
|
#pragma mark -
|
|
|
|
#pragma mark Table View - Feed List
|
|
|
|
|
|
|
|
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
2012-10-02 15:39:18 -07:00
|
|
|
if (appDelegate.hasNoSites) {
|
2012-12-07 15:17:22 -08:00
|
|
|
return 3;
|
2012-08-02 19:43:55 -07:00
|
|
|
}
|
2011-10-04 18:01:35 -07:00
|
|
|
return [appDelegate.dictFoldersArray count];
|
2010-06-20 11:04:23 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
|
2011-10-04 18:01:35 -07:00
|
|
|
return [appDelegate.dictFoldersArray objectAtIndex:section];
|
2010-06-20 11:04:23 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
2012-10-02 15:39:18 -07:00
|
|
|
if (appDelegate.hasNoSites) {
|
2012-08-02 19:43:55 -07:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2011-10-04 18:01:35 -07:00
|
|
|
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:section];
|
2012-10-17 15:07:53 -07:00
|
|
|
|
2012-12-20 12:08:35 -08:00
|
|
|
return [[appDelegate.dictFolders objectForKey:folderName] count];
|
2010-06-20 11:04:23 -04:00
|
|
|
}
|
|
|
|
|
2011-08-02 18:03:11 -07:00
|
|
|
- (UITableViewCell *)tableView:(UITableView *)tableView
|
2011-11-29 18:39:52 -08:00
|
|
|
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
2012-08-02 19:43:55 -07:00
|
|
|
|
|
|
|
// messaging when there are no sites
|
2012-10-02 15:39:18 -07:00
|
|
|
if (appDelegate.hasNoSites) {
|
2012-08-02 19:43:55 -07:00
|
|
|
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"EmptyCell"];
|
|
|
|
if (cell == nil) {
|
|
|
|
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
|
|
|
|
}
|
|
|
|
cell.textLabel.font=[UIFont systemFontOfSize:14.0];
|
|
|
|
cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
|
|
|
if (indexPath.section == 0) {
|
|
|
|
cell.textLabel.text = @"Tap the settings to find friends.";
|
|
|
|
} else {
|
|
|
|
cell.textLabel.text = @"Tap + to add sites.";
|
|
|
|
}
|
|
|
|
|
|
|
|
return cell;
|
|
|
|
}
|
|
|
|
|
2012-12-20 12:08:35 -08:00
|
|
|
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:indexPath.section];
|
|
|
|
id feedId = [[appDelegate.dictFolders objectForKey:folderName] objectAtIndex:indexPath.row];
|
|
|
|
NSString *feedIdStr = [NSString stringWithFormat:@"%@",feedId];
|
|
|
|
BOOL isSocial = [appDelegate isSocialFeed:feedIdStr];
|
2012-07-18 21:41:38 -07:00
|
|
|
|
2012-12-20 12:08:35 -08:00
|
|
|
NSString *CellIdentifier;
|
|
|
|
if (indexPath.section == 0 || indexPath.section == 1) {
|
2012-07-18 21:41:38 -07:00
|
|
|
CellIdentifier = @"BlurblogCellIdentifier";
|
|
|
|
} else {
|
|
|
|
CellIdentifier = @"FeedCellIdentifier";
|
|
|
|
}
|
2012-12-20 12:08:35 -08:00
|
|
|
|
2012-07-18 21:41:38 -07:00
|
|
|
FeedTableCell *cell = (FeedTableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
|
2011-08-24 21:44:16 -07:00
|
|
|
if (cell == nil) {
|
2012-11-19 19:15:05 -08:00
|
|
|
cell = [[FeedTableCell alloc]
|
|
|
|
initWithStyle:UITableViewCellStyleDefault
|
|
|
|
reuseIdentifier:CellIdentifier];
|
|
|
|
cell.appDelegate = appDelegate;
|
2011-08-24 21:44:16 -07:00
|
|
|
}
|
|
|
|
|
2012-12-20 12:08:35 -08:00
|
|
|
if (![self isFeedVisible:feedId]) {
|
|
|
|
return cell;
|
2012-06-25 15:02:20 -07:00
|
|
|
}
|
2012-12-20 12:08:35 -08:00
|
|
|
|
|
|
|
NSDictionary *feed = isSocial ?
|
|
|
|
[appDelegate.dictSocialFeeds objectForKey:feedIdStr] :
|
|
|
|
[appDelegate.dictFeeds objectForKey:feedIdStr];
|
|
|
|
cell.feedFavicon = [Utilities getImage:feedIdStr isSocial:isSocial];
|
2011-10-17 09:37:16 -07:00
|
|
|
cell.feedTitle = [feed objectForKey:@"feed_title"];
|
2011-08-24 21:44:16 -07:00
|
|
|
cell.positiveCount = [[feed objectForKey:@"ps"] intValue];
|
|
|
|
cell.neutralCount = [[feed objectForKey:@"nt"] intValue];
|
|
|
|
cell.negativeCount = [[feed objectForKey:@"ng"] intValue];
|
2012-06-27 10:18:29 -07:00
|
|
|
cell.isSocial = isSocial;
|
2011-08-24 21:44:16 -07:00
|
|
|
|
2012-11-19 19:15:05 -08:00
|
|
|
[cell setNeedsDisplay];
|
|
|
|
|
2011-08-24 21:44:16 -07:00
|
|
|
return cell;
|
2010-06-20 11:04:23 -04:00
|
|
|
}
|
|
|
|
|
2011-08-12 10:12:30 -07:00
|
|
|
- (void)tableView:(UITableView *)tableView
|
2011-11-29 18:39:52 -08:00
|
|
|
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
2012-07-27 19:42:19 -07:00
|
|
|
|
2012-10-02 15:39:18 -07:00
|
|
|
if (appDelegate.hasNoSites) {
|
2012-08-02 19:43:55 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-27 19:42:19 -07:00
|
|
|
// set the current row pointer
|
|
|
|
self.currentRowAtIndexPath = indexPath;
|
|
|
|
|
2012-10-03 15:46:02 -07:00
|
|
|
NSString *folderName;
|
|
|
|
if (indexPath.section == 0) {
|
2012-12-07 15:17:22 -08:00
|
|
|
folderName = @"river_global";
|
2012-10-03 15:46:02 -07:00
|
|
|
} else if (indexPath.section == 1) {
|
2012-12-07 15:17:22 -08:00
|
|
|
folderName = @"river_blurblogs";
|
|
|
|
} else if (indexPath.section == 2) {
|
2012-10-03 15:46:02 -07:00
|
|
|
folderName = @"everything";
|
|
|
|
} else {
|
|
|
|
folderName = [appDelegate.dictFoldersArray objectAtIndex:indexPath.section];
|
|
|
|
}
|
2012-12-20 12:08:35 -08:00
|
|
|
id feedId = [[appDelegate.dictFolders objectForKey:folderName] objectAtIndex:indexPath.row];
|
2011-08-24 21:44:16 -07:00
|
|
|
NSString *feedIdStr = [NSString stringWithFormat:@"%@",feedId];
|
2012-12-20 12:08:35 -08:00
|
|
|
NSDictionary *feed;
|
2012-06-26 16:24:19 -07:00
|
|
|
if ([appDelegate isSocialFeed:feedIdStr]) {
|
2012-06-25 15:02:20 -07:00
|
|
|
feed = [appDelegate.dictSocialFeeds objectForKey:feedIdStr];
|
2012-06-26 16:24:19 -07:00
|
|
|
appDelegate.isSocialView = YES;
|
2012-06-25 15:02:20 -07:00
|
|
|
} else {
|
|
|
|
feed = [appDelegate.dictFeeds objectForKey:feedIdStr];
|
2012-06-26 16:24:19 -07:00
|
|
|
appDelegate.isSocialView = NO;
|
2012-06-25 15:02:20 -07:00
|
|
|
}
|
2012-12-20 12:08:35 -08:00
|
|
|
|
2011-08-24 21:44:16 -07:00
|
|
|
// If all feeds are already showing, no need to remember this one.
|
|
|
|
if (!self.viewShowingAllFeeds) {
|
|
|
|
[self.stillVisibleFeeds setObject:indexPath forKey:feedIdStr];
|
|
|
|
}
|
|
|
|
|
|
|
|
[appDelegate setActiveFeed:feed];
|
2011-10-20 09:32:39 -07:00
|
|
|
[appDelegate setActiveFolder:folderName];
|
2011-08-24 21:44:16 -07:00
|
|
|
appDelegate.readStories = [NSMutableArray array];
|
2011-10-25 09:28:05 -07:00
|
|
|
appDelegate.isRiverView = NO;
|
2012-08-08 10:57:38 -07:00
|
|
|
appDelegate.isSocialRiverView = NO;
|
2012-10-14 17:30:03 -07:00
|
|
|
[appDelegate.folderCountCache removeObjectForKey:folderName];
|
2012-12-11 11:50:06 -08:00
|
|
|
appDelegate.activeClassifiers = [NSMutableDictionary dictionary];
|
2012-10-14 17:30:03 -07:00
|
|
|
|
2011-08-24 21:44:16 -07:00
|
|
|
[appDelegate loadFeedDetailView];
|
2010-06-20 11:04:23 -04:00
|
|
|
}
|
|
|
|
|
2012-12-10 18:34:13 -08:00
|
|
|
- (CGFloat)tableView:(UITableView *)tableView
|
2011-11-29 18:39:52 -08:00
|
|
|
heightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
2012-07-11 11:03:34 -07:00
|
|
|
|
2012-10-02 15:39:18 -07:00
|
|
|
if (appDelegate.hasNoSites) {
|
2012-08-02 19:43:55 -07:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
|
|
|
return kBlurblogTableViewRowHeight;
|
|
|
|
} else {
|
|
|
|
return kPhoneBlurblogTableViewRowHeight;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-03 15:46:02 -07:00
|
|
|
NSString *folderName;
|
|
|
|
if (indexPath.section == 0) {
|
2012-12-07 15:17:22 -08:00
|
|
|
folderName = @"river_global";
|
|
|
|
} else if (indexPath.section == 1) {
|
|
|
|
folderName = @"river_blurblogs";
|
2012-10-03 15:46:02 -07:00
|
|
|
} else {
|
|
|
|
folderName = [appDelegate.dictFoldersArray objectAtIndex:indexPath.section];
|
|
|
|
}
|
|
|
|
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
|
|
|
|
NSString *collapseKey = [NSString stringWithFormat:@"folderCollapsed:%@", folderName];
|
|
|
|
bool isFolderCollapsed = [userPreferences boolForKey:collapseKey];
|
|
|
|
|
|
|
|
if (isFolderCollapsed) {
|
|
|
|
return 0;
|
|
|
|
}
|
2012-07-11 11:03:34 -07:00
|
|
|
|
2012-12-20 12:08:35 -08:00
|
|
|
id feedId = [[appDelegate.dictFolders objectForKey:folderName] objectAtIndex:indexPath.row];
|
|
|
|
if (![self isFeedVisible:feedId]) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-12-07 15:17:22 -08:00
|
|
|
if ([folderName isEqualToString:@"river_blurblogs"] ||
|
|
|
|
[folderName isEqualToString:@"river_global"]) { // blurblogs
|
2012-08-02 12:01:42 -07:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
2012-12-20 12:08:35 -08:00
|
|
|
return kBlurblogTableViewRowHeight;
|
2012-08-02 12:01:42 -07:00
|
|
|
} else {
|
|
|
|
return kPhoneBlurblogTableViewRowHeight;
|
|
|
|
}
|
2012-07-11 11:03:34 -07:00
|
|
|
} else {
|
2012-08-02 12:01:42 -07:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
|
|
|
return kTableViewRowHeight;
|
|
|
|
} else {
|
|
|
|
return kPhoneTableViewRowHeight;
|
|
|
|
}
|
2012-07-11 11:03:34 -07:00
|
|
|
}
|
2011-07-19 09:38:49 -07:00
|
|
|
}
|
|
|
|
|
2011-08-12 10:12:30 -07:00
|
|
|
- (UIView *)tableView:(UITableView *)tableView
|
2011-11-29 18:39:52 -08:00
|
|
|
viewForHeaderInSection:(NSInteger)section {
|
2012-06-07 13:37:23 -07:00
|
|
|
|
2011-10-25 09:28:05 -07:00
|
|
|
|
2012-10-02 15:39:18 -07:00
|
|
|
CGRect rect = CGRectMake(0.0, 0.0, tableView.bounds.size.width, kFolderTitleHeight);
|
2012-10-04 15:44:25 -07:00
|
|
|
FolderTitleView *folderTitle = [[FolderTitleView alloc] initWithFrame:rect];
|
|
|
|
folderTitle.section = section;
|
2011-10-26 23:12:21 -07:00
|
|
|
|
2012-10-02 15:39:18 -07:00
|
|
|
return folderTitle;
|
2011-08-12 10:12:30 -07:00
|
|
|
}
|
|
|
|
|
2011-10-26 23:12:21 -07:00
|
|
|
- (IBAction)sectionTapped:(UIButton *)button {
|
2013-02-22 12:13:01 -08:00
|
|
|
button.backgroundColor = UIColorFromRGB(0x214607);
|
2011-11-30 18:46:11 -08:00
|
|
|
}
|
2012-08-08 10:57:38 -07:00
|
|
|
|
2011-11-30 18:46:11 -08:00
|
|
|
- (IBAction)sectionUntapped:(UIButton *)button {
|
|
|
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.15 * NSEC_PER_SEC),
|
|
|
|
dispatch_get_current_queue(), ^{
|
|
|
|
button.backgroundColor = [UIColor clearColor];
|
|
|
|
});
|
2011-10-26 23:12:21 -07:00
|
|
|
}
|
|
|
|
|
2012-06-26 12:12:31 -07:00
|
|
|
- (IBAction)sectionUntappedOutside:(UIButton *)button {
|
|
|
|
button.backgroundColor = [UIColor clearColor];
|
|
|
|
}
|
|
|
|
|
2012-12-20 12:21:44 -08:00
|
|
|
- (CGFloat)tableView:(UITableView *)tableView
|
|
|
|
heightForHeaderInSection:(NSInteger)section {
|
2012-10-17 15:07:53 -07:00
|
|
|
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:section];
|
2012-07-20 22:00:30 -07:00
|
|
|
|
2012-12-20 12:08:35 -08:00
|
|
|
BOOL visibleFeeds = [[self.visibleFolders objectForKey:folderName] boolValue];
|
2013-02-06 15:15:43 -08:00
|
|
|
if (!visibleFeeds && section != 2 && section != 0 && ![folderName isEqual:@"saved_stories"]) {
|
2012-07-20 22:00:30 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-10-30 17:05:39 -07:00
|
|
|
return 32;
|
2011-08-12 10:12:30 -07:00
|
|
|
}
|
|
|
|
|
2011-10-25 09:47:55 -07:00
|
|
|
- (void)didSelectSectionHeader:(UIButton *)button {
|
2012-07-27 19:42:19 -07:00
|
|
|
// reset pointer to the cells
|
|
|
|
self.currentRowAtIndexPath = nil;
|
|
|
|
|
2011-10-25 09:47:55 -07:00
|
|
|
appDelegate.readStories = [NSMutableArray array];
|
2012-08-08 10:57:38 -07:00
|
|
|
|
2011-10-26 08:40:31 -07:00
|
|
|
NSMutableArray *feeds = [NSMutableArray array];
|
2011-11-29 18:39:52 -08:00
|
|
|
|
2012-08-13 17:07:26 -07:00
|
|
|
if (button.tag == 0) {
|
2012-12-07 15:17:22 -08:00
|
|
|
appDelegate.isSocialRiverView = YES;
|
|
|
|
appDelegate.isRiverView = YES;
|
|
|
|
[appDelegate setActiveFolder:@"river_global"];
|
|
|
|
} else if (button.tag == 1) {
|
2012-08-13 17:07:26 -07:00
|
|
|
appDelegate.isSocialRiverView = YES;
|
|
|
|
appDelegate.isRiverView = YES;
|
|
|
|
// add all the feeds from every NON blurblog folder
|
2012-10-03 15:46:02 -07:00
|
|
|
[appDelegate setActiveFolder:@"river_blurblogs"];
|
2012-08-13 17:07:26 -07:00
|
|
|
for (NSString *folderName in self.activeFeedLocations) {
|
2012-10-03 15:46:02 -07:00
|
|
|
if ([folderName isEqualToString:@"river_blurblogs"]) { // remove all blurblugs which is a blank folder name
|
2012-08-13 17:07:26 -07:00
|
|
|
NSArray *originalFolder = [appDelegate.dictFolders objectForKey:folderName];
|
|
|
|
NSArray *folderFeeds = [self.activeFeedLocations objectForKey:folderName];
|
|
|
|
for (int l=0; l < [folderFeeds count]; l++) {
|
|
|
|
[feeds addObject:[originalFolder objectAtIndex:[[folderFeeds objectAtIndex:l] intValue]]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-12-10 18:34:13 -08:00
|
|
|
} else if (button.tag == 2) {
|
2012-08-13 17:07:26 -07:00
|
|
|
appDelegate.isSocialRiverView = NO;
|
|
|
|
appDelegate.isRiverView = YES;
|
2012-08-10 18:10:07 -07:00
|
|
|
// add all the feeds from every NON blurblog folder
|
2012-10-03 15:46:02 -07:00
|
|
|
[appDelegate setActiveFolder:@"everything"];
|
2011-11-29 18:39:52 -08:00
|
|
|
for (NSString *folderName in self.activeFeedLocations) {
|
2012-10-03 15:46:02 -07:00
|
|
|
if (![folderName isEqualToString:@"river_blurblogs"]) {
|
2012-07-16 22:35:28 -07:00
|
|
|
NSArray *originalFolder = [appDelegate.dictFolders objectForKey:folderName];
|
|
|
|
NSArray *folderFeeds = [self.activeFeedLocations objectForKey:folderName];
|
|
|
|
for (int l=0; l < [folderFeeds count]; l++) {
|
|
|
|
[feeds addObject:[originalFolder objectAtIndex:[[folderFeeds objectAtIndex:l] intValue]]];
|
|
|
|
}
|
2011-11-29 18:39:52 -08:00
|
|
|
}
|
|
|
|
}
|
2012-12-10 18:34:13 -08:00
|
|
|
[appDelegate.folderCountCache removeAllObjects];
|
2011-11-29 18:39:52 -08:00
|
|
|
} else {
|
2012-08-13 18:45:06 -07:00
|
|
|
appDelegate.isSocialRiverView = NO;
|
|
|
|
appDelegate.isRiverView = YES;
|
2011-11-29 18:39:52 -08:00
|
|
|
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:button.tag];
|
|
|
|
|
|
|
|
[appDelegate setActiveFolder:folderName];
|
|
|
|
NSArray *originalFolder = [appDelegate.dictFolders objectForKey:folderName];
|
|
|
|
NSArray *activeFolderFeeds = [self.activeFeedLocations objectForKey:folderName];
|
|
|
|
for (int l=0; l < [activeFolderFeeds count]; l++) {
|
|
|
|
[feeds addObject:[originalFolder objectAtIndex:[[activeFolderFeeds objectAtIndex:l] intValue]]];
|
|
|
|
}
|
|
|
|
|
2011-10-26 08:40:31 -07:00
|
|
|
}
|
|
|
|
appDelegate.activeFolderFeeds = feeds;
|
2012-12-20 12:21:44 -08:00
|
|
|
if (!self.viewShowingAllFeeds) {
|
|
|
|
for (id feedId in feeds) {
|
|
|
|
NSString *feedIdStr = [NSString stringWithFormat:@"%@", feedId];
|
|
|
|
[self.stillVisibleFeeds setObject:[NSNumber numberWithBool:YES] forKey:feedIdStr];
|
|
|
|
}
|
|
|
|
}
|
2012-10-14 17:30:03 -07:00
|
|
|
[appDelegate.folderCountCache removeObjectForKey:appDelegate.activeFolder];
|
|
|
|
|
2011-10-26 08:40:31 -07:00
|
|
|
[appDelegate loadRiverFeedDetailView];
|
2011-10-25 09:28:05 -07:00
|
|
|
}
|
|
|
|
|
2012-10-03 15:46:02 -07:00
|
|
|
- (void)didCollapseFolder:(UIButton *)button {
|
|
|
|
NSString *folderName;
|
|
|
|
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
|
|
|
|
|
|
|
|
if (button.tag == 0) {
|
2012-12-07 15:17:22 -08:00
|
|
|
folderName = @"river_global";
|
|
|
|
} else if (button.tag == 1) {
|
2012-10-03 15:46:02 -07:00
|
|
|
folderName = @"river_blurblogs";
|
|
|
|
} else {
|
|
|
|
folderName = [appDelegate.dictFoldersArray objectAtIndex:button.tag];
|
|
|
|
}
|
|
|
|
|
|
|
|
NSString *collapseKey = [NSString stringWithFormat:@"folderCollapsed:%@", folderName];
|
|
|
|
bool isFolderCollapsed = [userPreferences boolForKey:collapseKey];
|
|
|
|
|
|
|
|
if (isFolderCollapsed) {
|
|
|
|
// Expand folder
|
|
|
|
[userPreferences setBool:NO forKey:collapseKey];
|
|
|
|
} else {
|
|
|
|
// Collapse folder
|
|
|
|
[userPreferences setBool:YES forKey:collapseKey];
|
|
|
|
}
|
|
|
|
[userPreferences synchronize];
|
|
|
|
|
2012-12-20 12:08:35 -08:00
|
|
|
[self.feedTitlesTable beginUpdates];
|
2012-10-03 15:46:02 -07:00
|
|
|
[self.feedTitlesTable reloadSections:[NSIndexSet indexSetWithIndex:button.tag]
|
|
|
|
withRowAnimation:UITableViewRowAnimationFade];
|
|
|
|
[self.feedTitlesTable endUpdates];
|
|
|
|
|
2012-10-30 17:25:20 -07:00
|
|
|
// Scroll to section header if collapse causes it to scroll far off screen
|
|
|
|
NSArray *indexPathsVisibleCells = [self.feedTitlesTable indexPathsForVisibleRows];
|
|
|
|
BOOL firstFeedInFolderVisible = NO;
|
|
|
|
for (NSIndexPath *indexPath in indexPathsVisibleCells) {
|
|
|
|
if (indexPath.row == 0 && indexPath.section == button.tag) {
|
|
|
|
firstFeedInFolderVisible = YES;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!firstFeedInFolderVisible) {
|
|
|
|
CGRect headerRect = [self.feedTitlesTable rectForHeaderInSection:button.tag];
|
|
|
|
CGPoint headerPoint = CGPointMake(headerRect.origin.x, headerRect.origin.y);
|
|
|
|
[self.feedTitlesTable setContentOffset:headerPoint animated:YES];
|
|
|
|
}
|
|
|
|
|
2012-10-03 15:46:02 -07:00
|
|
|
}
|
|
|
|
|
2012-12-20 12:08:35 -08:00
|
|
|
- (BOOL)isFeedVisible:(id)feedId {
|
|
|
|
NSString *feedIdStr = [NSString stringWithFormat:@"%@",feedId];
|
|
|
|
BOOL isSocial = [appDelegate isSocialFeed:feedIdStr];
|
|
|
|
|
|
|
|
NSDictionary *feed = isSocial ?
|
|
|
|
[appDelegate.dictSocialFeeds objectForKey:feedIdStr] :
|
|
|
|
[appDelegate.dictFeeds objectForKey:feedIdStr];
|
|
|
|
|
|
|
|
NSIndexPath *stillVisible = [self.stillVisibleFeeds objectForKey:feedIdStr];
|
|
|
|
if (!stillVisible &&
|
|
|
|
appDelegate.selectedIntelligence >= 1 &&
|
|
|
|
[[feed objectForKey:@"ps"] intValue] <= 0) {
|
|
|
|
return NO;
|
|
|
|
} else if (!stillVisible &&
|
|
|
|
!self.viewShowingAllFeeds &&
|
|
|
|
([[feed objectForKey:@"ps"] intValue] <= 0 &&
|
|
|
|
[[feed objectForKey:@"nt"] intValue] <= 0)) {
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
2012-08-12 16:50:34 -07:00
|
|
|
- (void)changeToAllMode {
|
|
|
|
[self.intelligenceControl setSelectedSegmentIndex:0];
|
2012-12-20 12:08:35 -08:00
|
|
|
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
|
2012-08-12 16:50:34 -07:00
|
|
|
[userPreferences setInteger:-1 forKey:@"selectedIntelligence"];
|
|
|
|
[userPreferences synchronize];
|
|
|
|
}
|
|
|
|
|
2011-08-02 09:16:54 -07:00
|
|
|
- (IBAction)selectIntelligence {
|
2012-07-10 12:34:58 -07:00
|
|
|
[MBProgressHUD hideHUDForView:self.feedTitlesTable animated:NO];
|
2012-07-14 01:16:35 -07:00
|
|
|
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.innerView animated:YES];
|
2012-07-09 18:17:01 -07:00
|
|
|
hud.mode = MBProgressHUDModeText;
|
|
|
|
hud.removeFromSuperViewOnHide = YES;
|
|
|
|
|
2013-02-06 18:42:15 -08:00
|
|
|
NSIndexPath *topRow;
|
|
|
|
if ([[self.feedTitlesTable indexPathsForVisibleRows] count]) {
|
|
|
|
topRow = [[self.feedTitlesTable indexPathsForVisibleRows] objectAtIndex:0];
|
|
|
|
}
|
2012-07-09 17:32:22 -07:00
|
|
|
int selectedSegmentIndex = [self.intelligenceControl selectedSegmentIndex];
|
2012-12-20 12:08:35 -08:00
|
|
|
self.stillVisibleFeeds = [NSMutableDictionary dictionary];
|
2011-08-27 15:53:51 -07:00
|
|
|
|
2012-10-03 15:46:02 -07:00
|
|
|
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
|
2012-12-20 12:08:35 -08:00
|
|
|
int direction;
|
2012-07-09 17:32:22 -07:00
|
|
|
if (selectedSegmentIndex == 0) {
|
2012-07-12 22:05:23 -07:00
|
|
|
hud.labelText = @"All Stories";
|
2012-07-16 19:45:14 -07:00
|
|
|
[userPreferences setInteger:-1 forKey:@"selectedIntelligence"];
|
2012-07-09 17:32:22 -07:00
|
|
|
[userPreferences synchronize];
|
|
|
|
|
2012-12-20 12:08:35 -08:00
|
|
|
direction = -1;
|
2012-07-09 17:42:32 -07:00
|
|
|
self.viewShowingAllFeeds = YES;
|
2012-12-20 12:08:35 -08:00
|
|
|
[appDelegate setSelectedIntelligence:0];
|
2012-07-09 18:17:01 -07:00
|
|
|
} else if(selectedSegmentIndex == 1) {
|
2012-07-12 22:05:23 -07:00
|
|
|
hud.labelText = @"Unread Stories";
|
2012-07-16 19:45:14 -07:00
|
|
|
[userPreferences setInteger:0 forKey:@"selectedIntelligence"];
|
2012-07-09 17:32:22 -07:00
|
|
|
[userPreferences synchronize];
|
|
|
|
|
2012-12-20 12:08:35 -08:00
|
|
|
direction = self.viewShowingAllFeeds ? 1 : -1;
|
2012-07-09 17:42:32 -07:00
|
|
|
self.viewShowingAllFeeds = NO;
|
2012-12-20 12:08:35 -08:00
|
|
|
[appDelegate setSelectedIntelligence:0];
|
2012-07-09 17:32:22 -07:00
|
|
|
} else {
|
2012-07-12 22:05:23 -07:00
|
|
|
hud.labelText = @"Focus Stories";
|
2012-07-16 19:45:14 -07:00
|
|
|
[userPreferences setInteger:1 forKey:@"selectedIntelligence"];
|
2012-07-09 17:32:22 -07:00
|
|
|
[userPreferences synchronize];
|
|
|
|
|
2012-12-20 12:08:35 -08:00
|
|
|
direction = 1;
|
|
|
|
self.viewShowingAllFeeds = NO;
|
2012-07-09 17:32:22 -07:00
|
|
|
[appDelegate setSelectedIntelligence:1];
|
2011-08-24 21:44:16 -07:00
|
|
|
}
|
2011-08-02 18:19:46 -07:00
|
|
|
|
2012-12-20 12:08:35 -08:00
|
|
|
[self calculateFeedLocations];
|
|
|
|
[self.feedTitlesTable reloadData];
|
2012-06-26 12:29:37 -07:00
|
|
|
|
2012-12-20 12:08:35 -08:00
|
|
|
NSIndexPath *newMiddleRow;
|
2013-02-06 18:42:15 -08:00
|
|
|
if (topRow && [self.feedTitlesTable numberOfRowsInSection:topRow.section] == 0) {
|
2012-12-20 12:08:35 -08:00
|
|
|
newMiddleRow = [[self.feedTitlesTable indexPathsForVisibleRows] objectAtIndex:0];
|
2013-02-06 18:42:15 -08:00
|
|
|
} else if (topRow) {
|
2012-12-20 12:08:35 -08:00
|
|
|
newMiddleRow = [NSIndexPath indexPathForRow:0 inSection:topRow.section];
|
|
|
|
}
|
2013-02-06 18:42:15 -08:00
|
|
|
if (newMiddleRow) {
|
|
|
|
[self.feedTitlesTable scrollToRowAtIndexPath:newMiddleRow
|
|
|
|
atScrollPosition:UITableViewScrollPositionTop
|
|
|
|
animated:NO];
|
|
|
|
}
|
2012-12-20 12:08:35 -08:00
|
|
|
[self.feedTitlesTable
|
|
|
|
reloadRowsAtIndexPaths:[self.feedTitlesTable indexPathsForVisibleRows]
|
|
|
|
withRowAnimation:direction == 1 ? UITableViewRowAnimationLeft : UITableViewRowAnimationRight];
|
|
|
|
[self redrawUnreadCounts];
|
2011-10-14 16:35:40 -07:00
|
|
|
|
2012-12-20 12:08:35 -08:00
|
|
|
[hud hide:YES afterDelay:0.5];
|
2011-08-02 10:13:06 -07:00
|
|
|
}
|
|
|
|
|
2011-08-27 15:53:51 -07:00
|
|
|
- (void)redrawUnreadCounts {
|
|
|
|
for (UITableViewCell *cell in self.feedTitlesTable.visibleCells) {
|
|
|
|
[cell setNeedsDisplay];
|
|
|
|
}
|
2012-10-07 15:47:21 -04:00
|
|
|
for (UIView *view in self.feedTitlesTable.subviews) {
|
|
|
|
if ([view class] == [FolderTitleView class]) {
|
|
|
|
[view setNeedsDisplay];
|
|
|
|
}
|
|
|
|
}
|
2011-08-27 15:53:51 -07:00
|
|
|
}
|
|
|
|
|
2012-12-20 12:08:35 -08:00
|
|
|
- (void)calculateFeedLocations {
|
2011-08-02 10:13:06 -07:00
|
|
|
self.activeFeedLocations = [NSMutableDictionary dictionary];
|
2012-12-20 12:08:35 -08:00
|
|
|
self.visibleFolders = [NSMutableDictionary dictionary];
|
|
|
|
|
2011-10-04 18:01:35 -07:00
|
|
|
for (NSString *folderName in appDelegate.dictFoldersArray) {
|
2012-12-07 15:17:22 -08:00
|
|
|
if ([folderName isEqualToString:@"river_global"]) continue;
|
2011-10-04 18:01:35 -07:00
|
|
|
NSArray *folder = [appDelegate.dictFolders objectForKey:folderName];
|
2011-08-24 21:44:16 -07:00
|
|
|
NSMutableArray *feedLocations = [NSMutableArray array];
|
2012-06-26 11:45:42 -07:00
|
|
|
for (int f = 0; f < [folder count]; f++) {
|
2011-08-24 21:44:16 -07:00
|
|
|
id feedId = [folder objectAtIndex:f];
|
2012-12-20 12:08:35 -08:00
|
|
|
if ([self isFeedVisible:feedId]) {
|
2011-08-24 21:44:16 -07:00
|
|
|
NSNumber *location = [NSNumber numberWithInt:f];
|
|
|
|
[feedLocations addObject:location];
|
2012-12-20 12:08:35 -08:00
|
|
|
if (![[self.visibleFolders objectForKey:folderName] boolValue]) {
|
|
|
|
[self.visibleFolders setObject:[NSNumber numberWithBool:YES] forKey:folderName];
|
2011-08-24 21:44:16 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
[self.activeFeedLocations setObject:feedLocations forKey:folderName];
|
|
|
|
}
|
2011-08-02 09:16:54 -07:00
|
|
|
}
|
|
|
|
|
2011-08-02 18:03:11 -07:00
|
|
|
+ (int)computeMaxScoreForFeed:(NSDictionary *)feed {
|
2011-08-24 21:44:16 -07:00
|
|
|
int maxScore = -2;
|
|
|
|
if ([[feed objectForKey:@"ng"] intValue] > 0) maxScore = -1;
|
|
|
|
if ([[feed objectForKey:@"nt"] intValue] > 0) maxScore = 0;
|
|
|
|
if ([[feed objectForKey:@"ps"] intValue] > 0) maxScore = 1;
|
|
|
|
return maxScore;
|
2011-08-02 18:03:11 -07:00
|
|
|
}
|
|
|
|
|
2011-08-04 17:58:28 -07:00
|
|
|
#pragma mark -
|
|
|
|
#pragma mark Favicons
|
|
|
|
|
|
|
|
|
|
|
|
- (void)loadFavicons {
|
2011-08-24 21:44:16 -07:00
|
|
|
NSString *urlString = [NSString stringWithFormat:@"http://%@/reader/favicons",
|
|
|
|
NEWSBLUR_URL];
|
|
|
|
NSURL *url = [NSURL URLWithString:urlString];
|
2012-08-10 18:10:07 -07:00
|
|
|
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
|
2011-08-24 21:44:16 -07:00
|
|
|
|
|
|
|
[request setDidFinishSelector:@selector(saveAndDrawFavicons:)];
|
|
|
|
[request setDidFailSelector:@selector(requestFailed:)];
|
|
|
|
[request setDelegate:self];
|
|
|
|
[request startAsynchronous];
|
2011-08-04 17:58:28 -07:00
|
|
|
}
|
|
|
|
|
2012-06-26 11:45:42 -07:00
|
|
|
- (void)loadAvatars {
|
|
|
|
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
|
|
|
|
dispatch_async(queue, ^{
|
2012-07-15 17:18:23 -07:00
|
|
|
for (NSString *feed_id in [appDelegate.dictSocialFeeds allKeys]) {
|
2012-06-26 11:45:42 -07:00
|
|
|
NSDictionary *feed = [appDelegate.dictSocialFeeds objectForKey:feed_id];
|
2012-07-11 10:33:39 -07:00
|
|
|
NSURL *imageURL = [NSURL URLWithString:[feed objectForKey:@"photo_url"]];
|
2012-06-26 11:45:42 -07:00
|
|
|
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
|
|
|
|
UIImage *faviconImage = [UIImage imageWithData:imageData];
|
2012-07-11 18:08:07 -07:00
|
|
|
faviconImage = [Utilities roundCorneredImage:faviconImage radius:6];
|
2012-07-02 10:45:25 -07:00
|
|
|
|
2012-06-26 11:45:42 -07:00
|
|
|
[Utilities saveImage:faviconImage feedId:feed_id];
|
|
|
|
}
|
|
|
|
|
|
|
|
[Utilities saveimagesToDisk];
|
|
|
|
|
|
|
|
dispatch_sync(dispatch_get_main_queue(), ^{
|
|
|
|
[self.feedTitlesTable reloadData];
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2012-07-11 18:08:07 -07:00
|
|
|
|
2012-07-02 10:45:25 -07:00
|
|
|
|
2011-08-04 17:58:28 -07:00
|
|
|
- (void)saveAndDrawFavicons:(ASIHTTPRequest *)request {
|
|
|
|
NSString *responseString = [request responseString];
|
2012-07-27 16:10:13 -07:00
|
|
|
NSData *responseData=[responseString dataUsingEncoding:NSUTF8StringEncoding];
|
|
|
|
NSError *error;
|
|
|
|
NSDictionary *results = [NSJSONSerialization
|
|
|
|
JSONObjectWithData:responseData
|
|
|
|
options:kNilOptions
|
|
|
|
error:&error];
|
2011-08-24 21:44:16 -07:00
|
|
|
|
2011-10-18 08:56:13 -07:00
|
|
|
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
|
|
|
|
dispatch_async(queue, ^{
|
|
|
|
for (id feed_id in results) {
|
2012-07-27 16:10:13 -07:00
|
|
|
NSMutableDictionary *feed = [[appDelegate.dictFeeds objectForKey:feed_id] mutableCopy];
|
2011-10-18 08:56:13 -07:00
|
|
|
[feed setValue:[results objectForKey:feed_id] forKey:@"favicon"];
|
|
|
|
[appDelegate.dictFeeds setValue:feed forKey:feed_id];
|
|
|
|
|
|
|
|
NSString *favicon = [feed objectForKey:@"favicon"];
|
|
|
|
if ((NSNull *)favicon != [NSNull null] && [favicon length] > 0) {
|
|
|
|
NSData *imageData = [NSData dataWithBase64EncodedString:favicon];
|
|
|
|
UIImage *faviconImage = [UIImage imageWithData:imageData];
|
|
|
|
[Utilities saveImage:faviconImage feedId:feed_id];
|
|
|
|
}
|
2011-10-14 16:35:40 -07:00
|
|
|
}
|
2011-10-18 08:56:13 -07:00
|
|
|
[Utilities saveimagesToDisk];
|
|
|
|
|
|
|
|
dispatch_sync(dispatch_get_main_queue(), ^{
|
|
|
|
[self.feedTitlesTable reloadData];
|
|
|
|
});
|
|
|
|
});
|
2011-08-24 21:44:16 -07:00
|
|
|
|
2011-08-04 17:58:28 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)requestFailed:(ASIHTTPRequest *)request {
|
|
|
|
NSError *error = [request error];
|
|
|
|
NSLog(@"Error: %@", error);
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
#pragma mark PullToRefresh
|
|
|
|
|
|
|
|
// called when the user pulls-to-refresh
|
|
|
|
- (void)pullToRefreshViewShouldRefresh:(PullToRefreshView *)view {
|
2012-08-16 20:10:50 -07:00
|
|
|
self.inPullToRefresh_ = YES;
|
2012-08-09 10:18:15 -07:00
|
|
|
[self fetchFeedList:NO];
|
2012-07-02 11:42:06 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)refreshFeedList {
|
2012-12-10 20:22:21 -08:00
|
|
|
[self refreshFeedList:nil];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)refreshFeedList:(id)feedId {
|
2012-06-29 17:37:49 -07:00
|
|
|
// refresh the feed
|
2012-12-10 20:22:21 -08:00
|
|
|
NSString *urlString;
|
|
|
|
if (feedId) {
|
|
|
|
urlString = [NSString stringWithFormat:@"http://%@/reader/feed_unread_count?feed_id=%@",
|
|
|
|
NEWSBLUR_URL, feedId];
|
|
|
|
} else {
|
|
|
|
urlString = [NSString stringWithFormat:@"http://%@/reader/refresh_feeds",
|
|
|
|
NEWSBLUR_URL];
|
|
|
|
}
|
|
|
|
NSURL *urlFeedList = [NSURL URLWithString:urlString];
|
2012-06-29 17:37:49 -07:00
|
|
|
|
|
|
|
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:urlFeedList];
|
|
|
|
[[NSHTTPCookieStorage sharedHTTPCookieStorage]
|
|
|
|
setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
|
|
|
|
[request setDelegate:self];
|
|
|
|
[request setResponseEncoding:NSUTF8StringEncoding];
|
|
|
|
[request setDefaultResponseEncoding:NSUTF8StringEncoding];
|
|
|
|
[request setDidFinishSelector:@selector(finishRefreshingFeedList:)];
|
|
|
|
[request setDidFailSelector:@selector(requestFailed:)];
|
|
|
|
[request setTimeOutSeconds:30];
|
|
|
|
[request startAsynchronous];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)finishRefreshingFeedList:(ASIHTTPRequest *)request {
|
2012-08-09 10:18:15 -07:00
|
|
|
if ([request responseStatusCode] == 403) {
|
|
|
|
return [appDelegate showLogin];
|
|
|
|
} else if ([request responseStatusCode] >= 500) {
|
|
|
|
[pull finishedLoading];
|
|
|
|
return [self informError:@"The server barfed!"];
|
|
|
|
}
|
|
|
|
|
|
|
|
NSString *responseString = [request responseString];
|
|
|
|
NSData *responseData=[responseString dataUsingEncoding:NSUTF8StringEncoding];
|
|
|
|
NSError *error;
|
|
|
|
NSDictionary *results = [NSJSONSerialization
|
|
|
|
JSONObjectWithData:responseData
|
|
|
|
options:kNilOptions
|
|
|
|
error:&error];
|
|
|
|
|
|
|
|
NSMutableDictionary *updatedDictFeeds = [appDelegate.dictFeeds mutableCopy];
|
|
|
|
NSDictionary *newFeedCounts = [results objectForKey:@"feeds"];
|
2012-11-26 15:51:50 -08:00
|
|
|
NSInteger intelligenceLevel = [appDelegate selectedIntelligence];
|
2012-08-09 10:18:15 -07:00
|
|
|
for (id feed in newFeedCounts) {
|
|
|
|
NSString *feedIdStr = [NSString stringWithFormat:@"%@", feed];
|
|
|
|
NSMutableDictionary *newFeed = [[appDelegate.dictFeeds objectForKey:feedIdStr] mutableCopy];
|
|
|
|
NSMutableDictionary *newFeedCount = [newFeedCounts objectForKey:feed];
|
|
|
|
|
|
|
|
if ([newFeed isKindOfClass:[NSDictionary class]]) {
|
2012-11-26 15:51:50 -08:00
|
|
|
// Check if a feed goes from visible to hidden, but doesn't disappear.
|
|
|
|
if ((intelligenceLevel > 0 &&
|
|
|
|
[[newFeed objectForKey:@"ps"] intValue] > 0 &&
|
|
|
|
[[newFeedCount objectForKey:@"ps"] intValue] == 0) ||
|
|
|
|
(intelligenceLevel == 0 &&
|
|
|
|
([[newFeed objectForKey:@"ps"] intValue] > 0 || [[newFeed objectForKey:@"nt"] intValue] > 0) &&
|
|
|
|
[[newFeedCount objectForKey:@"ps"] intValue] == 0 &&
|
|
|
|
[[newFeedCount objectForKey:@"nt"] intValue] == 0)) {
|
|
|
|
NSIndexPath *indexPath;
|
|
|
|
for (int s=0; s < [appDelegate.dictFoldersArray count]; s++) {
|
|
|
|
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:s];
|
|
|
|
NSArray *activeFolderFeeds = [self.activeFeedLocations objectForKey:folderName];
|
|
|
|
NSArray *originalFolder = [appDelegate.dictFolders objectForKey:folderName];
|
|
|
|
for (int l=0; l < [activeFolderFeeds count]; l++) {
|
|
|
|
if ([[originalFolder objectAtIndex:[[activeFolderFeeds objectAtIndex:l] intValue]] intValue] == [feed intValue]) {
|
|
|
|
indexPath = [NSIndexPath indexPathForRow:l inSection:s];
|
2012-12-20 12:08:35 -08:00
|
|
|
break;
|
2012-11-26 15:51:50 -08:00
|
|
|
}
|
|
|
|
}
|
2012-12-20 12:08:35 -08:00
|
|
|
if (indexPath) break;
|
2012-11-26 15:51:50 -08:00
|
|
|
}
|
|
|
|
if (indexPath) {
|
|
|
|
[self.stillVisibleFeeds setObject:indexPath forKey:feedIdStr];
|
|
|
|
}
|
|
|
|
}
|
2012-08-09 10:18:15 -07:00
|
|
|
[newFeed setObject:[newFeedCount objectForKey:@"ng"] forKey:@"ng"];
|
|
|
|
[newFeed setObject:[newFeedCount objectForKey:@"nt"] forKey:@"nt"];
|
|
|
|
[newFeed setObject:[newFeedCount objectForKey:@"ps"] forKey:@"ps"];
|
|
|
|
[updatedDictFeeds setObject:newFeed forKey:feedIdStr];
|
|
|
|
}
|
2012-11-26 15:51:50 -08:00
|
|
|
|
2012-08-09 10:18:15 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
NSMutableDictionary *updatedDictSocialFeeds = [appDelegate.dictSocialFeeds mutableCopy];
|
|
|
|
NSDictionary *newSocialFeedCounts = [results objectForKey:@"social_feeds"];
|
|
|
|
for (id feed in newSocialFeedCounts) {
|
|
|
|
NSString *feedIdStr = [NSString stringWithFormat:@"%@", feed];
|
|
|
|
NSMutableDictionary *newFeed = [[appDelegate.dictSocialFeeds objectForKey:feedIdStr] mutableCopy];
|
|
|
|
NSMutableDictionary *newFeedCount = [newSocialFeedCounts objectForKey:feed];
|
|
|
|
|
|
|
|
if ([newFeed isKindOfClass:[NSDictionary class]]) {
|
|
|
|
[newFeed setObject:[newFeedCount objectForKey:@"ng"] forKey:@"ng"];
|
|
|
|
[newFeed setObject:[newFeedCount objectForKey:@"nt"] forKey:@"nt"];
|
|
|
|
[newFeed setObject:[newFeedCount objectForKey:@"ps"] forKey:@"ps"];
|
|
|
|
[updatedDictSocialFeeds setObject:newFeed forKey:feedIdStr];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
appDelegate.dictSocialFeeds = updatedDictSocialFeeds;
|
|
|
|
appDelegate.dictFeeds = updatedDictFeeds;
|
2012-10-14 17:30:03 -07:00
|
|
|
|
|
|
|
[appDelegate.folderCountCache removeAllObjects];
|
2012-08-09 10:18:15 -07:00
|
|
|
[self.feedTitlesTable reloadData];
|
2013-02-15 16:41:20 -08:00
|
|
|
[self refreshHeaderCounts];
|
2011-08-04 17:58:28 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// called when the date shown needs to be updated, optional
|
|
|
|
- (NSDate *)pullToRefreshViewLastUpdated:(PullToRefreshView *)view {
|
2011-08-24 21:44:16 -07:00
|
|
|
return self.lastUpdate;
|
2011-08-04 17:58:28 -07:00
|
|
|
}
|
|
|
|
|
2012-07-31 13:10:26 -07:00
|
|
|
#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;
|
2012-08-02 00:57:01 -07:00
|
|
|
CGFloat contentMargin = 5.0;
|
2012-07-31 13:10:26 -07:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2012-08-14 17:20:45 -07:00
|
|
|
- (void)resetToolbar {
|
|
|
|
self.navigationItem.leftBarButtonItem = nil;
|
|
|
|
self.navigationItem.titleView = nil;
|
|
|
|
self.navigationItem.rightBarButtonItem = nil;
|
|
|
|
}
|
|
|
|
|
2013-02-15 16:41:20 -08:00
|
|
|
- (void)refreshHeaderCounts {
|
2013-03-03 15:41:59 -08:00
|
|
|
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
|
|
|
|
[self refreshHeaderCounts:orientation];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)refreshHeaderCounts:(UIInterfaceOrientation)orientation {
|
|
|
|
if (!appDelegate.activeUsername) return;
|
|
|
|
|
2013-02-15 16:41:20 -08:00
|
|
|
UIView *userInfoView = [[UIView alloc]
|
|
|
|
initWithFrame:CGRectMake(0, 0,
|
2013-03-03 15:41:59 -08:00
|
|
|
self.view.bounds.size.width,
|
2013-02-15 16:41:20 -08:00
|
|
|
self.navigationController.toolbar.frame.size.height)];
|
2013-03-03 15:41:59 -08:00
|
|
|
int yOffset = 6;
|
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone &&
|
2013-03-03 17:37:54 -08:00
|
|
|
UIInterfaceOrientationIsLandscape(orientation)) {
|
2013-03-03 15:41:59 -08:00
|
|
|
yOffset = 0;
|
|
|
|
}
|
|
|
|
UILabel *userLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, yOffset, userInfoView.frame.size.width, 16)];
|
2013-02-15 16:41:20 -08:00
|
|
|
userLabel.text = appDelegate.activeUsername;
|
|
|
|
userLabel.font = [UIFont fontWithName:@"Helvetica-Bold" size:14.0];
|
|
|
|
userLabel.textColor = UIColorFromRGB(0x404040);
|
|
|
|
userLabel.backgroundColor = [UIColor clearColor];
|
|
|
|
userLabel.shadowColor = UIColorFromRGB(0xFAFAFA);
|
|
|
|
[userInfoView addSubview:userLabel];
|
|
|
|
|
|
|
|
[appDelegate.folderCountCache removeObjectForKey:@"everything"];
|
|
|
|
UnreadCounts *counts = [appDelegate splitUnreadCountForFolder:@"everything"];
|
2013-02-21 12:19:15 -08:00
|
|
|
UIImageView *yellow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"g_icn_unread"]];
|
|
|
|
yellow.frame = CGRectMake(0, userLabel.frame.origin.y + userLabel.frame.size.height + 4, 8, 8);
|
2013-02-15 16:41:20 -08:00
|
|
|
[userInfoView addSubview:yellow];
|
|
|
|
|
|
|
|
UILabel *neutralCount = [[UILabel alloc] init];
|
2013-02-21 12:19:15 -08:00
|
|
|
neutralCount.frame = CGRectMake(yellow.frame.size.width + yellow.frame.origin.x + 2,
|
|
|
|
yellow.frame.origin.y - 3, 100, 16);
|
2013-02-15 16:41:20 -08:00
|
|
|
neutralCount.text = [NSString stringWithFormat:@"%d", counts.nt];
|
|
|
|
neutralCount.font = [UIFont fontWithName:@"Helvetica-Bold" size:11];
|
|
|
|
neutralCount.textColor = UIColorFromRGB(0x707070);
|
|
|
|
neutralCount.backgroundColor = [UIColor clearColor];
|
|
|
|
[neutralCount sizeToFit];
|
|
|
|
[userInfoView addSubview:neutralCount];
|
|
|
|
|
2013-02-21 12:19:15 -08:00
|
|
|
UIImageView *green = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"g_icn_focus"]];
|
|
|
|
green.frame = CGRectMake(neutralCount.frame.origin.x + neutralCount.frame.size.width + 8,
|
|
|
|
yellow.frame.origin.y, 8, 8);
|
2013-02-15 16:41:20 -08:00
|
|
|
[userInfoView addSubview:green];
|
|
|
|
|
|
|
|
UILabel *positiveCount = [[UILabel alloc] init];
|
2013-02-21 12:19:15 -08:00
|
|
|
positiveCount.frame = CGRectMake(green.frame.size.width + green.frame.origin.x + 2,
|
|
|
|
green.frame.origin.y - 3, 100, 16);
|
2013-02-15 16:41:20 -08:00
|
|
|
positiveCount.text = [NSString stringWithFormat:@"%d", counts.ps];
|
|
|
|
positiveCount.font = [UIFont fontWithName:@"Helvetica-Bold" size:11];
|
|
|
|
positiveCount.textColor = UIColorFromRGB(0x707070);
|
|
|
|
positiveCount.backgroundColor = [UIColor clearColor];
|
|
|
|
[positiveCount sizeToFit];
|
|
|
|
[userInfoView addSubview:positiveCount];
|
|
|
|
|
|
|
|
|
|
|
|
self.navigationItem.titleView = userInfoView;
|
|
|
|
}
|
|
|
|
|
2012-07-31 13:10:26 -07:00
|
|
|
|
2012-06-29 17:37:49 -07:00
|
|
|
@end
|