2010-06-17 13:10:45 -04:00
|
|
|
//
|
|
|
|
// NewsBlurAppDelegate.m
|
|
|
|
// NewsBlur
|
|
|
|
//
|
|
|
|
// Created by Samuel Clay on 6/16/10.
|
2010-06-21 17:17:26 -04:00
|
|
|
// Copyright NewsBlur 2010. All rights reserved.
|
2010-06-17 13:10:45 -04:00
|
|
|
//
|
|
|
|
|
|
|
|
#import "NewsBlurAppDelegate.h"
|
2012-06-19 11:48:51 -07:00
|
|
|
#import "NewsBlurViewController.h"
|
2012-07-24 11:44:16 -07:00
|
|
|
#import "NBContainerViewController.h"
|
2010-06-21 17:17:26 -04:00
|
|
|
#import "FeedDetailViewController.h"
|
2012-07-15 15:06:06 -07:00
|
|
|
#import "DashboardViewController.h"
|
2012-06-19 10:55:46 -07:00
|
|
|
#import "FeedsMenuViewController.h"
|
2012-10-12 13:58:26 -04:00
|
|
|
#import "FeedDetailMenuViewController.h"
|
2010-06-25 18:36:01 -04:00
|
|
|
#import "StoryDetailViewController.h"
|
2012-11-05 15:12:42 -08:00
|
|
|
#import "StoryPageControl.h"
|
2012-06-13 18:07:24 -07:00
|
|
|
#import "FirstTimeUserViewController.h"
|
2012-08-12 18:50:32 -07:00
|
|
|
#import "FriendsListViewController.h"
|
2010-10-31 23:02:13 -04:00
|
|
|
#import "LoginViewController.h"
|
2011-12-02 16:23:00 -08:00
|
|
|
#import "AddSiteViewController.h"
|
|
|
|
#import "MoveSiteViewController.h"
|
2012-12-24 23:01:25 -08:00
|
|
|
#import "TrainerViewController.h"
|
2010-11-13 18:32:43 -05:00
|
|
|
#import "OriginalStoryViewController.h"
|
2012-06-21 11:53:48 -07:00
|
|
|
#import "ShareViewController.h"
|
2012-07-01 18:26:39 -07:00
|
|
|
#import "UserProfileViewController.h"
|
2012-07-24 16:03:16 -07:00
|
|
|
#import "NBContainerViewController.h"
|
2012-07-28 23:31:12 -07:00
|
|
|
#import "AFJSONRequestOperation.h"
|
2013-06-22 19:34:12 -07:00
|
|
|
#import "ASINetworkQueue.h"
|
2012-08-14 17:20:45 -07:00
|
|
|
#import "InteractionsModule.h"
|
|
|
|
#import "ActivityModule.h"
|
2012-08-15 13:04:05 -07:00
|
|
|
#import "FirstTimeUserViewController.h"
|
|
|
|
#import "FirstTimeUserAddSitesViewController.h"
|
|
|
|
#import "FirstTimeUserAddFriendsViewController.h"
|
|
|
|
#import "FirstTimeUserAddNewsBlurViewController.h"
|
2011-10-27 09:44:58 -07:00
|
|
|
#import "MBProgressHUD.h"
|
2011-10-28 18:29:33 -07:00
|
|
|
#import "Utilities.h"
|
2011-12-04 21:09:16 -08:00
|
|
|
#import "StringHelper.h"
|
2013-03-04 20:21:29 -08:00
|
|
|
#import "AuthorizeServicesViewController.h"
|
2013-05-30 18:45:51 -07:00
|
|
|
#import "Reachability.h"
|
2013-06-05 17:11:01 -07:00
|
|
|
#import "FMDatabase.h"
|
2013-06-14 19:21:30 -07:00
|
|
|
#import "FMDatabaseQueue.h"
|
2013-06-16 21:39:38 -07:00
|
|
|
#import "FMDatabaseAdditions.h"
|
2013-06-15 17:33:31 -07:00
|
|
|
#import "JSON.h"
|
2013-06-21 17:48:06 -07:00
|
|
|
#import "IASKAppSettingsViewController.h"
|
2013-07-15 18:25:09 -07:00
|
|
|
#import "OfflineSyncUnreads.h"
|
|
|
|
#import "OfflineFetchStories.h"
|
|
|
|
#import "OfflineFetchImages.h"
|
2013-08-05 18:32:43 -07:00
|
|
|
#import "OfflineCleanImages.h"
|
2013-07-19 15:04:03 -07:00
|
|
|
#import "PocketAPI.h"
|
2010-06-17 13:10:45 -04:00
|
|
|
|
|
|
|
@implementation NewsBlurAppDelegate
|
|
|
|
|
2013-09-05 16:34:39 -07:00
|
|
|
#define CURRENT_DB_VERSION 29
|
2012-11-01 15:26:50 -07:00
|
|
|
#define IS_IPHONE_5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
|
|
|
|
|
2010-06-17 13:10:45 -04:00
|
|
|
@synthesize window;
|
2012-06-09 12:54:32 -07:00
|
|
|
|
2012-07-22 14:23:50 -07:00
|
|
|
@synthesize ftuxNavigationController;
|
2010-06-21 17:17:26 -04:00
|
|
|
@synthesize navigationController;
|
2012-07-31 17:17:02 -07:00
|
|
|
@synthesize modalNavigationController;
|
2012-08-13 18:45:06 -07:00
|
|
|
@synthesize shareNavigationController;
|
2013-03-02 19:15:08 -08:00
|
|
|
@synthesize trainNavigationController;
|
2012-07-28 12:56:51 -07:00
|
|
|
@synthesize userProfileNavigationController;
|
2012-07-24 11:44:16 -07:00
|
|
|
@synthesize masterContainerViewController;
|
2012-07-10 12:34:58 -07:00
|
|
|
@synthesize dashboardViewController;
|
2010-06-21 17:17:26 -04:00
|
|
|
@synthesize feedsViewController;
|
2012-06-19 10:55:46 -07:00
|
|
|
@synthesize feedsMenuViewController;
|
2010-06-24 12:53:50 -04:00
|
|
|
@synthesize feedDetailViewController;
|
2012-10-12 13:58:26 -04:00
|
|
|
@synthesize feedDetailMenuViewController;
|
2012-06-20 09:32:55 -07:00
|
|
|
@synthesize feedDashboardViewController;
|
2012-07-01 18:26:39 -07:00
|
|
|
@synthesize friendsListViewController;
|
2012-06-18 14:31:42 -07:00
|
|
|
@synthesize fontSettingsViewController;
|
2010-06-25 18:36:01 -04:00
|
|
|
@synthesize storyDetailViewController;
|
2012-11-05 15:12:42 -08:00
|
|
|
@synthesize storyPageControl;
|
2012-06-22 18:01:08 -07:00
|
|
|
@synthesize shareViewController;
|
2010-10-31 23:02:13 -04:00
|
|
|
@synthesize loginViewController;
|
2011-12-02 16:23:00 -08:00
|
|
|
@synthesize addSiteViewController;
|
|
|
|
@synthesize moveSiteViewController;
|
2012-12-24 23:01:25 -08:00
|
|
|
@synthesize trainerViewController;
|
2010-11-13 18:32:43 -05:00
|
|
|
@synthesize originalStoryViewController;
|
2013-09-25 17:43:00 -07:00
|
|
|
@synthesize originalStoryViewNavController;
|
2012-07-01 18:26:39 -07:00
|
|
|
@synthesize userProfileViewController;
|
2013-06-21 17:48:06 -07:00
|
|
|
@synthesize preferencesViewController;
|
2010-06-17 13:10:45 -04:00
|
|
|
|
2012-07-22 14:23:50 -07:00
|
|
|
@synthesize firstTimeUserViewController;
|
|
|
|
@synthesize firstTimeUserAddSitesViewController;
|
|
|
|
@synthesize firstTimeUserAddFriendsViewController;
|
|
|
|
@synthesize firstTimeUserAddNewsBlurViewController;
|
|
|
|
|
2012-06-20 08:33:16 -07:00
|
|
|
@synthesize feedDetailPortraitYCoordinate;
|
2010-11-13 18:32:43 -05:00
|
|
|
@synthesize activeUsername;
|
2012-07-03 17:54:36 -07:00
|
|
|
@synthesize activeUserProfileId;
|
2012-07-28 14:15:20 -07:00
|
|
|
@synthesize activeUserProfileName;
|
2012-10-02 15:39:18 -07:00
|
|
|
@synthesize hasNoSites;
|
2011-10-25 09:28:05 -07:00
|
|
|
@synthesize isRiverView;
|
2012-06-26 11:45:42 -07:00
|
|
|
@synthesize isSocialView;
|
2012-08-08 10:57:38 -07:00
|
|
|
@synthesize isSocialRiverView;
|
2012-08-06 19:21:39 -07:00
|
|
|
@synthesize isTryFeedView;
|
2012-08-02 18:00:48 -07:00
|
|
|
|
2012-07-16 22:35:28 -07:00
|
|
|
@synthesize inFindingStoryMode;
|
2013-07-17 19:22:41 -07:00
|
|
|
@synthesize hasLoadedFeedDetail;
|
2012-07-16 19:45:14 -07:00
|
|
|
@synthesize tryFeedStoryId;
|
2012-07-31 23:49:51 -07:00
|
|
|
@synthesize tryFeedCategory;
|
2012-06-19 15:47:51 -07:00
|
|
|
@synthesize popoverHasFeedView;
|
2012-06-29 23:25:56 -07:00
|
|
|
@synthesize inFeedDetail;
|
2012-08-02 18:00:48 -07:00
|
|
|
@synthesize inStoryDetail;
|
2012-06-25 18:05:25 -07:00
|
|
|
@synthesize activeComment;
|
2012-07-27 12:27:13 -07:00
|
|
|
@synthesize activeShareType;
|
|
|
|
|
2010-06-25 18:36:01 -04:00
|
|
|
@synthesize activeFeed;
|
2012-12-07 16:17:48 -08:00
|
|
|
@synthesize activeClassifiers;
|
2012-12-27 00:15:26 -08:00
|
|
|
@synthesize activePopularTags;
|
|
|
|
@synthesize activePopularAuthors;
|
2011-10-20 09:32:39 -07:00
|
|
|
@synthesize activeFolder;
|
2011-10-26 08:40:31 -07:00
|
|
|
@synthesize activeFolderFeeds;
|
2010-06-25 18:36:01 -04:00
|
|
|
@synthesize activeFeedStories;
|
2011-07-29 21:27:37 -07:00
|
|
|
@synthesize activeFeedStoryLocations;
|
2011-08-08 09:58:15 -07:00
|
|
|
@synthesize activeFeedStoryLocationIds;
|
2012-06-22 18:01:08 -07:00
|
|
|
@synthesize activeFeedUserProfiles;
|
2010-06-25 18:36:01 -04:00
|
|
|
@synthesize activeStory;
|
2011-07-24 16:52:24 -07:00
|
|
|
@synthesize storyCount;
|
2012-11-26 09:54:20 -08:00
|
|
|
@synthesize storyLocationsCount;
|
2011-11-09 09:51:42 -08:00
|
|
|
@synthesize visibleUnreadCount;
|
2012-10-17 15:07:53 -07:00
|
|
|
@synthesize savedStoriesCount;
|
2013-06-16 14:09:28 -07:00
|
|
|
@synthesize totalUnfetchedStoryCount;
|
2013-06-16 21:39:38 -07:00
|
|
|
@synthesize remainingUnfetchedStoryCount;
|
|
|
|
@synthesize latestFetchedStoryDate;
|
2013-07-18 18:24:38 -07:00
|
|
|
@synthesize latestCachedImageDate;
|
2013-06-21 22:18:54 -07:00
|
|
|
@synthesize totalUncachedImagesCount;
|
|
|
|
@synthesize remainingUncachedImagesCount;
|
2011-08-09 17:58:43 -07:00
|
|
|
@synthesize originalStoryCount;
|
2011-07-29 09:06:17 -07:00
|
|
|
@synthesize selectedIntelligence;
|
2010-11-13 18:32:43 -05:00
|
|
|
@synthesize activeOriginalStoryURL;
|
2011-07-24 21:47:58 -07:00
|
|
|
@synthesize recentlyReadStories;
|
2013-07-19 12:20:51 -07:00
|
|
|
@synthesize recentlyReadStoryLocations;
|
2011-11-03 18:08:24 -07:00
|
|
|
@synthesize recentlyReadFeeds;
|
2011-08-22 18:25:33 -07:00
|
|
|
@synthesize readStories;
|
2013-09-05 12:38:06 -07:00
|
|
|
@synthesize unreadStoryHashes;
|
2012-10-14 17:30:03 -07:00
|
|
|
@synthesize folderCountCache;
|
2010-06-17 13:10:45 -04:00
|
|
|
|
2011-10-04 18:01:35 -07:00
|
|
|
@synthesize dictFolders;
|
|
|
|
@synthesize dictFeeds;
|
2012-06-26 16:24:19 -07:00
|
|
|
@synthesize dictActiveFeeds;
|
2012-06-25 15:02:20 -07:00
|
|
|
@synthesize dictSocialFeeds;
|
2013-03-04 20:21:29 -08:00
|
|
|
@synthesize dictSocialProfile;
|
2012-07-01 18:26:39 -07:00
|
|
|
@synthesize dictUserProfile;
|
2013-03-04 20:21:29 -08:00
|
|
|
@synthesize dictSocialServices;
|
2013-06-29 17:28:41 -07:00
|
|
|
@synthesize dictUnreadCounts;
|
2012-07-26 23:07:47 -07:00
|
|
|
@synthesize userInteractionsArray;
|
|
|
|
@synthesize userActivitiesArray;
|
2011-10-04 18:01:35 -07:00
|
|
|
@synthesize dictFoldersArray;
|
|
|
|
|
2013-06-05 17:11:01 -07:00
|
|
|
@synthesize database;
|
2012-08-14 17:20:45 -07:00
|
|
|
@synthesize categories;
|
|
|
|
@synthesize categoryFeeds;
|
2013-06-23 22:19:08 -07:00
|
|
|
@synthesize activeCachedImages;
|
2013-07-15 18:25:09 -07:00
|
|
|
@synthesize hasQueuedReadStories;
|
|
|
|
@synthesize offlineQueue;
|
2013-08-05 18:32:43 -07:00
|
|
|
@synthesize offlineCleaningQueue;
|
2012-08-14 17:20:45 -07:00
|
|
|
|
2011-12-03 18:22:14 -08:00
|
|
|
+ (NewsBlurAppDelegate*) sharedAppDelegate {
|
|
|
|
return (NewsBlurAppDelegate*) [UIApplication sharedApplication].delegate;
|
|
|
|
}
|
|
|
|
|
2010-06-17 13:10:45 -04:00
|
|
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
|
|
|
|
2012-06-30 00:02:08 -07:00
|
|
|
NSString *currentiPhoneVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
|
2013-07-16 18:06:36 -07:00
|
|
|
[self registerDefaultsFromSettingsBundle];
|
2012-06-30 00:02:08 -07:00
|
|
|
|
2013-03-03 14:03:56 -08:00
|
|
|
self.navigationController.delegate = self;
|
2012-07-24 16:03:16 -07:00
|
|
|
self.navigationController.viewControllers = [NSArray arrayWithObject:self.feedsViewController];
|
|
|
|
|
2012-06-30 00:02:08 -07:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
|
|
|
[ASIHTTPRequest setDefaultUserAgentString:[NSString stringWithFormat:@"NewsBlur iPad App v%@",
|
|
|
|
currentiPhoneVersion]];
|
2012-07-24 11:44:16 -07:00
|
|
|
[window addSubview:self.masterContainerViewController.view];
|
|
|
|
self.window.rootViewController = self.masterContainerViewController;
|
2012-06-09 12:54:32 -07:00
|
|
|
} else {
|
2012-07-24 16:03:16 -07:00
|
|
|
[ASIHTTPRequest setDefaultUserAgentString:[NSString stringWithFormat:@"NewsBlur iPhone App v%@",
|
|
|
|
currentiPhoneVersion]];
|
2012-07-01 12:08:30 -07:00
|
|
|
[window addSubview:self.navigationController.view];
|
2012-07-24 16:03:16 -07:00
|
|
|
self.window.rootViewController = self.navigationController;
|
2012-06-09 12:54:32 -07:00
|
|
|
}
|
2013-04-12 10:11:21 -07:00
|
|
|
|
|
|
|
|
2010-06-17 13:10:45 -04:00
|
|
|
[window makeKeyAndVisible];
|
2013-07-19 17:20:39 -07:00
|
|
|
[self performSelectorOnMainThread:@selector(showSplashView) withObject:nil waitUntilDone:NO];
|
|
|
|
|
2012-08-09 10:18:15 -07:00
|
|
|
[self.feedsViewController fetchFeedList:YES];
|
2013-07-19 17:20:39 -07:00
|
|
|
|
2013-09-24 17:18:20 -07:00
|
|
|
[[UINavigationBar appearance] setBarTintColor:UIColorFromRGB(0xE0E3DB)];
|
|
|
|
[[UIToolbar appearance] setBarTintColor:UIColorFromRGB(0xE0E3DB)];
|
|
|
|
[[UISegmentedControl appearance] setTintColor:UIColorFromRGB(0x8F918B)];
|
|
|
|
// [[UISegmentedControl appearance] setBackgroundColor:UIColorFromRGB(0x8F918B)];
|
2013-05-30 16:31:57 -07:00
|
|
|
|
2013-06-14 19:21:30 -07:00
|
|
|
[self createDatabaseConnection];
|
2013-07-19 15:04:03 -07:00
|
|
|
|
|
|
|
[[PocketAPI sharedAPI] setConsumerKey:@"16638-05adf4465390446398e53b8b"];
|
|
|
|
|
2013-05-30 16:31:57 -07:00
|
|
|
// [self showFirstTimeUser];
|
2013-05-30 19:23:10 -07:00
|
|
|
|
2013-05-30 16:31:57 -07:00
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
2013-07-16 18:06:36 -07:00
|
|
|
- (void)registerDefaultsFromSettingsBundle {
|
|
|
|
NSString *settingsBundle = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"bundle"];
|
|
|
|
if(!settingsBundle) {
|
|
|
|
NSLog(@"Could not find Settings.bundle");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[settingsBundle stringByAppendingPathComponent:@"Root.plist"]];
|
|
|
|
NSArray *preferences = [settings objectForKey:@"PreferenceSpecifiers"];
|
|
|
|
|
|
|
|
NSMutableDictionary *defaultsToRegister = [[NSMutableDictionary alloc] initWithCapacity:[preferences count]];
|
|
|
|
for(NSDictionary *prefSpecification in preferences) {
|
|
|
|
NSString *key = [prefSpecification objectForKey:@"Key"];
|
|
|
|
if (key && [[prefSpecification allKeys] containsObject:@"DefaultValue"]) {
|
|
|
|
[defaultsToRegister setObject:[prefSpecification objectForKey:@"DefaultValue"] forKey:key];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[[NSUserDefaults standardUserDefaults] registerDefaults:defaultsToRegister];
|
|
|
|
}
|
|
|
|
|
2013-05-30 16:31:57 -07:00
|
|
|
- (void)showSplashView {
|
2012-11-08 17:39:32 -08:00
|
|
|
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
|
2012-11-01 15:26:50 -07:00
|
|
|
splashView = [[UIImageView alloc] init];
|
2013-05-30 18:45:51 -07:00
|
|
|
// int rotate = 0;
|
|
|
|
// if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
|
|
|
|
// NSLog(@"UPSIDE DOWN");
|
|
|
|
// rotate = -2;
|
|
|
|
// } else if (orientation == UIInterfaceOrientationLandscapeLeft) {
|
|
|
|
// rotate = -1;
|
|
|
|
// } else if (orientation == UIInterfaceOrientationLandscapeRight) {
|
|
|
|
// rotate = 1;
|
|
|
|
// }
|
|
|
|
// splashView.transform = CGAffineTransformMakeRotation(M_PI * rotate * 90.0 / 180);
|
2012-11-08 17:39:32 -08:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad &&
|
|
|
|
UIInterfaceOrientationIsLandscape(orientation)) {
|
2013-05-30 16:31:57 -07:00
|
|
|
splashView.frame = CGRectMake(0, 0, self.view.frame.size.height, self.view.frame.size.width);
|
2012-11-08 17:39:32 -08:00
|
|
|
splashView.image = [UIImage imageNamed:@"Default-Landscape.png"];
|
|
|
|
} else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
2012-11-01 15:26:50 -07:00
|
|
|
splashView.frame = self.view.frame;
|
|
|
|
splashView.image = [UIImage imageNamed:@"Default-Portrait.png"];
|
|
|
|
} else if (IS_IPHONE_5) {
|
2013-04-12 10:11:21 -07:00
|
|
|
splashView.frame = CGRectMake(0, 0, self.window.frame.size.width, 568);
|
2012-11-01 15:26:50 -07:00
|
|
|
splashView.image = [UIImage imageNamed:@"Default-568h.png"];
|
|
|
|
} else {
|
|
|
|
splashView.frame = self.window.frame;
|
|
|
|
splashView.image = [UIImage imageNamed:@"Default.png"];
|
|
|
|
}
|
2012-11-08 17:39:32 -08:00
|
|
|
|
2013-05-30 16:31:57 -07:00
|
|
|
// [splashView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
|
2012-12-27 23:04:25 -08:00
|
|
|
splashView.alpha = 1.0;
|
2013-04-12 10:11:21 -07:00
|
|
|
[window.rootViewController.view addSubview:splashView];
|
2012-11-01 15:26:50 -07:00
|
|
|
[UIView beginAnimations:nil context:nil];
|
2012-12-27 23:04:25 -08:00
|
|
|
[UIView setAnimationDuration:.6];
|
2012-11-01 15:26:50 -07:00
|
|
|
[UIView setAnimationTransition:UIViewAnimationTransitionNone forView:window cache:YES];
|
|
|
|
[UIView setAnimationDelegate:self];
|
|
|
|
[UIView setAnimationDidStopSelector:@selector(startupAnimationDone:finished:context:)];
|
2013-05-30 16:31:57 -07:00
|
|
|
// splashView.alpha = 0;
|
2013-04-12 10:11:21 -07:00
|
|
|
splashView.frame = CGRectMake(0, -1 * splashView.frame.size.height, splashView.frame.size.width, splashView.frame.size.height);
|
|
|
|
// splashView.frame = CGRectMake(-60, -80, 440, 728);
|
2012-11-01 15:26:50 -07:00
|
|
|
[UIView commitAnimations];
|
2013-05-30 18:45:51 -07:00
|
|
|
[self setupReachability];
|
2010-06-17 13:10:45 -04:00
|
|
|
}
|
2010-11-11 20:05:53 -05:00
|
|
|
|
2011-07-29 09:06:17 -07:00
|
|
|
- (void)viewDidLoad {
|
2011-11-09 09:51:42 -08:00
|
|
|
self.visibleUnreadCount = 0;
|
2012-10-17 15:07:53 -07:00
|
|
|
self.savedStoriesCount = 0;
|
2013-06-16 14:09:28 -07:00
|
|
|
self.totalUnfetchedStoryCount = 0;
|
2013-06-16 21:39:38 -07:00
|
|
|
self.remainingUnfetchedStoryCount = 0;
|
|
|
|
self.latestFetchedStoryDate = 0;
|
2013-07-18 18:24:38 -07:00
|
|
|
self.latestCachedImageDate = 0;
|
2013-06-21 22:18:54 -07:00
|
|
|
self.totalUncachedImagesCount = 0;
|
|
|
|
self.remainingUncachedImagesCount = 0;
|
2011-07-29 09:06:17 -07:00
|
|
|
}
|
|
|
|
|
2012-11-01 15:26:50 -07:00
|
|
|
- (void)startupAnimationDone:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
|
|
|
|
[splashView removeFromSuperview];
|
|
|
|
}
|
|
|
|
|
2013-07-19 14:35:14 -07:00
|
|
|
//- (void)applicationDidBecomeActive:(UIApplication *)application {
|
|
|
|
// [[NSNotificationCenter defaultCenter] postNotificationName:AppDidBecomeActiveNotificationName object:nil];
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//- (void)applicationWillTerminate:(UIApplication *)application {
|
|
|
|
// [[NSNotificationCenter defaultCenter] postNotificationName:AppWillTerminateNotificationName object:nil];
|
|
|
|
//}
|
2013-07-19 15:04:03 -07:00
|
|
|
- (BOOL)application:(UIApplication *)application
|
|
|
|
openURL:(NSURL *)url
|
|
|
|
sourceApplication:(NSString *)sourceApplication
|
|
|
|
annotation:(id)annotation {
|
|
|
|
if ([[PocketAPI sharedAPI] handleOpenURL:url]){
|
|
|
|
return YES;
|
|
|
|
} else {
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
}
|
2013-03-06 16:23:17 -08:00
|
|
|
|
2013-05-30 18:45:51 -07:00
|
|
|
- (void)setupReachability {
|
2013-06-18 21:23:20 -04:00
|
|
|
Reachability* reach = [Reachability reachabilityWithHostname:NEWSBLUR_HOST];
|
2013-05-30 18:45:51 -07:00
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(reachabilityChanged:)
|
|
|
|
name:kReachabilityChangedNotification
|
|
|
|
object:nil];
|
|
|
|
reach.reachableBlock = ^(Reachability *reach) {
|
|
|
|
NSLog(@"Reachable: %@", reach);
|
|
|
|
};
|
|
|
|
reach.unreachableBlock = ^(Reachability *reach) {
|
|
|
|
NSLog(@"Un-Reachable: %@", reach);
|
|
|
|
};
|
|
|
|
[reach startNotifier];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)reachabilityChanged:(id)something {
|
|
|
|
NSLog(@"Reachability changed: %@", something);
|
|
|
|
}
|
2013-03-06 16:23:17 -08:00
|
|
|
|
2012-06-29 23:48:47 -07:00
|
|
|
#pragma mark -
|
2012-07-01 12:08:30 -07:00
|
|
|
#pragma mark Social Views
|
|
|
|
|
2013-09-25 17:43:00 -07:00
|
|
|
- (NSDictionary *)getUser:(NSInteger)userId {
|
2013-09-05 16:34:39 -07:00
|
|
|
for (int i = 0; i < self.activeFeedUserProfiles.count; i++) {
|
|
|
|
if ([[[self.activeFeedUserProfiles objectAtIndex:i] objectForKey:@"user_id"] intValue] == userId) {
|
|
|
|
return [self.activeFeedUserProfiles objectAtIndex:i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check DB if not found in active feed
|
|
|
|
__block NSDictionary *user;
|
|
|
|
[self.database inDatabase:^(FMDatabase *db) {
|
2013-09-25 17:43:00 -07:00
|
|
|
NSString *userSql = [NSString stringWithFormat:@"SELECT * FROM users WHERE user_id = %ld", (long)userId];
|
2013-09-05 16:34:39 -07:00
|
|
|
FMResultSet *cursor = [db executeQuery:userSql];
|
|
|
|
while ([cursor next]) {
|
|
|
|
user = [NSJSONSerialization
|
|
|
|
JSONObjectWithData:[[cursor stringForColumn:@"user_json"]
|
|
|
|
dataUsingEncoding:NSUTF8StringEncoding]
|
|
|
|
options:nil error:nil];
|
|
|
|
if (user) break;
|
|
|
|
}
|
|
|
|
}];
|
|
|
|
|
|
|
|
return user;
|
|
|
|
}
|
|
|
|
|
2012-07-28 12:56:51 -07:00
|
|
|
- (void)showUserProfileModal:(id)sender {
|
2012-08-02 18:00:48 -07:00
|
|
|
UserProfileViewController *newUserProfile = [[UserProfileViewController alloc] init];
|
|
|
|
self.userProfileViewController = newUserProfile;
|
2012-07-12 22:05:23 -07:00
|
|
|
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self.userProfileViewController];
|
2012-07-28 12:56:51 -07:00
|
|
|
self.userProfileNavigationController = navController;
|
2013-09-25 12:05:17 -07:00
|
|
|
self.userProfileNavigationController.navigationBar.translucent = NO;
|
2012-07-31 00:53:16 -07:00
|
|
|
|
2012-07-28 12:56:51 -07:00
|
|
|
|
|
|
|
// adding Done button
|
|
|
|
UIBarButtonItem *donebutton = [[UIBarButtonItem alloc]
|
2012-07-28 14:56:40 -07:00
|
|
|
initWithTitle:@"Close"
|
2012-07-28 12:56:51 -07:00
|
|
|
style:UIBarButtonItemStyleDone
|
|
|
|
target:self
|
|
|
|
action:@selector(hideUserProfileModal)];
|
|
|
|
|
2012-08-02 18:00:48 -07:00
|
|
|
newUserProfile.navigationItem.rightBarButtonItem = donebutton;
|
|
|
|
newUserProfile.navigationItem.title = self.activeUserProfileName;
|
|
|
|
newUserProfile.navigationItem.backBarButtonItem.title = self.activeUserProfileName;
|
|
|
|
[newUserProfile getUserProfile];
|
2012-07-25 17:29:29 -07:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
2012-07-28 12:56:51 -07:00
|
|
|
[self.masterContainerViewController showUserProfilePopover:sender];
|
2012-07-25 17:29:29 -07:00
|
|
|
} else {
|
2013-06-17 11:50:13 -07:00
|
|
|
[self.navigationController presentViewController:navController animated:YES completion:nil];
|
2012-07-25 17:29:29 -07:00
|
|
|
}
|
2012-07-31 23:49:51 -07:00
|
|
|
|
2012-07-12 22:05:23 -07:00
|
|
|
}
|
|
|
|
|
2012-07-28 14:15:20 -07:00
|
|
|
- (void)pushUserProfile {
|
|
|
|
UserProfileViewController *userProfileView = [[UserProfileViewController alloc] init];
|
|
|
|
|
|
|
|
|
|
|
|
// adding Done button
|
|
|
|
UIBarButtonItem *donebutton = [[UIBarButtonItem alloc]
|
2012-07-28 14:56:40 -07:00
|
|
|
initWithTitle:@"Close"
|
2012-07-28 14:15:20 -07:00
|
|
|
style:UIBarButtonItemStyleDone
|
|
|
|
target:self
|
|
|
|
action:@selector(hideUserProfileModal)];
|
|
|
|
|
|
|
|
userProfileView.navigationItem.rightBarButtonItem = donebutton;
|
|
|
|
userProfileView.navigationItem.title = self.activeUserProfileName;
|
|
|
|
userProfileView.navigationItem.backBarButtonItem.title = self.activeUserProfileName;
|
2012-07-31 10:24:38 -07:00
|
|
|
[userProfileView getUserProfile];
|
2012-08-13 23:35:11 -07:00
|
|
|
if (self.modalNavigationController.view.window == nil) {
|
|
|
|
[self.userProfileNavigationController pushViewController:userProfileView animated:YES];
|
|
|
|
} else {
|
|
|
|
[self.modalNavigationController pushViewController:userProfileView animated:YES];
|
|
|
|
};
|
|
|
|
|
2012-07-28 14:15:20 -07:00
|
|
|
}
|
|
|
|
|
2012-07-12 22:05:23 -07:00
|
|
|
- (void)hideUserProfileModal {
|
2012-07-28 12:56:51 -07:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
2012-07-31 13:10:26 -07:00
|
|
|
[self.masterContainerViewController hidePopover];
|
2012-07-28 12:56:51 -07:00
|
|
|
} else {
|
2013-06-17 11:50:13 -07:00
|
|
|
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
|
2012-07-28 12:56:51 -07:00
|
|
|
}
|
2012-07-12 22:05:23 -07:00
|
|
|
}
|
|
|
|
|
2013-06-21 17:48:06 -07:00
|
|
|
- (void)showPreferences {
|
|
|
|
if (!preferencesViewController) {
|
|
|
|
preferencesViewController = [[IASKAppSettingsViewController alloc] init];
|
|
|
|
}
|
|
|
|
|
|
|
|
preferencesViewController.delegate = self.feedsViewController;
|
|
|
|
preferencesViewController.showDoneButton = YES;
|
|
|
|
preferencesViewController.showCreditsFooter = NO;
|
|
|
|
preferencesViewController.title = @"Preferences";
|
|
|
|
BOOL enabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"offline_allowed"];
|
2013-07-11 18:36:09 -07:00
|
|
|
preferencesViewController.hiddenKeys = enabled ? nil :
|
|
|
|
[NSSet setWithObjects:@"offline_image_download",
|
|
|
|
@"offline_download_connection",
|
|
|
|
@"offline_store_limit",
|
|
|
|
nil];
|
|
|
|
[[NSUserDefaults standardUserDefaults] setObject:@"Delete offline stories..." forKey:@"offline_cache_empty_stories"];
|
2013-06-21 17:48:06 -07:00
|
|
|
|
|
|
|
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:preferencesViewController];
|
|
|
|
self.modalNavigationController = navController;
|
2013-09-25 12:05:17 -07:00
|
|
|
self.modalNavigationController.navigationBar.translucent = NO;
|
2013-06-21 17:48:06 -07:00
|
|
|
|
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
|
|
|
self.modalNavigationController.modalPresentationStyle = UIModalPresentationFormSheet;
|
|
|
|
[masterContainerViewController presentViewController:modalNavigationController animated:YES completion:nil];
|
|
|
|
} else {
|
|
|
|
[navigationController presentViewController:modalNavigationController animated:YES completion:nil];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-01 12:08:30 -07:00
|
|
|
- (void)showFindFriends {
|
2012-07-31 15:17:51 -07:00
|
|
|
FriendsListViewController *friendsBVC = [[FriendsListViewController alloc] init];
|
2012-07-31 13:10:26 -07:00
|
|
|
UINavigationController *friendsNav = [[UINavigationController alloc] initWithRootViewController:friendsListViewController];
|
|
|
|
|
2013-06-21 17:48:06 -07:00
|
|
|
self.friendsListViewController = friendsBVC;
|
2012-07-31 17:17:02 -07:00
|
|
|
self.modalNavigationController = friendsNav;
|
2013-09-25 12:05:17 -07:00
|
|
|
self.modalNavigationController.navigationBar.translucent = NO;
|
2012-07-01 12:08:30 -07:00
|
|
|
|
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
2012-07-31 17:17:02 -07:00
|
|
|
self.modalNavigationController.modalPresentationStyle = UIModalPresentationFormSheet;
|
2013-06-17 11:50:13 -07:00
|
|
|
[masterContainerViewController presentViewController:modalNavigationController animated:YES completion:nil];
|
2012-07-01 12:08:30 -07:00
|
|
|
} else {
|
2013-06-17 11:50:13 -07:00
|
|
|
[navigationController presentViewController:modalNavigationController animated:YES completion:nil];
|
2012-07-01 12:08:30 -07:00
|
|
|
}
|
2012-07-31 00:53:16 -07:00
|
|
|
[self.friendsListViewController loadSuggestedFriendsList];
|
2012-07-01 12:08:30 -07:00
|
|
|
}
|
2012-06-29 23:48:47 -07:00
|
|
|
|
2012-07-20 15:54:10 -07:00
|
|
|
- (void)showShareView:(NSString *)type
|
|
|
|
setUserId:(NSString *)userId
|
|
|
|
setUsername:(NSString *)username
|
2012-07-30 14:58:57 -07:00
|
|
|
setReplyId:(NSString *)replyId {
|
2012-07-23 16:17:49 -07:00
|
|
|
|
2013-03-02 21:27:29 -08:00
|
|
|
[self.shareViewController setCommentType:type];
|
2012-07-12 23:44:14 -07:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
2012-07-25 20:38:44 -07:00
|
|
|
[self.masterContainerViewController transitionToShareView];
|
2012-07-12 23:44:14 -07:00
|
|
|
} else {
|
2012-08-13 18:45:06 -07:00
|
|
|
if (self.shareNavigationController == nil) {
|
2012-11-28 15:21:44 -08:00
|
|
|
UINavigationController *shareNav = [[UINavigationController alloc]
|
|
|
|
initWithRootViewController:self.shareViewController];
|
2012-08-13 18:45:06 -07:00
|
|
|
self.shareNavigationController = shareNav;
|
2013-09-25 12:05:17 -07:00
|
|
|
self.shareNavigationController.navigationBar.translucent = NO;
|
2012-08-13 18:45:06 -07:00
|
|
|
}
|
2013-03-02 21:27:29 -08:00
|
|
|
[self.shareViewController setSiteInfo:type setUserId:userId setUsername:username setReplyId:replyId];
|
2013-06-17 11:50:13 -07:00
|
|
|
[self.navigationController presentViewController:self.shareNavigationController animated:YES completion:nil];
|
2012-07-12 23:44:14 -07:00
|
|
|
}
|
2013-03-02 21:27:29 -08:00
|
|
|
|
2012-11-28 15:21:44 -08:00
|
|
|
[self.shareViewController setSiteInfo:type setUserId:userId setUsername:username setReplyId:replyId];
|
2012-07-12 13:34:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)hideShareView:(BOOL)resetComment {
|
|
|
|
if (resetComment) {
|
|
|
|
self.shareViewController.commentField.text = @"";
|
2012-08-13 23:54:10 -07:00
|
|
|
self.shareViewController.currentType = nil;
|
2012-07-12 13:34:41 -07:00
|
|
|
}
|
2012-07-26 11:11:43 -07:00
|
|
|
|
2012-07-23 16:17:49 -07:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
2012-07-25 20:38:44 -07:00
|
|
|
[self.masterContainerViewController transitionFromShareView];
|
2012-07-12 23:44:14 -07:00
|
|
|
} else {
|
2013-06-17 11:50:13 -07:00
|
|
|
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
|
2012-07-26 11:11:43 -07:00
|
|
|
[self.shareViewController.commentField resignFirstResponder];
|
2012-07-12 23:44:14 -07:00
|
|
|
}
|
2012-06-29 23:48:47 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)resetShareComments {
|
|
|
|
[shareViewController clearComments];
|
|
|
|
}
|
|
|
|
|
2010-06-24 00:22:26 -04:00
|
|
|
#pragma mark -
|
2013-06-29 17:28:41 -07:00
|
|
|
#pragma mark View Management
|
2010-06-24 00:22:26 -04:00
|
|
|
|
2010-11-11 23:48:27 -05:00
|
|
|
- (void)showLogin {
|
2012-07-01 23:48:43 -07:00
|
|
|
self.dictFeeds = nil;
|
|
|
|
self.dictSocialFeeds = nil;
|
|
|
|
self.dictFolders = nil;
|
|
|
|
self.dictFoldersArray = nil;
|
2012-08-14 17:20:45 -07:00
|
|
|
self.userActivitiesArray = nil;
|
|
|
|
self.userInteractionsArray = nil;
|
2013-06-29 17:28:41 -07:00
|
|
|
self.dictUnreadCounts = nil;
|
2012-07-01 23:48:43 -07:00
|
|
|
|
|
|
|
[self.feedsViewController.feedTitlesTable reloadData];
|
2012-08-14 17:20:45 -07:00
|
|
|
[self.feedsViewController resetToolbar];
|
|
|
|
|
|
|
|
[self.dashboardViewController.interactionsModule.interactionsTable reloadData];
|
|
|
|
[self.dashboardViewController.activitiesModule.activitiesTable reloadData];
|
|
|
|
|
|
|
|
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
|
|
|
|
[userPreferences setInteger:-1 forKey:@"selectedIntelligence"];
|
|
|
|
[userPreferences synchronize];
|
|
|
|
|
2012-06-13 12:19:35 -07:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
2013-06-17 11:50:13 -07:00
|
|
|
[self.masterContainerViewController presentViewController:loginViewController animated:NO completion:nil];
|
2012-06-13 12:19:35 -07:00
|
|
|
} else {
|
2013-06-17 11:50:13 -07:00
|
|
|
[feedsMenuViewController dismissViewControllerAnimated:NO completion:nil];
|
|
|
|
[self.navigationController presentViewController:loginViewController animated:NO completion:nil];
|
2012-06-13 12:19:35 -07:00
|
|
|
}
|
2010-11-11 23:48:27 -05:00
|
|
|
}
|
|
|
|
|
2012-06-13 18:07:24 -07:00
|
|
|
- (void)showFirstTimeUser {
|
2012-08-15 13:04:05 -07:00
|
|
|
// [self.feedsViewController changeToAllMode];
|
|
|
|
|
2012-07-22 14:23:50 -07:00
|
|
|
UINavigationController *ftux = [[UINavigationController alloc] initWithRootViewController:self.firstTimeUserViewController];
|
|
|
|
|
|
|
|
self.ftuxNavigationController = ftux;
|
2013-09-25 12:05:17 -07:00
|
|
|
self.ftuxNavigationController.navigationBar.translucent = NO;
|
2012-07-22 14:23:50 -07:00
|
|
|
|
2012-06-13 18:07:24 -07:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
2012-07-22 14:23:50 -07:00
|
|
|
self.ftuxNavigationController.modalPresentationStyle = UIModalPresentationFormSheet;
|
2013-06-17 11:50:13 -07:00
|
|
|
[self.masterContainerViewController presentViewController:self.ftuxNavigationController animated:YES completion:nil];
|
2012-08-14 17:20:45 -07:00
|
|
|
|
|
|
|
self.ftuxNavigationController.view.superview.frame = CGRectMake(0, 0, 540, 540);//it's important to do this after
|
|
|
|
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
|
|
|
|
if (UIInterfaceOrientationIsPortrait(orientation)) {
|
|
|
|
self.ftuxNavigationController.view.superview.center = self.view.center;
|
|
|
|
} else {
|
|
|
|
self.ftuxNavigationController.view.superview.center = CGPointMake(self.view.center.y, self.view.center.x);
|
|
|
|
}
|
|
|
|
|
2012-06-13 18:07:24 -07:00
|
|
|
} else {
|
2013-06-17 11:50:13 -07:00
|
|
|
[self.navigationController presentViewController:self.ftuxNavigationController animated:YES completion:nil];
|
2012-06-13 18:07:24 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-02 16:23:00 -08:00
|
|
|
- (void)showMoveSite {
|
|
|
|
UINavigationController *navController = self.navigationController;
|
2012-06-08 19:36:23 -07:00
|
|
|
|
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
|
|
|
moveSiteViewController.modalPresentationStyle=UIModalPresentationFormSheet;
|
2013-06-17 11:50:13 -07:00
|
|
|
[navController presentViewController:moveSiteViewController animated:YES completion:nil];
|
2012-06-08 19:36:23 -07:00
|
|
|
} else {
|
2013-06-17 11:50:13 -07:00
|
|
|
[navController presentViewController:moveSiteViewController animated:YES completion:nil];
|
2012-06-08 19:36:23 -07:00
|
|
|
}
|
2011-10-04 18:01:35 -07:00
|
|
|
}
|
|
|
|
|
2012-12-24 23:01:25 -08:00
|
|
|
- (void)openTrainSite {
|
|
|
|
UINavigationController *navController = self.navigationController;
|
2012-12-27 00:15:26 -08:00
|
|
|
trainerViewController.feedTrainer = YES;
|
|
|
|
trainerViewController.storyTrainer = NO;
|
2012-12-24 23:01:25 -08:00
|
|
|
|
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
2012-12-27 19:34:05 -08:00
|
|
|
// trainerViewController.modalPresentationStyle=UIModalPresentationFormSheet;
|
2013-06-17 11:50:13 -07:00
|
|
|
// [navController presentViewController:trainerViewController animated:YES completion:nil];
|
2013-02-27 17:22:49 -08:00
|
|
|
[self.masterContainerViewController showTrainingPopover:self.feedDetailViewController.settingsBarButton];
|
2012-12-27 00:15:26 -08:00
|
|
|
} else {
|
2013-03-02 19:15:08 -08:00
|
|
|
if (self.trainNavigationController == nil) {
|
|
|
|
self.trainNavigationController = [[UINavigationController alloc]
|
|
|
|
initWithRootViewController:self.trainerViewController];
|
|
|
|
}
|
2013-09-25 12:05:17 -07:00
|
|
|
self.trainNavigationController.navigationBar.translucent = NO;
|
2013-06-17 11:50:13 -07:00
|
|
|
[navController presentViewController:self.trainNavigationController animated:YES completion:nil];
|
2012-12-27 00:15:26 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-27 23:04:25 -08:00
|
|
|
- (void)openTrainStory:(id)sender {
|
2012-12-27 00:15:26 -08:00
|
|
|
UINavigationController *navController = self.navigationController;
|
|
|
|
trainerViewController.feedTrainer = NO;
|
|
|
|
trainerViewController.storyTrainer = YES;
|
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
2012-12-27 23:04:25 -08:00
|
|
|
[self.masterContainerViewController showTrainingPopover:sender];
|
2012-12-24 23:01:25 -08:00
|
|
|
} else {
|
2013-03-02 19:15:08 -08:00
|
|
|
if (self.trainNavigationController == nil) {
|
|
|
|
self.trainNavigationController = [[UINavigationController alloc]
|
|
|
|
initWithRootViewController:self.trainerViewController];
|
|
|
|
}
|
2013-09-25 12:05:17 -07:00
|
|
|
self.trainNavigationController.navigationBar.translucent = NO;
|
2013-06-17 11:50:13 -07:00
|
|
|
[navController presentViewController:self.trainNavigationController animated:YES completion:nil];
|
2012-12-24 23:01:25 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-03 18:22:14 -08:00
|
|
|
- (void)reloadFeedsView:(BOOL)showLoader {
|
2012-08-09 10:18:15 -07:00
|
|
|
[feedsViewController fetchFeedList:showLoader];
|
2013-06-17 11:50:13 -07:00
|
|
|
[loginViewController dismissViewControllerAnimated:NO completion:nil];
|
2010-11-11 20:05:53 -05:00
|
|
|
}
|
2011-10-06 10:27:37 -07:00
|
|
|
|
2010-06-25 18:36:01 -04:00
|
|
|
- (void)loadFeedDetailView {
|
2012-06-20 07:39:49 -07:00
|
|
|
[self setStories:nil];
|
2012-06-22 18:01:08 -07:00
|
|
|
[self setFeedUserProfiles:nil];
|
2013-03-01 15:48:18 -08:00
|
|
|
self.inFeedDetail = YES;
|
2012-06-27 21:28:04 -07:00
|
|
|
popoverHasFeedView = YES;
|
2012-06-19 15:47:51 -07:00
|
|
|
|
2013-03-03 14:03:56 -08:00
|
|
|
UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc]
|
|
|
|
initWithTitle: @"All"
|
|
|
|
style: UIBarButtonItemStyleBordered
|
|
|
|
target: nil
|
|
|
|
action: nil];
|
|
|
|
[feedsViewController.navigationItem setBackBarButtonItem:newBackButton];
|
2013-07-19 17:20:39 -07:00
|
|
|
[feedDetailViewController resetFeedDetail];
|
2013-08-06 18:08:55 -07:00
|
|
|
|
|
|
|
[self flushQueuedReadStories:NO withCallback:^{
|
|
|
|
[feedDetailViewController fetchFeedDetail:1 withCallback:nil];
|
|
|
|
}];
|
2013-03-03 14:03:56 -08:00
|
|
|
|
2012-07-10 12:34:58 -07:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
2012-07-24 11:44:16 -07:00
|
|
|
[self.masterContainerViewController transitionToFeedDetail];
|
2012-07-24 15:29:01 -07:00
|
|
|
} else {
|
2013-03-03 14:03:56 -08:00
|
|
|
[navigationController pushViewController:feedDetailViewController
|
|
|
|
animated:YES];
|
2012-07-20 22:00:30 -07:00
|
|
|
}
|
2012-06-19 15:47:51 -07:00
|
|
|
}
|
|
|
|
|
2012-11-09 14:13:44 -08:00
|
|
|
- (void)loadTryFeedDetailView:(NSString *)feedId
|
|
|
|
withStory:(NSString *)contentId
|
|
|
|
isSocial:(BOOL)social
|
|
|
|
withUser:(NSDictionary *)user
|
|
|
|
showFindingStory:(BOOL)showHUD {
|
2012-07-29 20:55:11 -07:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
|
|
|
|
[self.navigationController popToRootViewControllerAnimated:NO];
|
2013-06-17 11:50:13 -07:00
|
|
|
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
|
2013-02-21 17:57:32 -08:00
|
|
|
if (self.feedsViewController.popoverController) {
|
|
|
|
[self.feedsViewController.popoverController dismissPopoverAnimated:NO];
|
|
|
|
}
|
2012-07-29 20:55:11 -07:00
|
|
|
}
|
|
|
|
|
2012-07-28 23:31:12 -07:00
|
|
|
NSDictionary *feed = nil;
|
2012-07-16 22:35:28 -07:00
|
|
|
|
|
|
|
if (social) {
|
|
|
|
feed = [self.dictSocialFeeds objectForKey:feedId];
|
2012-07-29 20:55:11 -07:00
|
|
|
self.isSocialView = YES;
|
2012-08-01 12:41:02 -07:00
|
|
|
self.inFindingStoryMode = YES;
|
2012-07-29 20:55:11 -07:00
|
|
|
|
2012-07-28 23:31:12 -07:00
|
|
|
if (feed == nil) {
|
|
|
|
feed = user;
|
2012-08-06 19:21:39 -07:00
|
|
|
self.isTryFeedView = YES;
|
2012-07-28 23:31:12 -07:00
|
|
|
}
|
2012-07-16 22:35:28 -07:00
|
|
|
} else {
|
|
|
|
feed = [self.dictFeeds objectForKey:feedId];
|
2012-07-28 23:31:12 -07:00
|
|
|
if (feed == nil) {
|
2012-07-29 20:55:11 -07:00
|
|
|
feed = user;
|
2012-08-06 19:21:39 -07:00
|
|
|
self.isTryFeedView = YES;
|
2012-07-29 20:55:11 -07:00
|
|
|
|
2012-07-28 23:31:12 -07:00
|
|
|
}
|
2012-07-16 22:35:28 -07:00
|
|
|
[self setIsSocialView:NO];
|
|
|
|
[self setInFindingStoryMode:NO];
|
|
|
|
}
|
2012-07-29 20:55:11 -07:00
|
|
|
|
2012-11-13 12:28:16 -08:00
|
|
|
self.tryFeedStoryId = contentId;
|
|
|
|
self.activeFeed = feed;
|
|
|
|
self.activeFolder = nil;
|
2012-07-16 19:45:14 -07:00
|
|
|
|
|
|
|
[self loadFeedDetailView];
|
2012-11-09 14:13:44 -08:00
|
|
|
|
|
|
|
if (showHUD) {
|
2013-09-11 17:05:47 -07:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
|
|
|
[self.storyPageControl showShareHUD:@"Finding story..."];
|
|
|
|
} else {
|
|
|
|
MBProgressHUD *HUD = [MBProgressHUD showHUDAddedTo:self.feedDetailViewController.view animated:YES];
|
|
|
|
HUD.labelText = @"Finding story...";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)loadStarredDetailViewWithStory:(NSString *)contentId
|
|
|
|
showFindingStory:(BOOL)showHUD {
|
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
|
|
|
|
[self.navigationController popToRootViewControllerAnimated:NO];
|
|
|
|
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
|
|
|
|
if (self.feedsViewController.popoverController) {
|
|
|
|
[self.feedsViewController.popoverController dismissPopoverAnimated:NO];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
self.isSocialRiverView = NO;
|
|
|
|
self.isRiverView = YES;
|
|
|
|
self.inFindingStoryMode = YES;
|
|
|
|
self.isSocialView = NO;
|
|
|
|
|
|
|
|
self.tryFeedStoryId = contentId;
|
|
|
|
self.activeFeed = nil;
|
|
|
|
self.activeFolder = @"saved_stories";
|
|
|
|
|
|
|
|
[self loadRiverFeedDetailView];
|
|
|
|
|
|
|
|
if (showHUD) {
|
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
|
|
|
[self.storyPageControl showShareHUD:@"Finding story..."];
|
|
|
|
} else {
|
|
|
|
MBProgressHUD *HUD = [MBProgressHUD showHUDAddedTo:self.feedDetailViewController.view animated:YES];
|
|
|
|
HUD.labelText = @"Finding story...";
|
|
|
|
}
|
2012-11-09 14:13:44 -08:00
|
|
|
}
|
2012-07-16 19:45:14 -07:00
|
|
|
}
|
|
|
|
|
2012-06-26 12:12:31 -07:00
|
|
|
- (BOOL)isSocialFeed:(NSString *)feedIdStr {
|
|
|
|
if ([feedIdStr length] > 6) {
|
|
|
|
NSString *feedIdSubStr = [feedIdStr substringToIndex:6];
|
|
|
|
if ([feedIdSubStr isEqualToString:@"social"]) {
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NO;
|
|
|
|
}
|
2012-06-26 12:29:37 -07:00
|
|
|
|
2012-07-02 13:10:00 -07:00
|
|
|
- (BOOL)isPortrait {
|
|
|
|
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
|
|
|
|
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
|
|
|
|
return YES;
|
|
|
|
} else {
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-30 17:05:39 -07:00
|
|
|
- (NSString *)orderKey {
|
|
|
|
if (self.isRiverView) {
|
|
|
|
return [NSString stringWithFormat:@"folder:%@:order", self.activeFolder];
|
|
|
|
} else {
|
|
|
|
return [NSString stringWithFormat:@"%@:order", [self.activeFeed objectForKey:@"id"]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *)readFilterKey {
|
|
|
|
if (self.isRiverView) {
|
|
|
|
return [NSString stringWithFormat:@"folder:%@:read_filter", self.activeFolder];
|
|
|
|
} else {
|
|
|
|
return [NSString stringWithFormat:@"%@:read_filter", [self.activeFeed objectForKey:@"id"]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-02 11:28:55 -07:00
|
|
|
- (void)confirmLogout {
|
|
|
|
UIAlertView *logoutConfirm = [[UIAlertView alloc] initWithTitle:@"Positive?"
|
|
|
|
message:nil
|
|
|
|
delegate:self
|
|
|
|
cancelButtonTitle:@"Cancel"
|
|
|
|
otherButtonTitles:@"Logout", nil];
|
|
|
|
[logoutConfirm show];
|
|
|
|
[logoutConfirm setTag:1];
|
|
|
|
}
|
|
|
|
|
2013-03-04 20:21:29 -08:00
|
|
|
- (void)showConnectToService:(NSString *)serviceName {
|
2013-03-05 08:49:37 -08:00
|
|
|
AuthorizeServicesViewController *serviceVC = [[AuthorizeServicesViewController alloc] init];
|
|
|
|
serviceVC.url = [NSString stringWithFormat:@"/oauth/%@_connect", serviceName];
|
|
|
|
serviceVC.type = serviceName;
|
|
|
|
serviceVC.fromStory = YES;
|
2013-03-04 20:21:29 -08:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
2013-03-05 08:49:37 -08:00
|
|
|
UINavigationController *connectNav = [[UINavigationController alloc]
|
|
|
|
initWithRootViewController:serviceVC];
|
|
|
|
self.modalNavigationController = connectNav;
|
|
|
|
self.modalNavigationController.modalPresentationStyle = UIModalPresentationFormSheet;
|
2013-09-25 12:05:17 -07:00
|
|
|
self.modalNavigationController.navigationBar.translucent = NO;
|
2013-06-17 11:50:13 -07:00
|
|
|
[self.masterContainerViewController presentViewController:modalNavigationController
|
|
|
|
animated:YES completion:nil];
|
2013-03-04 20:21:29 -08:00
|
|
|
} else {
|
2013-03-05 08:49:37 -08:00
|
|
|
[self.shareNavigationController pushViewController:serviceVC animated:YES];
|
2013-03-04 20:21:29 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)refreshUserProfile:(void(^)())callback {
|
2013-06-18 21:23:20 -04:00
|
|
|
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@/social/load_user_profile",
|
2013-03-04 20:21:29 -08:00
|
|
|
NEWSBLUR_URL]];
|
|
|
|
ASIHTTPRequest *_request = [ASIHTTPRequest requestWithURL:url];
|
|
|
|
__weak ASIHTTPRequest *request = _request;
|
|
|
|
[request setResponseEncoding:NSUTF8StringEncoding];
|
|
|
|
[request setDefaultResponseEncoding:NSUTF8StringEncoding];
|
|
|
|
[request setFailedBlock:^(void) {
|
|
|
|
NSLog(@"Failed user profile");
|
|
|
|
callback();
|
|
|
|
}];
|
|
|
|
[request setCompletionBlock:^(void) {
|
|
|
|
NSString *responseString = [request responseString];
|
|
|
|
NSData *responseData=[responseString dataUsingEncoding:NSUTF8StringEncoding];
|
|
|
|
NSError *error;
|
|
|
|
NSDictionary *results = [NSJSONSerialization
|
|
|
|
JSONObjectWithData:responseData
|
|
|
|
options:kNilOptions
|
|
|
|
error:&error];
|
|
|
|
|
|
|
|
self.dictUserProfile = [results objectForKey:@"user_profile"];
|
|
|
|
self.dictSocialServices = [results objectForKey:@"services"];
|
|
|
|
callback();
|
|
|
|
}];
|
|
|
|
[request setTimeOutSeconds:30];
|
|
|
|
[request startAsynchronous];
|
|
|
|
}
|
|
|
|
|
2012-07-02 11:28:55 -07:00
|
|
|
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
|
|
|
|
if (alertView.tag == 1) { // this is logout
|
|
|
|
if (buttonIndex == 0) {
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
NSLog(@"Logging out...");
|
2013-06-18 21:23:20 -04:00
|
|
|
NSString *urlS = [NSString stringWithFormat:@"%@/reader/logout?api=1",
|
2012-07-02 11:28:55 -07:00
|
|
|
NEWSBLUR_URL];
|
|
|
|
NSURL *url = [NSURL URLWithString:urlS];
|
|
|
|
|
|
|
|
__block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
|
|
|
|
[request setDelegate:self];
|
|
|
|
[request setResponseEncoding:NSUTF8StringEncoding];
|
|
|
|
[request setDefaultResponseEncoding:NSUTF8StringEncoding];
|
|
|
|
[request setFailedBlock:^(void) {
|
|
|
|
[MBProgressHUD hideHUDForView:self.view animated:YES];
|
|
|
|
}];
|
|
|
|
[request setCompletionBlock:^(void) {
|
|
|
|
NSLog(@"Logout successful");
|
|
|
|
[MBProgressHUD hideHUDForView:self.view animated:YES];
|
|
|
|
[self showLogin];
|
|
|
|
}];
|
|
|
|
[request setTimeOutSeconds:30];
|
|
|
|
[request startAsynchronous];
|
|
|
|
|
|
|
|
[ASIHTTPRequest setSessionCookies:nil];
|
|
|
|
|
|
|
|
[MBProgressHUD hideHUDForView:self.view animated:YES];
|
|
|
|
MBProgressHUD *HUD = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
|
|
|
|
HUD.labelText = @"Logging out...";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-20 07:39:49 -07:00
|
|
|
- (void)loadRiverFeedDetailView {
|
|
|
|
[self setStories:nil];
|
2012-06-22 18:01:08 -07:00
|
|
|
[self setFeedUserProfiles:nil];
|
2012-06-29 23:25:56 -07:00
|
|
|
self.inFeedDetail = YES;
|
2012-06-27 14:37:37 -07:00
|
|
|
|
2012-06-20 07:39:49 -07:00
|
|
|
[feedDetailViewController resetFeedDetail];
|
2013-08-06 18:08:55 -07:00
|
|
|
|
|
|
|
[self flushQueuedReadStories:NO withCallback:^{
|
|
|
|
[feedDetailViewController fetchRiverPage:1 withCallback:nil];
|
|
|
|
}];
|
2012-07-10 12:34:58 -07:00
|
|
|
|
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
2012-07-24 16:03:16 -07:00
|
|
|
[self.masterContainerViewController transitionToFeedDetail];
|
|
|
|
} else {
|
|
|
|
UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc] initWithTitle: @"All"
|
|
|
|
style: UIBarButtonItemStyleBordered
|
|
|
|
target: nil
|
|
|
|
action: nil];
|
|
|
|
[feedsViewController.navigationItem setBackBarButtonItem: newBackButton];
|
|
|
|
UINavigationController *navController = self.navigationController;
|
|
|
|
[navController pushViewController:feedDetailViewController animated:YES];
|
|
|
|
}
|
2012-06-20 07:39:49 -07:00
|
|
|
}
|
|
|
|
|
2012-06-29 21:15:43 -07:00
|
|
|
- (void)adjustStoryDetailWebView {
|
2012-07-12 13:34:41 -07:00
|
|
|
// change UIWebView
|
2012-11-07 17:54:16 -08:00
|
|
|
[storyPageControl.currentPage changeWebViewWidth];
|
|
|
|
[storyPageControl.nextPage changeWebViewWidth];
|
2012-11-14 17:31:52 -08:00
|
|
|
[storyPageControl.previousPage changeWebViewWidth];
|
2012-07-23 15:27:20 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)calibrateStoryTitles {
|
|
|
|
[self.feedDetailViewController checkScroll];
|
|
|
|
[self.feedDetailViewController changeActiveFeedDetailRow];
|
|
|
|
|
|
|
|
}
|
2012-07-12 13:34:41 -07:00
|
|
|
|
2012-12-12 15:08:24 -08:00
|
|
|
- (void)recalculateIntelligenceScores:(id)feedId {
|
2012-12-13 12:12:00 -08:00
|
|
|
NSString *feedIdStr = [NSString stringWithFormat:@"%@", feedId];
|
|
|
|
NSMutableArray *newFeedStories = [NSMutableArray array];
|
2012-12-12 15:08:24 -08:00
|
|
|
|
2012-12-13 12:12:00 -08:00
|
|
|
for (NSDictionary *story in self.activeFeedStories) {
|
|
|
|
NSString *storyFeedId = [NSString stringWithFormat:@"%@",
|
|
|
|
[story objectForKey:@"story_feed_id"]];
|
|
|
|
if (![storyFeedId isEqualToString:feedIdStr]) {
|
|
|
|
[newFeedStories addObject:story];
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
NSMutableDictionary *newStory = [story mutableCopy];
|
|
|
|
|
|
|
|
// If the story is visible, mark it as sticky so it doesn;t go away on page loads.
|
2013-09-25 17:43:00 -07:00
|
|
|
NSInteger score = [NewsBlurAppDelegate computeStoryScore:[story objectForKey:@"intelligence"]];
|
2012-12-13 12:12:00 -08:00
|
|
|
if (score >= self.selectedIntelligence) {
|
|
|
|
[newStory setObject:[NSNumber numberWithBool:YES] forKey:@"sticky"];
|
|
|
|
}
|
|
|
|
|
|
|
|
NSNumber *zero = [NSNumber numberWithInt:0];
|
|
|
|
NSMutableDictionary *intelligence = [NSMutableDictionary
|
|
|
|
dictionaryWithObjects:[NSArray arrayWithObjects:
|
|
|
|
[zero copy], [zero copy],
|
|
|
|
[zero copy], [zero copy], nil]
|
|
|
|
forKeys:[NSArray arrayWithObjects:
|
|
|
|
@"author", @"feed", @"tags", @"title", nil]];
|
|
|
|
NSDictionary *classifiers = [self.activeClassifiers objectForKey:feedIdStr];
|
|
|
|
|
|
|
|
for (NSString *title in [classifiers objectForKey:@"titles"]) {
|
|
|
|
if ([[intelligence objectForKey:@"title"] intValue] <= 0 &&
|
|
|
|
[[story objectForKey:@"story_title"] containsString:title]) {
|
|
|
|
int score = [[[classifiers objectForKey:@"titles"] objectForKey:title] intValue];
|
|
|
|
[intelligence setObject:[NSNumber numberWithInt:score] forKey:@"title"];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (NSString *author in [classifiers objectForKey:@"authors"]) {
|
|
|
|
if ([[intelligence objectForKey:@"author"] intValue] <= 0 &&
|
2012-12-28 11:34:06 -08:00
|
|
|
[[story objectForKey:@"story_authors"] class] != [NSNull class] &&
|
2012-12-13 12:12:00 -08:00
|
|
|
[[story objectForKey:@"story_authors"] containsString:author]) {
|
|
|
|
int score = [[[classifiers objectForKey:@"authors"] objectForKey:author] intValue];
|
|
|
|
[intelligence setObject:[NSNumber numberWithInt:score] forKey:@"author"];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (NSString *tag in [classifiers objectForKey:@"tags"]) {
|
|
|
|
if ([[intelligence objectForKey:@"tags"] intValue] <= 0 &&
|
2012-12-28 11:34:06 -08:00
|
|
|
[[story objectForKey:@"story_tags"] class] != [NSNull class] &&
|
2012-12-13 12:12:00 -08:00
|
|
|
[[story objectForKey:@"story_tags"] containsObject:tag]) {
|
|
|
|
int score = [[[classifiers objectForKey:@"tags"] objectForKey:tag] intValue];
|
|
|
|
[intelligence setObject:[NSNumber numberWithInt:score] forKey:@"tags"];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (NSString *feed in [classifiers objectForKey:@"feeds"]) {
|
|
|
|
if ([[intelligence objectForKey:@"feed"] intValue] <= 0 &&
|
2012-12-27 18:37:05 -08:00
|
|
|
[storyFeedId isEqualToString:feed]) {
|
2012-12-13 12:12:00 -08:00
|
|
|
int score = [[[classifiers objectForKey:@"feeds"] objectForKey:feed] intValue];
|
|
|
|
[intelligence setObject:[NSNumber numberWithInt:score] forKey:@"feed"];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[newStory setObject:intelligence forKey:@"intelligence"];
|
|
|
|
[newFeedStories addObject:newStory];
|
|
|
|
}
|
|
|
|
|
|
|
|
self.activeFeedStories = newFeedStories;
|
2012-12-12 15:08:24 -08:00
|
|
|
}
|
|
|
|
|
2012-06-20 08:33:16 -07:00
|
|
|
- (void)dragFeedDetailView:(float)y {
|
2012-06-24 20:08:39 -07:00
|
|
|
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
|
|
|
|
|
2012-07-10 12:34:58 -07:00
|
|
|
if (UIInterfaceOrientationIsPortrait(storyDetailViewController.interfaceOrientation)) {
|
2012-06-22 19:15:48 -07:00
|
|
|
y = y + 20;
|
|
|
|
|
|
|
|
if(y > 955) {
|
|
|
|
self.feedDetailPortraitYCoordinate = 960;
|
|
|
|
} else if(y < 950 && y > 200) {
|
2012-06-20 08:33:16 -07:00
|
|
|
self.feedDetailPortraitYCoordinate = y;
|
2012-06-22 19:15:48 -07:00
|
|
|
}
|
|
|
|
|
2012-06-24 20:08:39 -07:00
|
|
|
[userPreferences setInteger:self.feedDetailPortraitYCoordinate forKey:@"feedDetailPortraitYCoordinate"];
|
|
|
|
[userPreferences synchronize];
|
2012-06-29 21:15:43 -07:00
|
|
|
[self adjustStoryDetailWebView];
|
2012-06-20 08:33:16 -07:00
|
|
|
}
|
2011-10-25 09:47:55 -07:00
|
|
|
}
|
|
|
|
|
2012-06-20 19:18:29 -07:00
|
|
|
- (void)changeActiveFeedDetailRow {
|
|
|
|
[feedDetailViewController changeActiveFeedDetailRow];
|
2012-06-18 16:45:36 -07:00
|
|
|
}
|
|
|
|
|
2010-06-25 18:36:01 -04:00
|
|
|
- (void)loadStoryDetailView {
|
2011-10-27 09:44:58 -07:00
|
|
|
NSString *feedTitle;
|
|
|
|
if (self.isRiverView) {
|
2012-10-03 15:46:02 -07:00
|
|
|
if ([self.activeFolder isEqualToString:@"river_blurblogs"]) {
|
|
|
|
feedTitle = @"All Shared Stories";
|
2012-12-07 15:17:22 -08:00
|
|
|
} else if ([self.activeFolder isEqualToString:@"river_global"]) {
|
|
|
|
feedTitle = @"Global Shared Stories";
|
2012-10-03 15:46:02 -07:00
|
|
|
} else if ([self.activeFolder isEqualToString:@"everything"]) {
|
|
|
|
feedTitle = @"All Stories";
|
2012-10-17 15:07:53 -07:00
|
|
|
} else if ([self.activeFolder isEqualToString:@"saved_stories"]) {
|
|
|
|
feedTitle = @"Saved Stories";
|
2012-10-03 15:46:02 -07:00
|
|
|
} else {
|
|
|
|
feedTitle = self.activeFolder;
|
|
|
|
}
|
2011-10-27 09:44:58 -07:00
|
|
|
} else {
|
|
|
|
feedTitle = [activeFeed objectForKey:@"feed_title"];
|
|
|
|
}
|
2012-07-20 19:55:38 -07:00
|
|
|
|
2013-09-25 17:43:00 -07:00
|
|
|
NSInteger activeStoryLocation = [self locationOfActiveStory];
|
2012-12-18 17:29:23 -08:00
|
|
|
if (activeStoryLocation >= 0) {
|
|
|
|
BOOL animated = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad &&
|
|
|
|
!self.tryFeedCategory);
|
|
|
|
[self.storyPageControl changePage:activeStoryLocation animated:animated];
|
|
|
|
// [self.storyPageControl updatePageWithActiveStory:activeStoryLocation];
|
|
|
|
}
|
|
|
|
|
2012-07-24 16:03:16 -07:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
|
2013-09-24 17:18:20 -07:00
|
|
|
if ([feedTitle length] >= 12) {
|
|
|
|
feedTitle = [NSString stringWithFormat:@"%@...", [feedTitle substringToIndex:MIN(9, [feedTitle length])]];
|
|
|
|
}
|
|
|
|
UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc] initWithTitle:feedTitle style: UIBarButtonItemStylePlain target: nil action: nil];
|
2012-06-09 12:54:32 -07:00
|
|
|
[feedDetailViewController.navigationItem setBackBarButtonItem: newBackButton];
|
2012-11-05 15:12:42 -08:00
|
|
|
UINavigationController *navController = self.navigationController;
|
|
|
|
[navController pushViewController:storyPageControl animated:YES];
|
2012-07-15 15:06:06 -07:00
|
|
|
[navController.navigationItem setLeftBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:feedTitle style:UIBarButtonItemStyleBordered target:nil action:nil]];
|
2012-06-09 12:54:32 -07:00
|
|
|
navController.navigationItem.hidesBackButton = YES;
|
|
|
|
}
|
2012-11-07 17:54:16 -08:00
|
|
|
|
2013-09-11 17:05:47 -07:00
|
|
|
[MBProgressHUD hideHUDForView:self.storyPageControl.view animated:YES];
|
2012-06-11 16:56:38 -07:00
|
|
|
}
|
|
|
|
|
2011-08-25 12:09:41 -07:00
|
|
|
- (void)navigationController:(UINavigationController *)navController
|
|
|
|
willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
|
2013-03-03 14:03:56 -08:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
|
|
|
[viewController viewWillAppear:animated];
|
2011-08-25 12:09:41 -07:00
|
|
|
}
|
2010-06-24 00:22:26 -04:00
|
|
|
}
|
|
|
|
|
2013-03-03 14:03:56 -08:00
|
|
|
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
|
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
|
|
|
[viewController viewDidAppear:animated];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-11 23:48:27 -05:00
|
|
|
- (void)setTitle:(NSString *)title {
|
|
|
|
UILabel *label = [[UILabel alloc] init];
|
|
|
|
[label setFont:[UIFont boldSystemFontOfSize:16.0]];
|
|
|
|
[label setBackgroundColor:[UIColor clearColor]];
|
2013-02-14 15:36:21 -08:00
|
|
|
[label setTextColor:UIColorFromRGB(0x404040)];
|
2010-11-11 23:48:27 -05:00
|
|
|
[label setText:title];
|
2012-11-13 14:49:53 -08:00
|
|
|
[label setShadowOffset:CGSizeMake(0, -1)];
|
2013-02-14 15:36:21 -08:00
|
|
|
[label setShadowColor:UIColorFromRGB(0xFAFAFA)];
|
2010-11-11 23:48:27 -05:00
|
|
|
[label sizeToFit];
|
|
|
|
[navigationController.navigationBar.topItem setTitleView:label];
|
|
|
|
}
|
2010-06-24 00:22:26 -04:00
|
|
|
|
2012-06-14 10:19:36 -07:00
|
|
|
- (void)showOriginalStory:(NSURL *)url {
|
2010-11-13 18:32:43 -05:00
|
|
|
self.activeOriginalStoryURL = url;
|
2013-09-26 16:12:09 -07:00
|
|
|
UINavigationController *navController = [[UINavigationController alloc]
|
|
|
|
initWithRootViewController:self.originalStoryViewController];
|
|
|
|
navController.navigationBar.translucent = NO;
|
|
|
|
self.originalStoryViewNavController = navController;
|
|
|
|
|
2012-06-29 10:46:26 -07:00
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
2013-09-26 16:12:09 -07:00
|
|
|
[self.masterContainerViewController presentViewController:self.originalStoryViewNavController
|
2013-09-24 17:18:20 -07:00
|
|
|
animated:YES completion:nil];
|
2012-06-29 10:46:26 -07:00
|
|
|
} else {
|
2013-09-24 17:18:20 -07:00
|
|
|
[self.navigationController presentViewController:self.originalStoryViewNavController
|
|
|
|
animated:YES completion:nil];
|
2012-06-29 10:46:26 -07:00
|
|
|
}
|
2010-11-13 18:32:43 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)closeOriginalStory {
|
2013-06-17 11:50:13 -07:00
|
|
|
if (![self.presentedViewController isBeingDismissed]) {
|
2013-09-24 17:18:20 -07:00
|
|
|
[originalStoryViewNavController dismissViewControllerAnimated:YES completion:nil];
|
2013-03-04 17:15:50 -08:00
|
|
|
}
|
2010-11-13 18:32:43 -05:00
|
|
|
}
|
2010-06-24 00:22:26 -04:00
|
|
|
|
2012-07-10 12:34:58 -07:00
|
|
|
- (void)hideStoryDetailView {
|
|
|
|
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
|
2012-07-24 16:03:16 -07:00
|
|
|
[self.masterContainerViewController transitionFromFeedDetail];
|
2012-07-11 18:08:07 -07:00
|
|
|
} else {
|
|
|
|
[self.navigationController popViewControllerAnimated:YES];
|
2012-07-10 12:34:58 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-29 17:28:41 -07:00
|
|
|
#pragma mark - Story Traversal
|
|
|
|
|
2013-09-25 17:43:00 -07:00
|
|
|
- (NSInteger)indexOfNextUnreadStory {
|
|
|
|
NSInteger location = [self locationOfNextUnreadStory];
|
2012-11-06 13:45:15 -08:00
|
|
|
return [self indexFromLocation:location];
|
|
|
|
}
|
|
|
|
|
2013-09-25 17:43:00 -07:00
|
|
|
- (NSInteger)locationOfNextUnreadStory {
|
|
|
|
NSInteger activeLocation = [self locationOfActiveStory];
|
|
|
|
NSInteger readStatus = -1;
|
|
|
|
for (NSInteger i=activeLocation+1; i < [self.activeFeedStoryLocations count]; i++) {
|
|
|
|
NSInteger storyIndex = [[self.activeFeedStoryLocations objectAtIndex:i] intValue];
|
2012-11-06 13:45:15 -08:00
|
|
|
NSDictionary *story = [activeFeedStories objectAtIndex:storyIndex];
|
2011-07-24 21:47:58 -07:00
|
|
|
readStatus = [[story objectForKey:@"read_status"] intValue];
|
|
|
|
if (readStatus == 0) {
|
2012-11-06 13:45:15 -08:00
|
|
|
return i;
|
2011-07-24 21:47:58 -07:00
|
|
|
}
|
|
|
|
}
|
2011-08-08 17:17:32 -07:00
|
|
|
if (activeLocation > 0) {
|
2013-09-25 17:43:00 -07:00
|
|
|
for (NSInteger i=activeLocation-1; i >= 0; i--) {
|
|
|
|
NSInteger storyIndex = [[self.activeFeedStoryLocations objectAtIndex:i] intValue];
|
2012-11-06 13:45:15 -08:00
|
|
|
NSDictionary *story = [activeFeedStories objectAtIndex:storyIndex];
|
2011-08-08 17:17:32 -07:00
|
|
|
readStatus = [[story objectForKey:@"read_status"] intValue];
|
|
|
|
if (readStatus == 0) {
|
2012-11-06 13:45:15 -08:00
|
|
|
return i;
|
2011-08-08 17:17:32 -07:00
|
|
|
}
|
2011-06-15 11:21:55 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-09-25 17:43:00 -07:00
|
|
|
- (NSInteger)indexOfNextStory {
|
|
|
|
NSInteger location = [self locationOfNextStory];
|
2012-11-06 13:45:15 -08:00
|
|
|
return [self indexFromLocation:location];
|
|
|
|
}
|
|
|
|
|
2013-09-25 17:43:00 -07:00
|
|
|
- (NSInteger)locationOfNextStory {
|
|
|
|
NSInteger activeLocation = [self locationOfActiveStory];
|
|
|
|
NSInteger nextStoryLocation = activeLocation + 1;
|
2012-06-28 15:03:28 -07:00
|
|
|
if (nextStoryLocation < [self.activeFeedStoryLocations count]) {
|
2012-11-06 13:45:15 -08:00
|
|
|
return nextStoryLocation;
|
2012-06-28 15:03:28 -07:00
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-09-25 17:43:00 -07:00
|
|
|
- (NSInteger)indexOfActiveStory {
|
|
|
|
for (NSInteger i=0; i < self.storyCount; i++) {
|
2011-06-15 11:21:55 -04:00
|
|
|
NSDictionary *story = [activeFeedStories objectAtIndex:i];
|
|
|
|
if ([activeStory objectForKey:@"id"] == [story objectForKey:@"id"]) {
|
|
|
|
return i;
|
2011-06-14 10:35:33 -04:00
|
|
|
}
|
|
|
|
}
|
2011-06-15 11:21:55 -04:00
|
|
|
return -1;
|
2011-06-14 10:35:33 -04:00
|
|
|
}
|
|
|
|
|
2013-09-25 17:43:00 -07:00
|
|
|
- (NSInteger)indexOfStoryId:(id)storyId {
|
2012-11-06 13:45:15 -08:00
|
|
|
for (int i=0; i < self.storyCount; i++) {
|
|
|
|
NSDictionary *story = [activeFeedStories objectAtIndex:i];
|
|
|
|
if ([story objectForKey:@"id"] == storyId) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-09-25 17:43:00 -07:00
|
|
|
- (NSInteger)locationOfStoryId:(id)storyId {
|
2012-11-06 13:45:15 -08:00
|
|
|
for (int i=0; i < [activeFeedStoryLocations count]; i++) {
|
|
|
|
if ([activeFeedStoryLocationIds objectAtIndex:i] == storyId) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-09-25 17:43:00 -07:00
|
|
|
- (NSInteger)locationOfActiveStory {
|
2011-08-08 09:58:15 -07:00
|
|
|
for (int i=0; i < [activeFeedStoryLocations count]; i++) {
|
2012-11-28 15:46:11 -08:00
|
|
|
if ([[activeFeedStoryLocationIds objectAtIndex:i]
|
|
|
|
isEqualToString:[self.activeStory objectForKey:@"id"]]) {
|
2011-08-08 09:58:15 -07:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-09-25 17:43:00 -07:00
|
|
|
- (NSInteger)indexFromLocation:(NSInteger)location {
|
2012-11-06 13:45:15 -08:00
|
|
|
if (location == -1) return -1;
|
|
|
|
return [[activeFeedStoryLocations objectAtIndex:location] intValue];
|
|
|
|
}
|
|
|
|
|
2011-08-22 18:25:33 -07:00
|
|
|
- (void)pushReadStory:(id)storyId {
|
|
|
|
if ([self.readStories lastObject] != storyId) {
|
|
|
|
[self.readStories addObject:storyId];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id)popReadStory {
|
|
|
|
if (storyCount == 0) {
|
|
|
|
return nil;
|
|
|
|
} else {
|
|
|
|
[self.readStories removeLastObject];
|
|
|
|
id lastStory = [self.readStories lastObject];
|
|
|
|
return lastStory;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-21 18:35:06 -07:00
|
|
|
- (NSString *)activeOrder {
|
|
|
|
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
|
|
|
|
NSString *orderPrefDefault = [userPreferences stringForKey:@"default_order"];
|
|
|
|
NSString *orderPref = [userPreferences stringForKey:[self orderKey]];
|
|
|
|
|
|
|
|
if (orderPref) {
|
|
|
|
return orderPref;
|
|
|
|
} else if (orderPrefDefault) {
|
|
|
|
return orderPrefDefault;
|
|
|
|
} else {
|
|
|
|
return @"newest";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *)activeReadFilter {
|
|
|
|
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
|
|
|
|
NSString *readFilterFeedPrefDefault = [userPreferences stringForKey:@"default_feed_read_filter"];
|
|
|
|
NSString *readFilterFolderPrefDefault = [userPreferences stringForKey:@"default_folder_read_filter"];
|
|
|
|
NSString *readFilterPref = [userPreferences stringForKey:[self readFilterKey]];
|
|
|
|
|
|
|
|
if (readFilterPref) {
|
|
|
|
return readFilterPref;
|
|
|
|
} else if (self.isRiverView || self.isSocialRiverView) {
|
|
|
|
if (readFilterFolderPrefDefault) {
|
|
|
|
return readFilterFolderPrefDefault;
|
|
|
|
} else {
|
|
|
|
return @"unread";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (readFilterFeedPrefDefault) {
|
|
|
|
return readFilterFeedPrefDefault;
|
|
|
|
} else {
|
|
|
|
return @"all";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-29 17:28:41 -07:00
|
|
|
#pragma mark - Unread Counts
|
|
|
|
|
|
|
|
- (void)populateDictUnreadCounts {
|
|
|
|
self.dictUnreadCounts = [NSMutableDictionary dictionary];
|
|
|
|
|
|
|
|
[self.database inDatabase:^(FMDatabase *db) {
|
|
|
|
FMResultSet *cursor = [db executeQuery:@"SELECT * FROM unread_counts"];
|
|
|
|
|
|
|
|
while ([cursor next]) {
|
|
|
|
NSDictionary *unreadCounts = [cursor resultDictionary];
|
|
|
|
[self.dictUnreadCounts setObject:unreadCounts forKey:[unreadCounts objectForKey:@"feed_id"]];
|
|
|
|
}
|
|
|
|
}];
|
|
|
|
}
|
2013-06-21 18:35:06 -07:00
|
|
|
|
2013-09-25 17:43:00 -07:00
|
|
|
- (NSInteger)unreadCount {
|
2012-08-13 17:07:26 -07:00
|
|
|
if (self.isRiverView || self.isSocialRiverView) {
|
2011-10-31 10:10:38 -07:00
|
|
|
return [self unreadCountForFolder:nil];
|
|
|
|
} else {
|
|
|
|
return [self unreadCountForFeed:nil];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-25 17:43:00 -07:00
|
|
|
- (NSInteger)allUnreadCount {
|
|
|
|
NSInteger total = 0;
|
2012-07-29 22:14:08 -07:00
|
|
|
for (id key in self.dictSocialFeeds) {
|
|
|
|
NSDictionary *feed = [self.dictSocialFeeds objectForKey:key];
|
2013-09-25 17:43:00 -07:00
|
|
|
total += [[feed objectForKey:@"ps"] integerValue];
|
|
|
|
total += [[feed objectForKey:@"nt"] integerValue];
|
2012-07-29 22:14:08 -07:00
|
|
|
NSLog(@"feed title and number is %@ %i", [feed objectForKey:@"feed_title"], ([[feed objectForKey:@"ps"] intValue] + [[feed objectForKey:@"nt"] intValue]));
|
2013-09-25 17:43:00 -07:00
|
|
|
NSLog(@"total is %ld", (long)total);
|
2012-07-29 22:14:08 -07:00
|
|
|
}
|
|
|
|
|
2013-06-29 17:28:41 -07:00
|
|
|
for (id key in self.dictUnreadCounts) {
|
|
|
|
NSDictionary *feed = [self.dictUnreadCounts objectForKey:key];
|
2012-07-29 22:14:08 -07:00
|
|
|
total += [[feed objectForKey:@"ps"] intValue];
|
|
|
|
total += [[feed objectForKey:@"nt"] intValue];
|
2013-06-29 17:28:41 -07:00
|
|
|
// NSLog(@"feed title and number is %@ %i", [feed objectForKey:@"feed_title"], ([[feed objectForKey:@"ps"] intValue] + [[feed objectForKey:@"nt"] intValue]));
|
|
|
|
// NSLog(@"total is %i", total);
|
2012-07-29 22:14:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return total;
|
|
|
|
}
|
|
|
|
|
2013-09-25 17:43:00 -07:00
|
|
|
- (NSInteger)unreadCountForFeed:(NSString *)feedId {
|
|
|
|
NSInteger total = 0;
|
2011-10-31 10:10:38 -07:00
|
|
|
NSDictionary *feed;
|
|
|
|
|
|
|
|
if (feedId) {
|
|
|
|
NSString *feedIdStr = [NSString stringWithFormat:@"%@",feedId];
|
2012-10-07 15:47:21 -04:00
|
|
|
if ([feedIdStr containsString:@"social:"]) {
|
2012-08-01 12:41:02 -07:00
|
|
|
feed = [self.dictSocialFeeds objectForKey:feedIdStr];
|
|
|
|
} else {
|
2013-06-29 17:28:41 -07:00
|
|
|
feed = [self.dictUnreadCounts objectForKey:feedIdStr];
|
2012-08-01 12:41:02 -07:00
|
|
|
}
|
|
|
|
|
2011-10-31 10:10:38 -07:00
|
|
|
} else {
|
2013-07-16 19:09:46 -07:00
|
|
|
NSString *feedIdStr = [NSString stringWithFormat:@"%@", [self.activeFeed objectForKey:@"id"]];
|
|
|
|
feed = [self.dictUnreadCounts objectForKey:feedIdStr];
|
2011-10-31 10:10:38 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
total += [[feed objectForKey:@"ps"] intValue];
|
2011-08-09 17:58:43 -07:00
|
|
|
if ([self selectedIntelligence] <= 0) {
|
2011-10-31 10:10:38 -07:00
|
|
|
total += [[feed objectForKey:@"nt"] intValue];
|
2011-08-09 17:58:43 -07:00
|
|
|
}
|
|
|
|
if ([self selectedIntelligence] <= -1) {
|
2011-10-31 10:10:38 -07:00
|
|
|
total += [[feed objectForKey:@"ng"] intValue];
|
2011-08-09 17:58:43 -07:00
|
|
|
}
|
2011-10-31 10:10:38 -07:00
|
|
|
|
2011-08-09 17:58:43 -07:00
|
|
|
return total;
|
|
|
|
}
|
|
|
|
|
2013-09-25 17:43:00 -07:00
|
|
|
- (NSInteger)unreadCountForFolder:(NSString *)folderName {
|
|
|
|
NSInteger total = 0;
|
2011-10-31 10:10:38 -07:00
|
|
|
NSArray *folder;
|
|
|
|
|
2013-02-06 15:15:43 -08:00
|
|
|
if ([folderName isEqual:@"river_blurblogs"] ||
|
|
|
|
(!folderName && [self.activeFolder isEqual:@"river_blurblogs"])) {
|
2012-08-13 17:07:26 -07:00
|
|
|
for (id feedId in self.dictSocialFeeds) {
|
|
|
|
total += [self unreadCountForFeed:feedId];
|
|
|
|
}
|
2013-02-06 15:15:43 -08:00
|
|
|
} else if ([folderName isEqual:@"river_global"] ||
|
|
|
|
(!folderName && [self.activeFolder isEqual:@"river_global"])) {
|
2012-12-07 15:17:22 -08:00
|
|
|
total = 0;
|
2013-02-06 15:15:43 -08:00
|
|
|
} else if ([folderName isEqual:@"everything"] ||
|
|
|
|
(!folderName && [self.activeFolder isEqual:@"everything"])) {
|
2013-06-29 17:28:41 -07:00
|
|
|
for (id feedId in self.dictUnreadCounts) {
|
2011-12-01 09:01:18 -08:00
|
|
|
total += [self unreadCountForFeed:feedId];
|
|
|
|
}
|
2011-10-31 10:10:38 -07:00
|
|
|
} else {
|
2011-12-01 09:01:18 -08:00
|
|
|
if (!folderName) {
|
|
|
|
folder = [self.dictFolders objectForKey:self.activeFolder];
|
|
|
|
} else {
|
|
|
|
folder = [self.dictFolders objectForKey:folderName];
|
|
|
|
}
|
2011-10-31 10:10:38 -07:00
|
|
|
|
2011-12-01 09:01:18 -08:00
|
|
|
for (id feedId in folder) {
|
|
|
|
total += [self unreadCountForFeed:feedId];
|
|
|
|
}
|
2011-10-31 10:10:38 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return total;
|
2011-07-26 08:37:10 -07:00
|
|
|
}
|
|
|
|
|
2012-10-07 15:47:21 -04:00
|
|
|
|
2012-10-12 15:33:40 -04:00
|
|
|
- (UnreadCounts *)splitUnreadCountForFeed:(NSString *)feedId {
|
|
|
|
UnreadCounts *counts = [UnreadCounts alloc];
|
2013-06-29 17:28:41 -07:00
|
|
|
NSDictionary *feedCounts;
|
2012-10-07 15:47:21 -04:00
|
|
|
|
2013-06-29 17:28:41 -07:00
|
|
|
if (!feedId) {
|
|
|
|
feedId = [self.activeFeed objectForKey:@"id"];
|
2012-10-07 15:47:21 -04:00
|
|
|
}
|
2013-06-29 17:28:41 -07:00
|
|
|
NSString *feedIdStr = [NSString stringWithFormat:@"%@", feedId];
|
|
|
|
feedCounts = [self.dictUnreadCounts objectForKey:feedIdStr];
|
2012-10-07 15:47:21 -04:00
|
|
|
|
2013-06-29 17:28:41 -07:00
|
|
|
counts.ps += [[feedCounts objectForKey:@"ps"] intValue];
|
|
|
|
counts.nt += [[feedCounts objectForKey:@"nt"] intValue];
|
|
|
|
counts.ng += [[feedCounts objectForKey:@"ng"] intValue];
|
2012-10-07 15:47:21 -04:00
|
|
|
|
|
|
|
return counts;
|
|
|
|
}
|
|
|
|
|
2012-10-12 15:33:40 -04:00
|
|
|
- (UnreadCounts *)splitUnreadCountForFolder:(NSString *)folderName {
|
|
|
|
UnreadCounts *counts = [UnreadCounts alloc];
|
2012-10-07 15:47:21 -04:00
|
|
|
NSArray *folder;
|
|
|
|
|
2012-10-14 17:30:03 -07:00
|
|
|
if ([[self.folderCountCache objectForKey:folderName] boolValue]) {
|
|
|
|
counts.ps = [[self.folderCountCache objectForKey:[NSString stringWithFormat:@"%@-ps", folderName]] intValue];
|
|
|
|
counts.nt = [[self.folderCountCache objectForKey:[NSString stringWithFormat:@"%@-nt", folderName]] intValue];
|
|
|
|
counts.ng = [[self.folderCountCache objectForKey:[NSString stringWithFormat:@"%@-ng", folderName]] intValue];
|
|
|
|
return counts;
|
|
|
|
}
|
|
|
|
|
2013-02-06 15:15:43 -08:00
|
|
|
if ([folderName isEqual:@"river_blurblogs"] ||
|
|
|
|
(!folderName && [self.activeFolder isEqual:@"river_blurblogs"])) {
|
2012-10-07 15:47:21 -04:00
|
|
|
for (id feedId in self.dictSocialFeeds) {
|
|
|
|
[counts addCounts:[self splitUnreadCountForFeed:feedId]];
|
|
|
|
}
|
2013-02-06 15:15:43 -08:00
|
|
|
} else if ([folderName isEqual:@"river_global"] ||
|
|
|
|
(!folderName && [self.activeFolder isEqual:@"river_global"])) {
|
2012-12-07 15:17:22 -08:00
|
|
|
// Nothing for global
|
2013-02-06 15:15:43 -08:00
|
|
|
} else if ([folderName isEqual:@"everything"] ||
|
|
|
|
(!folderName && [self.activeFolder isEqual:@"everything"])) {
|
2013-02-21 12:19:15 -08:00
|
|
|
for (NSArray *folder in [self.dictFolders allValues]) {
|
|
|
|
for (id feedId in folder) {
|
|
|
|
[counts addCounts:[self splitUnreadCountForFeed:feedId]];
|
|
|
|
}
|
2012-10-07 15:47:21 -04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!folderName) {
|
|
|
|
folder = [self.dictFolders objectForKey:self.activeFolder];
|
|
|
|
} else {
|
|
|
|
folder = [self.dictFolders objectForKey:folderName];
|
|
|
|
}
|
|
|
|
|
|
|
|
for (id feedId in folder) {
|
|
|
|
[counts addCounts:[self splitUnreadCountForFeed:feedId]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-14 17:30:03 -07:00
|
|
|
if (!self.folderCountCache) {
|
|
|
|
self.folderCountCache = [[NSMutableDictionary alloc] init];
|
|
|
|
}
|
|
|
|
[self.folderCountCache setObject:[NSNumber numberWithBool:YES] forKey:folderName];
|
|
|
|
[self.folderCountCache setObject:[NSNumber numberWithInt:counts.ps] forKey:[NSString stringWithFormat:@"%@-ps", folderName]];
|
|
|
|
[self.folderCountCache setObject:[NSNumber numberWithInt:counts.nt] forKey:[NSString stringWithFormat:@"%@-nt", folderName]];
|
|
|
|
[self.folderCountCache setObject:[NSNumber numberWithInt:counts.ng] forKey:[NSString stringWithFormat:@"%@-ng", folderName]];
|
|
|
|
|
2012-10-07 15:47:21 -04:00
|
|
|
return counts;
|
|
|
|
}
|
|
|
|
|
2013-06-29 17:28:41 -07:00
|
|
|
#pragma mark - Story Management
|
|
|
|
|
2011-07-24 16:52:24 -07:00
|
|
|
- (void)addStories:(NSArray *)stories {
|
2011-07-20 22:21:11 -07:00
|
|
|
self.activeFeedStories = [self.activeFeedStories arrayByAddingObjectsFromArray:stories];
|
2011-07-24 16:52:24 -07:00
|
|
|
self.storyCount = [self.activeFeedStories count];
|
2011-07-29 21:27:37 -07:00
|
|
|
[self calculateStoryLocations];
|
2012-11-26 09:54:20 -08:00
|
|
|
self.storyLocationsCount = [self.activeFeedStoryLocations count];
|
2011-07-24 16:52:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setStories:(NSArray *)activeFeedStoriesValue {
|
|
|
|
self.activeFeedStories = activeFeedStoriesValue;
|
|
|
|
self.storyCount = [self.activeFeedStories count];
|
2011-11-03 18:08:24 -07:00
|
|
|
self.recentlyReadFeeds = [NSMutableSet set];
|
2011-07-29 21:27:37 -07:00
|
|
|
[self calculateStoryLocations];
|
2012-11-26 09:54:20 -08:00
|
|
|
self.storyLocationsCount = [self.activeFeedStoryLocations count];
|
2011-07-20 22:21:11 -07:00
|
|
|
}
|
|
|
|
|
2012-06-22 18:01:08 -07:00
|
|
|
- (void)setFeedUserProfiles:(NSArray *)activeFeedUserProfilesValue{
|
|
|
|
self.activeFeedUserProfiles = activeFeedUserProfilesValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)addFeedUserProfiles:(NSArray *)activeFeedUserProfilesValue {
|
|
|
|
self.activeFeedUserProfiles = [self.activeFeedUserProfiles arrayByAddingObjectsFromArray:activeFeedUserProfilesValue];
|
|
|
|
}
|
|
|
|
|
2011-07-24 20:34:54 -07:00
|
|
|
- (void)markActiveStoryRead {
|
2013-09-25 17:43:00 -07:00
|
|
|
NSInteger activeLocation = [self locationOfActiveStory];
|
2011-08-08 09:58:15 -07:00
|
|
|
if (activeLocation == -1) {
|
|
|
|
return;
|
|
|
|
}
|
2012-07-29 20:55:11 -07:00
|
|
|
|
|
|
|
// changes the story layout in story feed detail
|
|
|
|
[self.feedDetailViewController changeActiveStoryTitleCellLayout];
|
2012-08-07 11:27:00 -07:00
|
|
|
|
2013-09-25 17:43:00 -07:00
|
|
|
NSInteger activeIndex = [[activeFeedStoryLocations objectAtIndex:activeLocation] intValue];
|
2012-06-29 13:48:00 -07:00
|
|
|
|
2012-06-29 12:54:52 -07:00
|
|
|
NSDictionary *feed;
|
2012-08-07 11:27:00 -07:00
|
|
|
NSDictionary *friendFeed;
|
2012-07-29 13:24:03 -07:00
|
|
|
id feedId;
|
2012-06-29 13:48:00 -07:00
|
|
|
NSString *feedIdStr;
|
2012-08-08 12:02:54 -07:00
|
|
|
NSDictionary *story = [activeFeedStories objectAtIndex:activeIndex];
|
2012-08-10 18:10:07 -07:00
|
|
|
NSMutableArray *otherFriendShares = [[self.activeStory objectForKey:@"shared_by_friends"] mutableCopy];
|
|
|
|
NSMutableArray *otherFriendComments = [[self.activeStory objectForKey:@"commented_by_friends"] mutableCopy];
|
2012-06-29 12:54:52 -07:00
|
|
|
|
2012-08-10 18:10:07 -07:00
|
|
|
if (self.isSocialView) {
|
2012-06-29 13:48:00 -07:00
|
|
|
feedId = [self.activeStory objectForKey:@"social_user_id"];
|
|
|
|
feedIdStr = [NSString stringWithFormat:@"social:%@",feedId];
|
|
|
|
feed = [self.dictSocialFeeds objectForKey:feedIdStr];
|
|
|
|
|
2012-08-10 18:10:07 -07:00
|
|
|
[otherFriendShares removeObject:feedId];
|
|
|
|
NSLog(@"otherFriendFeeds is %@", otherFriendShares);
|
|
|
|
[otherFriendComments removeObject:feedId];
|
|
|
|
NSLog(@"otherFriendFeeds is %@", otherFriendComments);
|
|
|
|
|
|
|
|
// make sure we set the active feed
|
|
|
|
self.activeFeed = feed;
|
2013-07-24 17:18:46 -07:00
|
|
|
} else if (self.isSocialRiverView && [[self.activeStory objectForKey:@"friend_user_ids"] count]) {
|
|
|
|
feedId = [[self.activeStory objectForKey:@"friend_user_ids"] objectAtIndex:0];
|
|
|
|
feedIdStr = [NSString stringWithFormat:@"social:%@",feedId];
|
|
|
|
feed = [self.dictSocialFeeds objectForKey:feedIdStr];
|
|
|
|
|
|
|
|
[otherFriendShares removeObject:feedId];
|
|
|
|
NSLog(@"otherFriendFeeds is %@", otherFriendShares);
|
|
|
|
[otherFriendComments removeObject:feedId];
|
|
|
|
NSLog(@"otherFriendFeeds is %@", otherFriendComments);
|
|
|
|
|
|
|
|
// make sure we set the active feed
|
|
|
|
self.activeFeed = feed;
|
2012-06-29 12:54:52 -07:00
|
|
|
} else {
|
2012-06-29 13:48:00 -07:00
|
|
|
feedId = [self.activeStory objectForKey:@"story_feed_id"];
|
|
|
|
feedIdStr = [NSString stringWithFormat:@"%@",feedId];
|
2012-06-29 12:54:52 -07:00
|
|
|
feed = [self.dictFeeds objectForKey:feedIdStr];
|
2012-08-08 12:02:54 -07:00
|
|
|
|
|
|
|
// make sure we set the active feed
|
|
|
|
self.activeFeed = feed;
|
2011-11-15 09:25:50 -08:00
|
|
|
}
|
2012-06-29 13:48:00 -07:00
|
|
|
|
2012-08-07 11:27:00 -07:00
|
|
|
// decrement all other friend feeds if they have the same story
|
2012-08-08 12:02:54 -07:00
|
|
|
if (self.isSocialView || self.isSocialRiverView) {
|
2012-08-10 18:10:07 -07:00
|
|
|
for (int i = 0; i < otherFriendShares.count; i++) {
|
|
|
|
feedIdStr = [NSString stringWithFormat:@"social:%@",
|
|
|
|
[otherFriendShares objectAtIndex:i]];
|
|
|
|
friendFeed = [self.dictSocialFeeds objectForKey:feedIdStr];
|
|
|
|
[self markStoryRead:story feed:friendFeed];
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < otherFriendComments.count; i++) {
|
2012-06-29 13:48:00 -07:00
|
|
|
feedIdStr = [NSString stringWithFormat:@"social:%@",
|
2012-08-10 18:10:07 -07:00
|
|
|
[otherFriendComments objectAtIndex:i]];
|
2012-08-07 11:27:00 -07:00
|
|
|
friendFeed = [self.dictSocialFeeds objectForKey:feedIdStr];
|
|
|
|
[self markStoryRead:story feed:friendFeed];
|
2012-06-29 13:48:00 -07:00
|
|
|
}
|
|
|
|
}
|
2012-06-29 17:37:49 -07:00
|
|
|
|
2013-07-19 15:41:43 -07:00
|
|
|
[self.recentlyReadStories setObject:[NSNumber numberWithBool:YES]
|
|
|
|
forKey:[self.activeStory objectForKey:@"story_hash"]];
|
2013-09-25 17:43:00 -07:00
|
|
|
[self.recentlyReadStoryLocations addObject:[NSNumber numberWithInteger:activeLocation]];
|
2012-08-07 11:27:00 -07:00
|
|
|
[self markStoryRead:story feed:feed];
|
2012-10-16 17:24:01 -07:00
|
|
|
self.activeStory = [self.activeFeedStories objectAtIndex:activeIndex];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)markActiveStoryUnread {
|
2013-09-25 17:43:00 -07:00
|
|
|
NSInteger activeLocation = [self locationOfActiveStory];
|
2012-10-16 17:24:01 -07:00
|
|
|
if (activeLocation == -1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// changes the story layout in story feed detail
|
|
|
|
[self.feedDetailViewController changeActiveStoryTitleCellLayout];
|
|
|
|
|
2013-09-25 17:43:00 -07:00
|
|
|
NSInteger activeIndex = [[activeFeedStoryLocations objectAtIndex:activeLocation] intValue];
|
2012-10-16 17:24:01 -07:00
|
|
|
|
|
|
|
NSDictionary *feed;
|
|
|
|
NSDictionary *friendFeed;
|
|
|
|
id feedId;
|
|
|
|
NSString *feedIdStr;
|
|
|
|
NSDictionary *story = [activeFeedStories objectAtIndex:activeIndex];
|
|
|
|
NSMutableArray *otherFriendShares = [[self.activeStory objectForKey:@"shared_by_friends"] mutableCopy];
|
|
|
|
NSMutableArray *otherFriendComments = [[self.activeStory objectForKey:@"commented_by_friends"] mutableCopy];
|
|
|
|
|
|
|
|
if (self.isSocialView) {
|
|
|
|
feedId = [self.activeStory objectForKey:@"social_user_id"];
|
|
|
|
feedIdStr = [NSString stringWithFormat:@"social:%@",feedId];
|
|
|
|
feed = [self.dictSocialFeeds objectForKey:feedIdStr];
|
|
|
|
|
|
|
|
[otherFriendShares removeObject:feedId];
|
|
|
|
NSLog(@"otherFriendFeeds is %@", otherFriendShares);
|
|
|
|
[otherFriendComments removeObject:feedId];
|
|
|
|
NSLog(@"otherFriendFeeds is %@", otherFriendComments);
|
|
|
|
|
|
|
|
// make sure we set the active feed
|
|
|
|
self.activeFeed = feed;
|
|
|
|
} else if (self.isSocialRiverView) {
|
|
|
|
feedId = [[self.activeStory objectForKey:@"friend_user_ids"] objectAtIndex:0];
|
|
|
|
feedIdStr = [NSString stringWithFormat:@"social:%@",feedId];
|
|
|
|
feed = [self.dictSocialFeeds objectForKey:feedIdStr];
|
|
|
|
|
|
|
|
[otherFriendShares removeObject:feedId];
|
|
|
|
NSLog(@"otherFriendFeeds is %@", otherFriendShares);
|
|
|
|
[otherFriendComments removeObject:feedId];
|
|
|
|
NSLog(@"otherFriendFeeds is %@", otherFriendComments);
|
|
|
|
|
|
|
|
// make sure we set the active feed
|
|
|
|
self.activeFeed = feed;
|
|
|
|
} else {
|
|
|
|
feedId = [self.activeStory objectForKey:@"story_feed_id"];
|
|
|
|
feedIdStr = [NSString stringWithFormat:@"%@",feedId];
|
|
|
|
feed = [self.dictFeeds objectForKey:feedIdStr];
|
|
|
|
|
|
|
|
// make sure we set the active feed
|
|
|
|
self.activeFeed = feed;
|
|
|
|
}
|
|
|
|
|
|
|
|
// decrement all other friend feeds if they have the same story
|
|
|
|
if (self.isSocialView || self.isSocialRiverView) {
|
|
|
|
for (int i = 0; i < otherFriendShares.count; i++) {
|
|
|
|
feedIdStr = [NSString stringWithFormat:@"social:%@",
|
|
|
|
[otherFriendShares objectAtIndex:i]];
|
|
|
|
friendFeed = [self.dictSocialFeeds objectForKey:feedIdStr];
|
|
|
|
[self markStoryUnread:story feed:friendFeed];
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < otherFriendComments.count; i++) {
|
|
|
|
feedIdStr = [NSString stringWithFormat:@"social:%@",
|
|
|
|
[otherFriendComments objectAtIndex:i]];
|
|
|
|
friendFeed = [self.dictSocialFeeds objectForKey:feedIdStr];
|
|
|
|
[self markStoryUnread:story feed:friendFeed];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-19 15:41:43 -07:00
|
|
|
[self.recentlyReadStories removeObjectForKey:[self.activeStory objectForKey:@"story_hash"]];
|
2013-09-25 17:43:00 -07:00
|
|
|
[self.recentlyReadStoryLocations removeObject:[NSNumber numberWithInteger:activeLocation]];
|
2012-10-16 17:24:01 -07:00
|
|
|
[self markStoryUnread:story feed:feed];
|
|
|
|
|
|
|
|
self.activeStory = [self.activeFeedStories objectAtIndex:activeIndex];
|
2011-11-10 18:28:22 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSDictionary *)markVisibleStoriesRead {
|
|
|
|
NSMutableDictionary *feedsStories = [NSMutableDictionary dictionary];
|
|
|
|
for (NSDictionary *story in self.activeFeedStories) {
|
|
|
|
if ([[story objectForKey:@"read_status"] intValue] != 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
NSString *feedIdStr = [NSString stringWithFormat:@"%@",[story objectForKey:@"story_feed_id"]];
|
|
|
|
NSDictionary *feed = [self.dictFeeds objectForKey:feedIdStr];
|
|
|
|
if (![feedsStories objectForKey:feedIdStr]) {
|
|
|
|
[feedsStories setObject:[NSMutableArray array] forKey:feedIdStr];
|
|
|
|
}
|
|
|
|
NSMutableArray *stories = [feedsStories objectForKey:feedIdStr];
|
2013-08-06 18:08:55 -07:00
|
|
|
[stories addObject:[story objectForKey:@"story_hash"]];
|
2011-11-10 18:28:22 -08:00
|
|
|
[self markStoryRead:story feed:feed];
|
|
|
|
}
|
|
|
|
return feedsStories;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)markStoryRead:(NSString *)storyId feedId:(id)feedId {
|
|
|
|
NSString *feedIdStr = [NSString stringWithFormat:@"%@",feedId];
|
|
|
|
NSDictionary *feed = [self.dictFeeds objectForKey:feedIdStr];
|
|
|
|
NSDictionary *story = nil;
|
|
|
|
for (NSDictionary *s in self.activeFeedStories) {
|
2013-08-06 18:08:55 -07:00
|
|
|
if ([[s objectForKey:@"story_hash"] isEqualToString:storyId]) {
|
2011-11-10 18:28:22 -08:00
|
|
|
story = s;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
[self markStoryRead:story feed:feed];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)markStoryRead:(NSDictionary *)story feed:(NSDictionary *)feed {
|
|
|
|
NSString *feedIdStr = [NSString stringWithFormat:@"%@", [feed objectForKey:@"id"]];
|
2013-07-24 17:18:46 -07:00
|
|
|
if (!feed) {
|
|
|
|
feedIdStr = @"0";
|
|
|
|
}
|
|
|
|
|
2012-07-27 16:48:30 -07:00
|
|
|
NSMutableDictionary *newStory = [story mutableCopy];
|
2012-08-01 21:40:19 -07:00
|
|
|
[newStory setValue:[NSNumber numberWithInt:1] forKey:@"read_status"];
|
2012-08-06 15:46:05 -07:00
|
|
|
|
|
|
|
// make the story as read in self.activeFeedStories
|
|
|
|
NSString *newStoryIdStr = [NSString stringWithFormat:@"%@", [newStory valueForKey:@"id"]];
|
|
|
|
NSMutableArray *newActiveFeedStories = [self.activeFeedStories mutableCopy];
|
|
|
|
for (int i = 0; i < [newActiveFeedStories count]; i++) {
|
|
|
|
NSMutableArray *thisStory = [[newActiveFeedStories objectAtIndex:i] mutableCopy];
|
|
|
|
NSString *thisStoryIdStr = [NSString stringWithFormat:@"%@", [thisStory valueForKey:@"id"]];
|
|
|
|
if ([newStoryIdStr isEqualToString:thisStoryIdStr]) {
|
|
|
|
[newActiveFeedStories replaceObjectAtIndex:i withObject:newStory];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.activeFeedStories = newActiveFeedStories;
|
2012-10-16 17:24:01 -07:00
|
|
|
|
2013-07-24 17:18:46 -07:00
|
|
|
// If not a feed, then don't bother updating local feed.
|
|
|
|
if (!feed) return;
|
|
|
|
|
2011-11-09 09:51:42 -08:00
|
|
|
self.visibleUnreadCount -= 1;
|
2012-07-27 16:48:30 -07:00
|
|
|
if (![self.recentlyReadFeeds containsObject:[newStory objectForKey:@"story_feed_id"]]) {
|
|
|
|
[self.recentlyReadFeeds addObject:[newStory objectForKey:@"story_feed_id"]];
|
2011-11-03 18:08:24 -07:00
|
|
|
}
|
2012-07-27 18:42:42 -07:00
|
|
|
|
2013-06-29 17:28:41 -07:00
|
|
|
NSDictionary *unreadCounts = [self.dictUnreadCounts objectForKey:feedIdStr];
|
|
|
|
NSMutableDictionary *newUnreadCounts = [unreadCounts mutableCopy];
|
2013-09-25 17:43:00 -07:00
|
|
|
NSInteger score = [NewsBlurAppDelegate computeStoryScore:[story objectForKey:@"intelligence"]];
|
2011-07-24 22:14:50 -07:00
|
|
|
if (score > 0) {
|
2013-06-29 17:28:41 -07:00
|
|
|
int unreads = MAX(0, [[newUnreadCounts objectForKey:@"ps"] intValue] - 1);
|
|
|
|
[newUnreadCounts setValue:[NSNumber numberWithInt:unreads] forKey:@"ps"];
|
2011-07-24 22:14:50 -07:00
|
|
|
} else if (score == 0) {
|
2013-06-29 17:28:41 -07:00
|
|
|
int unreads = MAX(0, [[newUnreadCounts objectForKey:@"nt"] intValue] - 1);
|
|
|
|
[newUnreadCounts setValue:[NSNumber numberWithInt:unreads] forKey:@"nt"];
|
2011-07-24 22:14:50 -07:00
|
|
|
} else if (score < 0) {
|
2013-06-29 17:28:41 -07:00
|
|
|
int unreads = MAX(0, [[newUnreadCounts objectForKey:@"ng"] intValue] - 1);
|
|
|
|
[newUnreadCounts setValue:[NSNumber numberWithInt:unreads] forKey:@"ng"];
|
2012-08-01 12:41:02 -07:00
|
|
|
}
|
2013-06-29 17:28:41 -07:00
|
|
|
[self.dictUnreadCounts setObject:newUnreadCounts forKey:feedIdStr];
|
2012-08-01 12:41:02 -07:00
|
|
|
|
2013-07-16 19:09:46 -07:00
|
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
|
|
|
|
(unsigned long)NULL), ^(void) {
|
|
|
|
[self.database inTransaction:^(FMDatabase *db, BOOL *rollback) {
|
|
|
|
NSString *storyHash = [newStory objectForKey:@"story_hash"];
|
|
|
|
[db executeUpdate:@"UPDATE stories SET story_json = ? WHERE story_hash = ?",
|
|
|
|
[newStory JSONRepresentation],
|
|
|
|
storyHash];
|
|
|
|
[db executeUpdate:@"DELETE FROM unread_hashes WHERE story_hash = ?",
|
|
|
|
storyHash];
|
|
|
|
[db executeUpdate:@"UPDATE unread_counts SET ps = ?, nt = ?, ng = ? WHERE feed_id = ?",
|
|
|
|
[newUnreadCounts objectForKey:@"ps"],
|
|
|
|
[newUnreadCounts objectForKey:@"nt"],
|
|
|
|
[newUnreadCounts objectForKey:@"ng"],
|
|
|
|
feedIdStr];
|
|
|
|
}];
|
|
|
|
});
|
2011-07-24 20:34:54 -07:00
|
|
|
}
|
|
|
|
|
2012-10-16 17:24:01 -07:00
|
|
|
|
|
|
|
- (void)markStoryUnread:(NSString *)storyId feedId:(id)feedId {
|
|
|
|
NSString *feedIdStr = [NSString stringWithFormat:@"%@",feedId];
|
|
|
|
NSDictionary *feed = [self.dictFeeds objectForKey:feedIdStr];
|
|
|
|
NSDictionary *story = nil;
|
|
|
|
for (NSDictionary *s in self.activeFeedStories) {
|
2013-08-06 18:08:55 -07:00
|
|
|
if ([[s objectForKey:@"story_hash"] isEqualToString:storyId]) {
|
2012-10-16 17:24:01 -07:00
|
|
|
story = s;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
[self markStoryUnread:story feed:feed];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)markStoryUnread:(NSDictionary *)story feed:(NSDictionary *)feed {
|
|
|
|
NSString *feedIdStr = [NSString stringWithFormat:@"%@", [feed objectForKey:@"id"]];
|
|
|
|
|
|
|
|
NSMutableDictionary *newStory = [story mutableCopy];
|
|
|
|
[newStory setValue:[NSNumber numberWithInt:0] forKey:@"read_status"];
|
|
|
|
|
|
|
|
// make the story as read in self.activeFeedStories
|
|
|
|
NSString *newStoryIdStr = [NSString stringWithFormat:@"%@", [newStory valueForKey:@"id"]];
|
|
|
|
NSMutableArray *newActiveFeedStories = [self.activeFeedStories mutableCopy];
|
|
|
|
for (int i = 0; i < [newActiveFeedStories count]; i++) {
|
|
|
|
NSMutableArray *thisStory = [[newActiveFeedStories objectAtIndex:i] mutableCopy];
|
|
|
|
NSString *thisStoryIdStr = [NSString stringWithFormat:@"%@", [thisStory valueForKey:@"id"]];
|
|
|
|
if ([newStoryIdStr isEqualToString:thisStoryIdStr]) {
|
|
|
|
[newActiveFeedStories replaceObjectAtIndex:i withObject:newStory];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.activeFeedStories = newActiveFeedStories;
|
|
|
|
|
|
|
|
self.visibleUnreadCount += 1;
|
|
|
|
// if ([self.recentlyReadFeeds containsObject:[newStory objectForKey:@"story_feed_id"]]) {
|
|
|
|
[self.recentlyReadFeeds removeObject:[newStory objectForKey:@"story_feed_id"]];
|
|
|
|
// }
|
|
|
|
|
2013-07-08 03:24:02 +02:00
|
|
|
NSDictionary *unreadCounts = [self.dictUnreadCounts objectForKey:feedIdStr];
|
2013-06-29 17:28:41 -07:00
|
|
|
NSMutableDictionary *newUnreadCounts = [unreadCounts mutableCopy];
|
2013-09-25 17:43:00 -07:00
|
|
|
NSInteger score = [NewsBlurAppDelegate computeStoryScore:[story objectForKey:@"intelligence"]];
|
2012-10-16 17:24:01 -07:00
|
|
|
if (score > 0) {
|
2013-06-29 17:28:41 -07:00
|
|
|
int unreads = MAX(0, [[newUnreadCounts objectForKey:@"ps"] intValue] + 1);
|
|
|
|
[newUnreadCounts setValue:[NSNumber numberWithInt:unreads] forKey:@"ps"];
|
2012-10-16 17:24:01 -07:00
|
|
|
} else if (score == 0) {
|
2013-06-29 17:28:41 -07:00
|
|
|
int unreads = MAX(0, [[newUnreadCounts objectForKey:@"nt"] intValue] + 1);
|
|
|
|
[newUnreadCounts setValue:[NSNumber numberWithInt:unreads] forKey:@"nt"];
|
2012-10-16 17:24:01 -07:00
|
|
|
} else if (score < 0) {
|
2013-06-29 17:28:41 -07:00
|
|
|
int unreads = MAX(0, [[newUnreadCounts objectForKey:@"ng"] intValue] + 1);
|
|
|
|
[newUnreadCounts setValue:[NSNumber numberWithInt:unreads] forKey:@"ng"];
|
2012-10-16 17:24:01 -07:00
|
|
|
}
|
2013-06-29 17:28:41 -07:00
|
|
|
[self.dictUnreadCounts setObject:newUnreadCounts forKey:feedIdStr];
|
2012-10-16 17:24:01 -07:00
|
|
|
|
2013-06-29 17:28:41 -07:00
|
|
|
[self.database inTransaction:^(FMDatabase *db, BOOL *rollback) {
|
|
|
|
[db executeUpdate:@"UPDATE unread_counts SET ps = ?, nt = ?, ng = ? WHERE feed_id = ?",
|
|
|
|
[newUnreadCounts objectForKey:@"ps"],
|
|
|
|
[newUnreadCounts objectForKey:@"nt"],
|
|
|
|
[newUnreadCounts objectForKey:@"ng"],
|
|
|
|
feedIdStr];
|
|
|
|
}];
|
2012-10-16 17:24:01 -07:00
|
|
|
}
|
|
|
|
|
2012-10-17 15:07:53 -07:00
|
|
|
- (void)markActiveStorySaved:(BOOL)saved {
|
|
|
|
NSMutableDictionary *newStory = [self.activeStory mutableCopy];
|
|
|
|
[newStory setValue:[NSNumber numberWithBool:saved] forKey:@"starred"];
|
|
|
|
|
|
|
|
self.activeStory = newStory;
|
|
|
|
|
|
|
|
// make the story as read in self.activeFeedStories
|
|
|
|
NSString *newStoryIdStr = [NSString stringWithFormat:@"%@", [newStory valueForKey:@"id"]];
|
|
|
|
NSMutableArray *newActiveFeedStories = [self.activeFeedStories mutableCopy];
|
|
|
|
for (int i = 0; i < [newActiveFeedStories count]; i++) {
|
|
|
|
NSMutableArray *thisStory = [[newActiveFeedStories objectAtIndex:i] mutableCopy];
|
|
|
|
NSString *thisStoryIdStr = [NSString stringWithFormat:@"%@", [thisStory valueForKey:@"id"]];
|
|
|
|
if ([newStoryIdStr isEqualToString:thisStoryIdStr]) {
|
|
|
|
[newActiveFeedStories replaceObjectAtIndex:i withObject:newStory];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.activeFeedStories = newActiveFeedStories;
|
2012-10-17 15:13:20 -07:00
|
|
|
|
|
|
|
if (saved) {
|
|
|
|
self.savedStoriesCount += 1;
|
|
|
|
} else {
|
|
|
|
self.savedStoriesCount -= 1;
|
|
|
|
}
|
2012-10-17 15:07:53 -07:00
|
|
|
}
|
|
|
|
|
2012-10-16 17:24:01 -07:00
|
|
|
- (void)markActiveFeedAllRead {
|
2011-10-18 17:44:05 -07:00
|
|
|
id feedId = [self.activeFeed objectForKey:@"id"];
|
2011-11-10 18:28:22 -08:00
|
|
|
[self markFeedAllRead:feedId];
|
2011-07-24 22:23:38 -07:00
|
|
|
}
|
|
|
|
|
2011-12-01 09:01:18 -08:00
|
|
|
- (void)markActiveFolderAllRead {
|
2013-02-06 15:15:43 -08:00
|
|
|
if ([self.activeFolder isEqual:@"everything"]) {
|
2011-12-01 09:01:18 -08:00
|
|
|
for (NSString *folderName in self.dictFoldersArray) {
|
|
|
|
for (id feedId in [self.dictFolders objectForKey:folderName]) {
|
|
|
|
[self markFeedAllRead:feedId];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (id feedId in [self.dictFolders objectForKey:self.activeFolder]) {
|
|
|
|
[self markFeedAllRead:feedId];
|
|
|
|
}
|
2011-11-09 09:51:42 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-10 18:28:22 -08:00
|
|
|
- (void)markFeedAllRead:(id)feedId {
|
|
|
|
NSString *feedIdStr = [NSString stringWithFormat:@"%@",feedId];
|
2013-06-29 17:28:41 -07:00
|
|
|
NSMutableDictionary *unreadCounts = [NSMutableDictionary dictionary];
|
2011-11-10 18:28:22 -08:00
|
|
|
|
2013-06-29 17:28:41 -07:00
|
|
|
[unreadCounts setValue:[NSNumber numberWithInt:0] forKey:@"ps"];
|
|
|
|
[unreadCounts setValue:[NSNumber numberWithInt:0] forKey:@"nt"];
|
|
|
|
[unreadCounts setValue:[NSNumber numberWithInt:0] forKey:@"ng"];
|
|
|
|
|
|
|
|
[self.dictUnreadCounts setObject:unreadCounts forKey:feedIdStr];
|
|
|
|
|
|
|
|
[self.database inTransaction:^(FMDatabase *db, BOOL *rollback) {
|
|
|
|
[db executeUpdate:@"UPDATE unread_counts SET ps = 0, nt = 0, ng = 0 WHERE feed_id = ?",
|
|
|
|
feedIdStr];
|
2013-08-06 18:08:55 -07:00
|
|
|
[db executeUpdate:@"DELETE FROM unread_hashes WHERE story_feed_id = ?", feedIdStr];
|
2013-06-29 17:28:41 -07:00
|
|
|
}];
|
2011-11-10 18:28:22 -08:00
|
|
|
}
|
|
|
|
|
2011-07-29 21:27:37 -07:00
|
|
|
- (void)calculateStoryLocations {
|
2011-11-09 09:51:42 -08:00
|
|
|
self.visibleUnreadCount = 0;
|
2011-08-01 09:43:13 -07:00
|
|
|
self.activeFeedStoryLocations = [NSMutableArray array];
|
2011-08-08 09:58:15 -07:00
|
|
|
self.activeFeedStoryLocationIds = [NSMutableArray array];
|
2011-07-29 21:27:37 -07:00
|
|
|
for (int i=0; i < self.storyCount; i++) {
|
|
|
|
NSDictionary *story = [self.activeFeedStories objectAtIndex:i];
|
2013-09-25 17:43:00 -07:00
|
|
|
NSInteger score = [NewsBlurAppDelegate computeStoryScore:[story objectForKey:@"intelligence"]];
|
2012-12-13 12:12:00 -08:00
|
|
|
if (score >= self.selectedIntelligence || [[story objectForKey:@"sticky"] boolValue]) {
|
2011-07-29 21:27:37 -07:00
|
|
|
NSNumber *location = [NSNumber numberWithInt:i];
|
|
|
|
[self.activeFeedStoryLocations addObject:location];
|
2011-08-08 09:58:15 -07:00
|
|
|
[self.activeFeedStoryLocationIds addObject:[story objectForKey:@"id"]];
|
2011-11-09 09:51:42 -08:00
|
|
|
if ([[story objectForKey:@"read_status"] intValue] == 0) {
|
|
|
|
self.visibleUnreadCount += 1;
|
|
|
|
}
|
2011-07-29 21:27:37 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-25 17:43:00 -07:00
|
|
|
+ (NSInteger)computeStoryScore:(NSDictionary *)intelligence {
|
|
|
|
NSInteger score = 0;
|
2011-07-26 08:37:10 -07:00
|
|
|
int title = [[intelligence objectForKey:@"title"] intValue];
|
|
|
|
int author = [[intelligence objectForKey:@"author"] intValue];
|
|
|
|
int tags = [[intelligence objectForKey:@"tags"] intValue];
|
|
|
|
|
|
|
|
int score_max = MAX(title, MAX(author, tags));
|
|
|
|
int score_min = MIN(title, MIN(author, tags));
|
2011-07-24 20:07:38 -07:00
|
|
|
|
|
|
|
if (score_max > 0) score = score_max;
|
|
|
|
else if (score_min < 0) score = score_min;
|
2010-11-22 10:44:52 -05:00
|
|
|
|
2011-07-24 20:07:38 -07:00
|
|
|
if (score == 0) score = [[intelligence objectForKey:@"feed"] integerValue];
|
|
|
|
|
2011-07-29 09:06:17 -07:00
|
|
|
// NSLog(@"%d/%d -- %d: %@", score_max, score_min, score, intelligence);
|
2010-11-22 10:44:52 -05:00
|
|
|
return score;
|
|
|
|
}
|
|
|
|
|
2013-06-29 17:28:41 -07:00
|
|
|
#pragma mark - Feed Management
|
2011-12-04 21:09:16 -08:00
|
|
|
|
|
|
|
- (NSString *)extractParentFolderName:(NSString *)folderName {
|
2012-10-15 14:57:20 -07:00
|
|
|
if ([folderName containsString:@"Top Level"] ||
|
2013-02-06 15:15:43 -08:00
|
|
|
[folderName isEqual:@"everything"]) {
|
2011-12-04 21:09:16 -08:00
|
|
|
folderName = @"";
|
|
|
|
}
|
|
|
|
|
|
|
|
if ([folderName containsString:@" - "]) {
|
2013-09-25 17:43:00 -07:00
|
|
|
NSInteger lastFolderLoc = [folderName rangeOfString:@" - "
|
|
|
|
options:NSBackwardsSearch].location;
|
2011-12-04 21:09:16 -08:00
|
|
|
folderName = [folderName substringToIndex:lastFolderLoc];
|
|
|
|
} else {
|
|
|
|
folderName = @"— Top Level —";
|
|
|
|
}
|
|
|
|
|
|
|
|
return folderName;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *)extractFolderName:(NSString *)folderName {
|
2012-10-15 14:57:20 -07:00
|
|
|
if ([folderName containsString:@"Top Level"] ||
|
2013-02-06 15:15:43 -08:00
|
|
|
[folderName isEqual:@"everything"]) {
|
2011-12-04 21:09:16 -08:00
|
|
|
folderName = @"";
|
|
|
|
}
|
|
|
|
if ([folderName containsString:@" - "]) {
|
2013-09-25 17:43:00 -07:00
|
|
|
NSInteger folder_loc = [folderName rangeOfString:@" - "
|
|
|
|
options:NSBackwardsSearch].location;
|
2011-12-04 21:09:16 -08:00
|
|
|
folderName = [folderName substringFromIndex:(folder_loc + 3)];
|
|
|
|
}
|
|
|
|
|
|
|
|
return folderName;
|
|
|
|
}
|
|
|
|
|
2012-12-28 11:34:06 -08:00
|
|
|
- (NSDictionary *)getFeed:(NSString *)feedId {
|
|
|
|
NSDictionary *feed;
|
|
|
|
if (self.isSocialView || self.isSocialRiverView) {
|
|
|
|
feed = [self.dictActiveFeeds objectForKey:feedId];
|
|
|
|
// this is to catch when a user is already subscribed
|
|
|
|
if (!feed) {
|
|
|
|
feed = [self.dictFeeds objectForKey:feedId];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
feed = [self.dictFeeds objectForKey:feedId];
|
|
|
|
}
|
|
|
|
|
|
|
|
return feed;
|
|
|
|
}
|
|
|
|
|
2011-12-04 21:09:16 -08:00
|
|
|
#pragma mark -
|
|
|
|
#pragma mark Feed Templates
|
|
|
|
|
2013-02-21 12:19:15 -08:00
|
|
|
+ (void)fillGradient:(CGRect)r startColor:(UIColor *)startColor endColor:(UIColor *)endColor {
|
|
|
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
|
|
|
UIGraphicsPushContext(context);
|
|
|
|
|
|
|
|
CGGradientRef gradient;
|
2013-02-14 15:36:21 -08:00
|
|
|
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
|
|
|
|
CGFloat locations[2] = {0.0f, 1.0f};
|
|
|
|
CGFloat startRed, startGreen, startBlue, startAlpha;
|
|
|
|
CGFloat endRed, endGreen, endBlue, endAlpha;
|
|
|
|
|
|
|
|
[startColor getRed:&startRed green:&startGreen blue:&startBlue alpha:&startAlpha];
|
|
|
|
[endColor getRed:&endRed green:&endGreen blue:&endBlue alpha:&endAlpha];
|
|
|
|
|
|
|
|
CGFloat components[8] = {
|
|
|
|
startRed, startGreen, startBlue, startAlpha,
|
|
|
|
endRed, endGreen, endBlue, endAlpha
|
|
|
|
};
|
2013-02-21 12:19:15 -08:00
|
|
|
gradient = CGGradientCreateWithColorComponents(colorSpace, components, locations, 2);
|
2013-02-14 15:36:21 -08:00
|
|
|
CGColorSpaceRelease(colorSpace);
|
2013-02-15 16:41:20 -08:00
|
|
|
|
2013-02-14 15:36:21 -08:00
|
|
|
CGPoint startPoint = CGPointMake(CGRectGetMinX(r), r.origin.y);
|
|
|
|
CGPoint endPoint = CGPointMake(startPoint.x, r.origin.y + r.size.height);
|
|
|
|
|
|
|
|
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
|
2013-02-21 12:19:15 -08:00
|
|
|
CGGradientRelease(gradient);
|
2013-02-14 15:36:21 -08:00
|
|
|
UIGraphicsPopContext();
|
|
|
|
}
|
|
|
|
|
2011-10-27 19:05:38 -07:00
|
|
|
+ (UIView *)makeGradientView:(CGRect)rect startColor:(NSString *)start endColor:(NSString *)end {
|
2012-07-15 15:06:06 -07:00
|
|
|
UIView *gradientView = [[UIView alloc] initWithFrame:rect];
|
2011-10-27 19:05:38 -07:00
|
|
|
|
|
|
|
CAGradientLayer *gradient = [CAGradientLayer layer];
|
2011-10-30 18:53:10 -07:00
|
|
|
gradient.frame = CGRectMake(0, 1, rect.size.width, rect.size.height-1);
|
2012-06-10 13:21:07 -07:00
|
|
|
gradient.opacity = 0.7;
|
2011-10-27 19:05:38 -07:00
|
|
|
unsigned int color = 0;
|
|
|
|
unsigned int colorFade = 0;
|
|
|
|
if ([start class] == [NSNull class]) {
|
|
|
|
start = @"505050";
|
|
|
|
}
|
|
|
|
if ([end class] == [NSNull class]) {
|
|
|
|
end = @"303030";
|
|
|
|
}
|
|
|
|
NSScanner *scanner = [NSScanner scannerWithString:start];
|
|
|
|
[scanner scanHexInt:&color];
|
|
|
|
NSScanner *scannerFade = [NSScanner scannerWithString:end];
|
|
|
|
[scannerFade scanHexInt:&colorFade];
|
|
|
|
gradient.colors = [NSArray arrayWithObjects:(id)[UIColorFromRGB(color) CGColor], (id)[UIColorFromRGB(colorFade) CGColor], nil];
|
2011-10-28 18:29:33 -07:00
|
|
|
|
|
|
|
CALayer *whiteBackground = [CALayer layer];
|
2011-10-30 18:53:10 -07:00
|
|
|
whiteBackground.frame = CGRectMake(0, 1, rect.size.width, rect.size.height-1);
|
2012-06-10 13:21:07 -07:00
|
|
|
whiteBackground.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.7].CGColor;
|
2011-10-28 18:29:33 -07:00
|
|
|
[gradientView.layer addSublayer:whiteBackground];
|
|
|
|
|
2011-10-27 19:05:38 -07:00
|
|
|
[gradientView.layer addSublayer:gradient];
|
2011-10-28 18:29:33 -07:00
|
|
|
|
|
|
|
CALayer *topBorder = [CALayer layer];
|
2011-10-30 18:53:10 -07:00
|
|
|
topBorder.frame = CGRectMake(0, 1, rect.size.width, 1);
|
2012-06-10 13:21:07 -07:00
|
|
|
topBorder.backgroundColor = [UIColorFromRGB(colorFade) colorWithAlphaComponent:0.7].CGColor;
|
2011-10-30 15:06:25 -07:00
|
|
|
topBorder.opacity = 1;
|
2011-10-28 18:29:33 -07:00
|
|
|
[gradientView.layer addSublayer:topBorder];
|
|
|
|
|
|
|
|
CALayer *bottomBorder = [CALayer layer];
|
|
|
|
bottomBorder.frame = CGRectMake(0, rect.size.height-1, rect.size.width, 1);
|
2012-06-10 13:21:07 -07:00
|
|
|
bottomBorder.backgroundColor = [UIColorFromRGB(colorFade) colorWithAlphaComponent:0.7].CGColor;
|
2011-10-30 15:06:25 -07:00
|
|
|
bottomBorder.opacity = 1;
|
2011-10-28 18:29:33 -07:00
|
|
|
[gradientView.layer addSublayer:bottomBorder];
|
|
|
|
|
|
|
|
return gradientView;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (UIView *)makeFeedTitleGradient:(NSDictionary *)feed withRect:(CGRect)rect {
|
|
|
|
UIView *gradientView;
|
2012-08-08 13:48:10 -07:00
|
|
|
if (self.isRiverView || self.isSocialView || self.isSocialRiverView) {
|
2011-10-28 18:29:33 -07:00
|
|
|
gradientView = [NewsBlurAppDelegate
|
|
|
|
makeGradientView:rect
|
2012-06-30 21:28:48 -07:00
|
|
|
startColor:[feed objectForKey:@"favicon_fade"]
|
|
|
|
endColor:[feed objectForKey:@"favicon_color"]];
|
2011-10-28 18:29:33 -07:00
|
|
|
|
2012-07-15 15:06:06 -07:00
|
|
|
UILabel *titleLabel = [[UILabel alloc] init];
|
2011-10-28 18:29:33 -07:00
|
|
|
titleLabel.text = [feed objectForKey:@"feed_title"];
|
|
|
|
titleLabel.backgroundColor = [UIColor clearColor];
|
2013-06-17 11:50:13 -07:00
|
|
|
titleLabel.textAlignment = NSTextAlignmentLeft;
|
|
|
|
titleLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
2011-12-04 21:09:16 -08:00
|
|
|
titleLabel.numberOfLines = 1;
|
2011-10-28 18:29:33 -07:00
|
|
|
titleLabel.font = [UIFont fontWithName:@"Helvetica-Bold" size:11.0];
|
|
|
|
titleLabel.shadowOffset = CGSizeMake(0, 1);
|
|
|
|
if ([[feed objectForKey:@"favicon_text_color"] class] != [NSNull class]) {
|
2011-11-30 18:46:11 -08:00
|
|
|
titleLabel.textColor = [[feed objectForKey:@"favicon_text_color"]
|
|
|
|
isEqualToString:@"white"] ?
|
2012-06-30 21:28:48 -07:00
|
|
|
[UIColor whiteColor] :
|
|
|
|
[UIColor blackColor];
|
2011-11-30 18:46:11 -08:00
|
|
|
titleLabel.shadowColor = [[feed objectForKey:@"favicon_text_color"]
|
|
|
|
isEqualToString:@"white"] ?
|
2012-06-30 21:28:48 -07:00
|
|
|
UIColorFromRGB(0x202020) :
|
|
|
|
UIColorFromRGB(0xd0d0d0);
|
2011-10-28 18:29:33 -07:00
|
|
|
} else {
|
|
|
|
titleLabel.textColor = [UIColor whiteColor];
|
|
|
|
titleLabel.shadowColor = [UIColor blackColor];
|
|
|
|
}
|
2011-12-04 21:09:16 -08:00
|
|
|
titleLabel.frame = CGRectMake(32, 1, rect.size.width-32, 20);
|
2011-10-28 18:29:33 -07:00
|
|
|
|
|
|
|
NSString *feedIdStr = [NSString stringWithFormat:@"%@", [feed objectForKey:@"id"]];
|
|
|
|
UIImage *titleImage = [Utilities getImage:feedIdStr];
|
|
|
|
UIImageView *titleImageView = [[UIImageView alloc] initWithImage:titleImage];
|
2011-10-30 18:53:10 -07:00
|
|
|
titleImageView.frame = CGRectMake(8, 3, 16.0, 16.0);
|
2011-10-28 18:29:33 -07:00
|
|
|
[titleLabel addSubview:titleImageView];
|
|
|
|
|
|
|
|
[gradientView addSubview:titleLabel];
|
|
|
|
[gradientView addSubview:titleImageView];
|
|
|
|
} else {
|
|
|
|
gradientView = [NewsBlurAppDelegate
|
2012-11-06 17:26:08 -08:00
|
|
|
makeGradientView:CGRectMake(0, -1, rect.size.width, 10)
|
2012-06-22 21:53:45 -07:00
|
|
|
// hard coding the 1024 as a hack for window.frame.size.width
|
2012-06-30 21:28:48 -07:00
|
|
|
startColor:[feed objectForKey:@"favicon_fade"]
|
|
|
|
endColor:[feed objectForKey:@"favicon_color"]];
|
2011-10-28 18:29:33 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
gradientView.opaque = YES;
|
|
|
|
|
2011-10-27 19:05:38 -07:00
|
|
|
return gradientView;
|
|
|
|
}
|
2011-08-18 09:56:52 -07:00
|
|
|
|
2011-12-02 16:23:00 -08:00
|
|
|
- (UIView *)makeFeedTitle:(NSDictionary *)feed {
|
2012-07-15 15:06:06 -07:00
|
|
|
UILabel *titleLabel = [[UILabel alloc] init];
|
2012-12-07 15:17:22 -08:00
|
|
|
if (self.isSocialRiverView && [self.activeFolder isEqualToString:@"river_blurblogs"]) {
|
2012-10-03 15:46:02 -07:00
|
|
|
titleLabel.text = [NSString stringWithFormat:@" All Shared Stories"];
|
2012-12-07 15:17:22 -08:00
|
|
|
} else if (self.isSocialRiverView && [self.activeFolder isEqualToString:@"river_global"]) {
|
|
|
|
titleLabel.text = [NSString stringWithFormat:@" Global Shared Stories"];
|
2012-10-03 15:46:02 -07:00
|
|
|
} else if (self.isRiverView && [self.activeFolder isEqualToString:@"everything"]) {
|
|
|
|
titleLabel.text = [NSString stringWithFormat:@" All Stories"];
|
2012-10-17 15:07:53 -07:00
|
|
|
} else if (self.isRiverView && [self.activeFolder isEqualToString:@"saved_stories"]) {
|
|
|
|
titleLabel.text = [NSString stringWithFormat:@" Saved Stories"];
|
2012-08-08 10:57:38 -07:00
|
|
|
} else if (self.isRiverView) {
|
2012-10-03 15:46:02 -07:00
|
|
|
titleLabel.text = [NSString stringWithFormat:@" %@", self.activeFolder];
|
2012-07-12 22:05:23 -07:00
|
|
|
} else if (self.isSocialView) {
|
|
|
|
titleLabel.text = [NSString stringWithFormat:@" %@", [feed objectForKey:@"feed_title"]];
|
2011-12-02 16:23:00 -08:00
|
|
|
} else {
|
|
|
|
titleLabel.text = [NSString stringWithFormat:@" %@", [feed objectForKey:@"feed_title"]];
|
|
|
|
}
|
|
|
|
titleLabel.backgroundColor = [UIColor clearColor];
|
2013-06-17 11:50:13 -07:00
|
|
|
titleLabel.textAlignment = NSTextAlignmentLeft;
|
2011-12-02 16:23:00 -08:00
|
|
|
titleLabel.font = [UIFont fontWithName:@"Helvetica-Bold" size:15.0];
|
2013-09-24 17:18:20 -07:00
|
|
|
titleLabel.textColor = UIColorFromRGB(0x4D4C4A);
|
2013-06-17 11:50:13 -07:00
|
|
|
titleLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
2011-12-04 21:09:16 -08:00
|
|
|
titleLabel.numberOfLines = 1;
|
2013-09-24 17:18:20 -07:00
|
|
|
titleLabel.shadowColor = UIColorFromRGB(0xF0F0F0);
|
|
|
|
titleLabel.shadowOffset = CGSizeMake(0, 1);
|
2012-07-12 22:05:23 -07:00
|
|
|
titleLabel.center = CGPointMake(0, -2);
|
2011-12-02 16:23:00 -08:00
|
|
|
[titleLabel sizeToFit];
|
|
|
|
|
2012-07-12 22:05:23 -07:00
|
|
|
if (!self.isSocialView) {
|
|
|
|
titleLabel.center = CGPointMake(28, -2);
|
|
|
|
NSString *feedIdStr = [NSString stringWithFormat:@"%@", [feed objectForKey:@"id"]];
|
|
|
|
UIImage *titleImage;
|
2013-02-21 12:19:15 -08:00
|
|
|
if (self.isSocialRiverView && [self.activeFolder isEqualToString:@"river_global"]) {
|
|
|
|
titleImage = [UIImage imageNamed:@"ak-icon-global.png"];
|
|
|
|
} else if (self.isSocialRiverView && [self.activeFolder isEqualToString:@"river_blurblogs"]) {
|
|
|
|
titleImage = [UIImage imageNamed:@"ak-icon-blurblogs.png"];
|
2012-10-17 15:07:53 -07:00
|
|
|
} else if (self.isRiverView && [self.activeFolder isEqualToString:@"everything"]) {
|
2013-02-21 12:19:15 -08:00
|
|
|
titleImage = [UIImage imageNamed:@"ak-icon-allstories.png"];
|
2012-10-17 15:07:53 -07:00
|
|
|
} else if (self.isRiverView && [self.activeFolder isEqualToString:@"saved_stories"]) {
|
2013-03-07 10:55:23 -05:00
|
|
|
titleImage = [UIImage imageNamed:@"clock.png"];
|
2012-08-08 10:57:38 -07:00
|
|
|
} else if (self.isRiverView) {
|
2013-02-21 14:44:34 -08:00
|
|
|
titleImage = [UIImage imageNamed:@"g_icn_folder.png"];
|
2012-07-12 22:05:23 -07:00
|
|
|
} else {
|
|
|
|
titleImage = [Utilities getImage:feedIdStr];
|
|
|
|
}
|
|
|
|
UIImageView *titleImageView = [[UIImageView alloc] initWithImage:titleImage];
|
|
|
|
titleImageView.frame = CGRectMake(0.0, 2.0, 16.0, 16.0);
|
|
|
|
[titleLabel addSubview:titleImageView];
|
|
|
|
}
|
|
|
|
return titleLabel;
|
|
|
|
}
|
|
|
|
|
2013-09-24 17:18:20 -07:00
|
|
|
- (NBBarButtonItem *)makeRightFeedTitle:(NSDictionary *)feed {
|
2012-07-12 22:05:23 -07:00
|
|
|
|
2011-12-02 16:23:00 -08:00
|
|
|
NSString *feedIdStr = [NSString stringWithFormat:@"%@", [feed objectForKey:@"id"]];
|
2012-07-25 17:29:29 -07:00
|
|
|
UIImage *titleImage = [Utilities getImage:feedIdStr];
|
2011-12-02 16:23:00 -08:00
|
|
|
|
2012-07-12 22:05:23 -07:00
|
|
|
titleImage = [Utilities roundCorneredImage:titleImage radius:6];
|
|
|
|
|
2013-09-24 17:18:20 -07:00
|
|
|
NBBarButtonItem *titleImageButton = [NBBarButtonItem buttonWithType:UIButtonTypeCustom];
|
2012-07-12 22:05:23 -07:00
|
|
|
titleImageButton.bounds = CGRectMake(0, 0, 32, 32);
|
|
|
|
|
|
|
|
[titleImageButton setImage:titleImage forState:UIControlStateNormal];
|
|
|
|
return titleImageButton;
|
2011-12-02 16:23:00 -08:00
|
|
|
}
|
|
|
|
|
2012-12-27 18:37:05 -08:00
|
|
|
#pragma mark -
|
|
|
|
#pragma mark Classifiers
|
|
|
|
|
|
|
|
- (void)toggleAuthorClassifier:(NSString *)author feedId:(NSString *)feedId {
|
|
|
|
int authorScore = [[[[self.activeClassifiers objectForKey:feedId]
|
|
|
|
objectForKey:@"authors"]
|
|
|
|
objectForKey:author] intValue];
|
|
|
|
if (authorScore > 0) {
|
|
|
|
authorScore = -1;
|
|
|
|
} else if (authorScore < 0) {
|
|
|
|
authorScore = 0;
|
|
|
|
} else {
|
|
|
|
authorScore = 1;
|
|
|
|
}
|
|
|
|
NSMutableDictionary *feedClassifiers = [[self.activeClassifiers objectForKey:feedId]
|
|
|
|
mutableCopy];
|
2013-09-05 17:07:21 -07:00
|
|
|
if (!feedClassifiers) feedClassifiers = [NSMutableDictionary dictionary];
|
2012-12-27 18:37:05 -08:00
|
|
|
NSMutableDictionary *authors = [[feedClassifiers objectForKey:@"authors"] mutableCopy];
|
2013-09-05 17:07:21 -07:00
|
|
|
if (!authors) authors = [NSMutableDictionary dictionary];
|
2012-12-27 18:37:05 -08:00
|
|
|
[authors setObject:[NSNumber numberWithInt:authorScore] forKey:author];
|
|
|
|
[feedClassifiers setObject:authors forKey:@"authors"];
|
|
|
|
[self.activeClassifiers setObject:feedClassifiers forKey:feedId];
|
|
|
|
[self.storyPageControl refreshHeaders];
|
|
|
|
[self.trainerViewController refresh];
|
|
|
|
|
2013-06-18 21:23:20 -04:00
|
|
|
NSString *urlString = [NSString stringWithFormat:@"%@/classifier/save",
|
2012-12-27 18:37:05 -08:00
|
|
|
NEWSBLUR_URL];
|
|
|
|
NSURL *url = [NSURL URLWithString:urlString];
|
|
|
|
__block ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
|
2013-09-05 17:07:21 -07:00
|
|
|
__weak ASIFormDataRequest *_request = request;
|
2012-12-27 18:37:05 -08:00
|
|
|
[request setPostValue:author
|
|
|
|
forKey:authorScore >= 1 ? @"like_author" :
|
|
|
|
authorScore <= -1 ? @"dislike_author" :
|
|
|
|
@"remove_like_author"];
|
|
|
|
[request setPostValue:feedId forKey:@"feed_id"];
|
|
|
|
[request setCompletionBlock:^{
|
2013-09-05 17:07:21 -07:00
|
|
|
[self requestClassifierResponse:_request withFeed:feedId];
|
|
|
|
}];
|
|
|
|
[request setFailedBlock:^{
|
|
|
|
[self requestClassifierResponse:_request withFeed:feedId];
|
2012-12-27 18:37:05 -08:00
|
|
|
}];
|
|
|
|
[request setDelegate:self];
|
|
|
|
[request startAsynchronous];
|
|
|
|
|
|
|
|
[self recalculateIntelligenceScores:feedId];
|
|
|
|
[self.feedDetailViewController.storyTitlesTable reloadData];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)toggleTagClassifier:(NSString *)tag feedId:(NSString *)feedId {
|
|
|
|
NSLog(@"toggleTagClassifier: %@", tag);
|
|
|
|
int tagScore = [[[[self.activeClassifiers objectForKey:feedId]
|
|
|
|
objectForKey:@"tags"]
|
|
|
|
objectForKey:tag] intValue];
|
|
|
|
|
|
|
|
if (tagScore > 0) {
|
|
|
|
tagScore = -1;
|
|
|
|
} else if (tagScore < 0) {
|
|
|
|
tagScore = 0;
|
|
|
|
} else {
|
|
|
|
tagScore = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
NSMutableDictionary *feedClassifiers = [[self.activeClassifiers objectForKey:feedId]
|
|
|
|
mutableCopy];
|
2013-09-05 17:07:21 -07:00
|
|
|
if (!feedClassifiers) feedClassifiers = [NSMutableDictionary dictionary];
|
2012-12-27 18:37:05 -08:00
|
|
|
NSMutableDictionary *tags = [[feedClassifiers objectForKey:@"tags"] mutableCopy];
|
2013-09-05 17:07:21 -07:00
|
|
|
if (!tags) tags = [NSMutableDictionary dictionary];
|
2012-12-27 18:37:05 -08:00
|
|
|
[tags setObject:[NSNumber numberWithInt:tagScore] forKey:tag];
|
|
|
|
[feedClassifiers setObject:tags forKey:@"tags"];
|
|
|
|
[self.activeClassifiers setObject:feedClassifiers forKey:feedId];
|
|
|
|
[self.storyPageControl refreshHeaders];
|
|
|
|
[self.trainerViewController refresh];
|
|
|
|
|
2013-06-18 21:23:20 -04:00
|
|
|
NSString *urlString = [NSString stringWithFormat:@"%@/classifier/save",
|
2012-12-27 18:37:05 -08:00
|
|
|
NEWSBLUR_URL];
|
|
|
|
NSURL *url = [NSURL URLWithString:urlString];
|
|
|
|
__block ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
|
2013-09-05 17:07:21 -07:00
|
|
|
__weak ASIFormDataRequest *_request = request;
|
2012-12-27 18:37:05 -08:00
|
|
|
[request setPostValue:tag
|
|
|
|
forKey:tagScore >= 1 ? @"like_tag" :
|
|
|
|
tagScore <= -1 ? @"dislike_tag" :
|
|
|
|
@"remove_like_tag"];
|
|
|
|
[request setPostValue:feedId forKey:@"feed_id"];
|
|
|
|
[request setCompletionBlock:^{
|
2013-09-05 17:07:21 -07:00
|
|
|
[self requestClassifierResponse:_request withFeed:feedId];
|
|
|
|
}];
|
|
|
|
[request setFailedBlock:^{
|
|
|
|
[self requestClassifierResponse:_request withFeed:feedId];
|
2012-12-27 18:37:05 -08:00
|
|
|
}];
|
|
|
|
[request setDelegate:self];
|
|
|
|
[request startAsynchronous];
|
|
|
|
|
|
|
|
[self recalculateIntelligenceScores:feedId];
|
|
|
|
[self.feedDetailViewController.storyTitlesTable reloadData];
|
|
|
|
}
|
|
|
|
|
2013-09-25 17:43:00 -07:00
|
|
|
- (void)toggleTitleClassifier:(NSString *)title feedId:(NSString *)feedId score:(NSInteger)score {
|
|
|
|
NSLog(@"toggle Title: %@ (%@) / %ld", title, feedId, (long)score);
|
|
|
|
NSInteger titleScore = [[[[self.activeClassifiers objectForKey:feedId]
|
|
|
|
objectForKey:@"titles"]
|
|
|
|
objectForKey:title] intValue];
|
2012-12-27 18:37:05 -08:00
|
|
|
|
|
|
|
if (score) {
|
|
|
|
titleScore = score;
|
|
|
|
} else {
|
|
|
|
if (titleScore > 0) {
|
|
|
|
titleScore = -1;
|
|
|
|
} else if (titleScore < 0) {
|
|
|
|
titleScore = 0;
|
|
|
|
} else {
|
|
|
|
titleScore = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NSMutableDictionary *feedClassifiers = [[self.activeClassifiers objectForKey:feedId]
|
|
|
|
mutableCopy];
|
2013-09-05 17:07:21 -07:00
|
|
|
if (!feedClassifiers) feedClassifiers = [NSMutableDictionary dictionary];
|
2012-12-27 18:37:05 -08:00
|
|
|
NSMutableDictionary *titles = [[feedClassifiers objectForKey:@"titles"] mutableCopy];
|
2013-09-05 17:07:21 -07:00
|
|
|
if (!titles) titles = [NSMutableDictionary dictionary];
|
2013-09-25 17:43:00 -07:00
|
|
|
[titles setObject:[NSNumber numberWithInteger:titleScore] forKey:title];
|
2012-12-27 18:37:05 -08:00
|
|
|
[feedClassifiers setObject:titles forKey:@"titles"];
|
|
|
|
[self.activeClassifiers setObject:feedClassifiers forKey:feedId];
|
|
|
|
[self.storyPageControl refreshHeaders];
|
|
|
|
[self.trainerViewController refresh];
|
|
|
|
|
2013-06-18 21:23:20 -04:00
|
|
|
NSString *urlString = [NSString stringWithFormat:@"%@/classifier/save",
|
2012-12-27 18:37:05 -08:00
|
|
|
NEWSBLUR_URL];
|
|
|
|
NSURL *url = [NSURL URLWithString:urlString];
|
|
|
|
__block ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
|
2013-09-05 17:07:21 -07:00
|
|
|
__weak ASIFormDataRequest *_request = request;
|
2012-12-27 18:37:05 -08:00
|
|
|
[request setPostValue:title
|
|
|
|
forKey:titleScore >= 1 ? @"like_title" :
|
|
|
|
titleScore <= -1 ? @"dislike_title" :
|
|
|
|
@"remove_like_title"];
|
|
|
|
[request setPostValue:feedId forKey:@"feed_id"];
|
|
|
|
[request setCompletionBlock:^{
|
2013-09-05 17:07:21 -07:00
|
|
|
[self requestClassifierResponse:_request withFeed:feedId];
|
|
|
|
}];
|
|
|
|
[request setFailedBlock:^{
|
|
|
|
[self requestClassifierResponse:_request withFeed:feedId];
|
2012-12-27 18:37:05 -08:00
|
|
|
}];
|
|
|
|
[request setDelegate:self];
|
|
|
|
[request startAsynchronous];
|
|
|
|
|
|
|
|
[self recalculateIntelligenceScores:feedId];
|
|
|
|
[self.feedDetailViewController.storyTitlesTable reloadData];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)toggleFeedClassifier:(NSString *)feedId {
|
|
|
|
int feedScore = [[[[self.activeClassifiers objectForKey:feedId]
|
|
|
|
objectForKey:@"feeds"]
|
|
|
|
objectForKey:feedId] intValue];
|
|
|
|
|
|
|
|
if (feedScore > 0) {
|
|
|
|
feedScore = -1;
|
|
|
|
} else if (feedScore < 0) {
|
|
|
|
feedScore = 0;
|
|
|
|
} else {
|
|
|
|
feedScore = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
NSMutableDictionary *feedClassifiers = [[self.activeClassifiers objectForKey:feedId]
|
|
|
|
mutableCopy];
|
2013-09-05 17:07:21 -07:00
|
|
|
if (!feedClassifiers) feedClassifiers = [NSMutableDictionary dictionary];
|
2012-12-27 18:37:05 -08:00
|
|
|
NSMutableDictionary *feeds = [[feedClassifiers objectForKey:@"feeds"] mutableCopy];
|
|
|
|
[feeds setObject:[NSNumber numberWithInt:feedScore] forKey:feedId];
|
|
|
|
[feedClassifiers setObject:feeds forKey:@"feeds"];
|
|
|
|
[self.activeClassifiers setObject:feedClassifiers forKey:feedId];
|
|
|
|
[self.storyPageControl refreshHeaders];
|
|
|
|
[self.trainerViewController refresh];
|
|
|
|
|
2013-06-18 21:23:20 -04:00
|
|
|
NSString *urlString = [NSString stringWithFormat:@"%@/classifier/save",
|
2012-12-27 18:37:05 -08:00
|
|
|
NEWSBLUR_URL];
|
|
|
|
NSURL *url = [NSURL URLWithString:urlString];
|
|
|
|
__block ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
|
2013-09-05 17:07:21 -07:00
|
|
|
__weak ASIFormDataRequest *_request = request;
|
2012-12-27 18:37:05 -08:00
|
|
|
[request setPostValue:feedId
|
|
|
|
forKey:feedScore >= 1 ? @"like_feed" :
|
|
|
|
feedScore <= -1 ? @"dislike_feed" :
|
|
|
|
@"remove_like_feed"];
|
|
|
|
[request setPostValue:feedId forKey:@"feed_id"];
|
|
|
|
[request setCompletionBlock:^{
|
2013-09-05 17:07:21 -07:00
|
|
|
[self requestClassifierResponse:_request withFeed:feedId];
|
|
|
|
}];
|
|
|
|
[request setFailedBlock:^{
|
|
|
|
[self requestClassifierResponse:_request withFeed:feedId];
|
2012-12-27 18:37:05 -08:00
|
|
|
}];
|
|
|
|
[request setDelegate:self];
|
|
|
|
[request startAsynchronous];
|
|
|
|
|
|
|
|
[self recalculateIntelligenceScores:feedId];
|
|
|
|
[self.feedDetailViewController.storyTitlesTable reloadData];
|
|
|
|
}
|
|
|
|
|
2013-09-05 17:07:21 -07:00
|
|
|
- (void)requestClassifierResponse:(ASIHTTPRequest *)request withFeed:(NSString *)feedId {
|
|
|
|
BaseViewController *view;
|
|
|
|
if (self.trainerViewController.isViewLoaded && self.trainerViewController.view.window) {
|
|
|
|
view = self.trainerViewController;
|
|
|
|
} else {
|
|
|
|
view = self.storyPageControl.currentPage;
|
|
|
|
}
|
|
|
|
if ([request responseStatusCode] == 503) {
|
|
|
|
return [view informError:@"In maintenance mode"];
|
|
|
|
} else if ([request responseStatusCode] != 200) {
|
|
|
|
return [view informError:@"The server barfed!"];
|
|
|
|
}
|
|
|
|
|
|
|
|
[self.feedsViewController refreshFeedList:feedId];
|
|
|
|
}
|
|
|
|
|
2013-03-06 14:29:40 -08:00
|
|
|
- (void)requestFailed:(ASIHTTPRequest *)request {
|
|
|
|
NSError *error = [request error];
|
|
|
|
NSLog(@"Error: %@", error);
|
|
|
|
[self informError:error];
|
|
|
|
}
|
|
|
|
|
2013-05-30 18:45:51 -07:00
|
|
|
#pragma mark -
|
|
|
|
#pragma mark Storing Stories for Offline
|
|
|
|
|
2013-09-25 17:43:00 -07:00
|
|
|
- (NSInteger)databaseSchemaVersion:(FMDatabase *)db {
|
2013-06-05 17:11:01 -07:00
|
|
|
int version = 0;
|
2013-06-14 19:21:30 -07:00
|
|
|
FMResultSet *resultSet = [db executeQuery:@"PRAGMA user_version"];
|
2013-06-05 17:11:01 -07:00
|
|
|
if ([resultSet next]) {
|
|
|
|
version = [resultSet intForColumnIndex:0];
|
|
|
|
}
|
|
|
|
return version;
|
|
|
|
}
|
|
|
|
|
2013-06-14 19:21:30 -07:00
|
|
|
- (void)createDatabaseConnection {
|
2013-06-26 16:22:44 -07:00
|
|
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
2013-06-05 17:11:01 -07:00
|
|
|
NSString *docsPath = [paths objectAtIndex:0];
|
2013-06-18 21:23:20 -04:00
|
|
|
NSString *dbName = [NSString stringWithFormat:@"%@.sqlite", NEWSBLUR_HOST];
|
2013-06-14 19:21:30 -07:00
|
|
|
NSString *path = [docsPath stringByAppendingPathComponent:dbName];
|
2013-06-05 17:11:01 -07:00
|
|
|
|
2013-06-14 19:21:30 -07:00
|
|
|
database = [FMDatabaseQueue databaseQueueWithPath:path];
|
|
|
|
[database inDatabase:^(FMDatabase *db) {
|
|
|
|
[self setupDatabase:db];
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setupDatabase:(FMDatabase *)db {
|
|
|
|
if ([self databaseSchemaVersion:db] < CURRENT_DB_VERSION) {
|
2013-06-05 17:11:01 -07:00
|
|
|
// FMDB cannot execute this query because FMDB tries to use prepared statements
|
2013-06-21 22:18:54 -07:00
|
|
|
[db closeOpenResultSets];
|
|
|
|
[db executeUpdate:@"drop table if exists `stories`"];
|
|
|
|
[db executeUpdate:@"drop table if exists `unread_hashes`"];
|
|
|
|
[db executeUpdate:@"drop table if exists `accounts`"];
|
2013-06-29 17:28:41 -07:00
|
|
|
[db executeUpdate:@"drop table if exists `unread_counts`"];
|
2013-06-22 19:34:12 -07:00
|
|
|
[db executeUpdate:@"drop table if exists `cached_images`"];
|
2013-09-05 16:34:39 -07:00
|
|
|
[db executeUpdate:@"drop table if exists `users`"];
|
2013-07-11 18:36:09 -07:00
|
|
|
// [db executeUpdate:@"drop table if exists `queued_read_hashes`"]; // Nope, don't clear this.
|
2013-06-14 19:21:30 -07:00
|
|
|
NSLog(@"Dropped db: %@", [db lastErrorMessage]);
|
|
|
|
sqlite3_exec(db.sqliteHandle, [[NSString stringWithFormat:@"PRAGMA user_version = %d", CURRENT_DB_VERSION] UTF8String], NULL, NULL, NULL);
|
|
|
|
}
|
2013-06-21 22:18:54 -07:00
|
|
|
NSString *createAccountsTable = [NSString stringWithFormat:@"create table if not exists accounts "
|
2013-06-20 19:25:57 -07:00
|
|
|
"("
|
|
|
|
" username varchar(36),"
|
|
|
|
" download_date date,"
|
|
|
|
" feeds_json text,"
|
|
|
|
" UNIQUE(username) ON CONFLICT REPLACE"
|
|
|
|
")"];
|
2013-06-21 22:18:54 -07:00
|
|
|
[db executeUpdate:createAccountsTable];
|
|
|
|
|
2013-06-29 17:28:41 -07:00
|
|
|
NSString *createCountsTable = [NSString stringWithFormat:@"create table if not exists unread_counts "
|
2013-06-21 22:18:54 -07:00
|
|
|
"("
|
2013-06-29 17:28:41 -07:00
|
|
|
" feed_id varchar(20),"
|
2013-06-21 22:18:54 -07:00
|
|
|
" ps number,"
|
|
|
|
" nt number,"
|
|
|
|
" ng number,"
|
|
|
|
" UNIQUE(feed_id) ON CONFLICT REPLACE"
|
|
|
|
")"];
|
2013-06-29 17:28:41 -07:00
|
|
|
[db executeUpdate:createCountsTable];
|
2013-06-20 19:25:57 -07:00
|
|
|
|
2013-06-14 19:21:30 -07:00
|
|
|
NSString *createStoryTable = [NSString stringWithFormat:@"create table if not exists stories "
|
|
|
|
"("
|
|
|
|
" story_feed_id number,"
|
|
|
|
" story_hash varchar(24),"
|
|
|
|
" story_timestamp number,"
|
|
|
|
" story_json text,"
|
|
|
|
" UNIQUE(story_hash) ON CONFLICT REPLACE"
|
|
|
|
")"];
|
|
|
|
[db executeUpdate:createStoryTable];
|
2013-06-26 16:22:44 -07:00
|
|
|
NSString *indexStoriesFeed = @"CREATE INDEX IF NOT EXISTS stories_story_feed_id ON stories (story_feed_id)";
|
|
|
|
[db executeUpdate:indexStoriesFeed];
|
2013-06-14 19:21:30 -07:00
|
|
|
|
|
|
|
NSString *createUnreadHashTable = [NSString stringWithFormat:@"create table if not exists unread_hashes "
|
|
|
|
"("
|
|
|
|
" story_feed_id number,"
|
|
|
|
" story_hash varchar(24),"
|
2013-06-16 21:39:38 -07:00
|
|
|
" story_timestamp number,"
|
2013-06-14 19:21:30 -07:00
|
|
|
" UNIQUE(story_hash) ON CONFLICT IGNORE"
|
|
|
|
")"];
|
|
|
|
[db executeUpdate:createUnreadHashTable];
|
2013-06-26 16:22:44 -07:00
|
|
|
NSString *indexUnreadHashes = @"CREATE INDEX IF NOT EXISTS unread_hashes_story_feed_id ON unread_hashes (story_feed_id)";
|
|
|
|
[db executeUpdate:indexUnreadHashes];
|
|
|
|
NSString *indexUnreadTimestamp = @"CREATE INDEX IF NOT EXISTS unread_hashes_timestamp ON stories (story_timestamp)";
|
|
|
|
[db executeUpdate:indexUnreadTimestamp];
|
2013-06-14 19:21:30 -07:00
|
|
|
|
|
|
|
NSString *createReadTable = [NSString stringWithFormat:@"create table if not exists queued_read_hashes "
|
|
|
|
"("
|
|
|
|
" story_feed_id number,"
|
|
|
|
" story_hash varchar(24),"
|
|
|
|
" UNIQUE(story_hash) ON CONFLICT IGNORE"
|
|
|
|
")"];
|
|
|
|
[db executeUpdate:createReadTable];
|
2013-09-05 16:34:39 -07:00
|
|
|
|
2013-06-22 19:34:12 -07:00
|
|
|
NSString *createImagesTable = [NSString stringWithFormat:@"create table if not exists cached_images "
|
|
|
|
"("
|
|
|
|
" story_feed_id number,"
|
|
|
|
" story_hash varchar(24),"
|
|
|
|
" image_url varchar(1024),"
|
2013-07-18 18:24:38 -07:00
|
|
|
" image_cached boolean,"
|
2013-07-11 18:36:09 -07:00
|
|
|
" failed boolean"
|
2013-06-22 19:34:12 -07:00
|
|
|
")"];
|
|
|
|
[db executeUpdate:createImagesTable];
|
2013-06-26 16:22:44 -07:00
|
|
|
NSString *indexImagesFeedId = @"CREATE INDEX IF NOT EXISTS cached_images_story_feed_id ON cached_images (story_feed_id)";
|
|
|
|
[db executeUpdate:indexImagesFeedId];
|
|
|
|
NSString *indexImagesStoryHash = @"CREATE INDEX IF NOT EXISTS cached_images_story_hash ON cached_images (story_hash)";
|
|
|
|
[db executeUpdate:indexImagesStoryHash];
|
2013-06-22 19:34:12 -07:00
|
|
|
|
2013-09-05 16:34:39 -07:00
|
|
|
|
|
|
|
NSString *createUsersTable = [NSString stringWithFormat:@"create table if not exists users "
|
|
|
|
"("
|
|
|
|
" user_id number,"
|
|
|
|
" username varchar(64),"
|
|
|
|
" location varchar(128),"
|
|
|
|
" image_url varchar(1024),"
|
|
|
|
" image_cached boolean,"
|
|
|
|
" user_json text,"
|
|
|
|
" UNIQUE(user_id) ON CONFLICT REPLACE"
|
|
|
|
")"];
|
|
|
|
[db executeUpdate:createUsersTable];
|
|
|
|
NSString *indexUsersUserId = @"CREATE INDEX IF NOT EXISTS users_user_id ON users (user_id)";
|
|
|
|
[db executeUpdate:indexUsersUserId];
|
|
|
|
|
2013-06-23 22:19:08 -07:00
|
|
|
NSError *error;
|
|
|
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
|
|
|
NSString *storyImagesDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"story_images"];
|
|
|
|
NSString *faviconsDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"favicons"];
|
|
|
|
NSString *avatarsDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"avatars"];
|
2013-06-05 17:11:01 -07:00
|
|
|
|
2013-06-23 22:19:08 -07:00
|
|
|
if (![[NSFileManager defaultManager] fileExistsAtPath:storyImagesDirectory]) {
|
|
|
|
[[NSFileManager defaultManager] createDirectoryAtPath:storyImagesDirectory withIntermediateDirectories:NO attributes:nil error:&error];
|
|
|
|
}
|
|
|
|
if (![[NSFileManager defaultManager] fileExistsAtPath:faviconsDirectory]) {
|
|
|
|
[[NSFileManager defaultManager] createDirectoryAtPath:faviconsDirectory withIntermediateDirectories:NO attributes:nil error:&error];
|
|
|
|
}
|
|
|
|
if (![[NSFileManager defaultManager] fileExistsAtPath:avatarsDirectory]) {
|
|
|
|
[[NSFileManager defaultManager] createDirectoryAtPath:avatarsDirectory withIntermediateDirectories:NO attributes:nil error:&error];
|
|
|
|
}
|
|
|
|
|
|
|
|
NSLog(@"Create db %d: %@", [db lastErrorCode], [db lastErrorMessage]);
|
2013-05-30 18:45:51 -07:00
|
|
|
}
|
|
|
|
|
2013-07-18 18:24:38 -07:00
|
|
|
- (void)cancelOfflineQueue {
|
|
|
|
if (offlineQueue) {
|
|
|
|
[offlineQueue cancelAllOperations];
|
|
|
|
}
|
2013-08-05 18:32:43 -07:00
|
|
|
if (offlineCleaningQueue) {
|
|
|
|
[offlineCleaningQueue cancelAllOperations];
|
|
|
|
}
|
2013-07-18 18:24:38 -07:00
|
|
|
}
|
|
|
|
|
2013-07-15 18:25:09 -07:00
|
|
|
- (void)startOfflineQueue {
|
|
|
|
if (!offlineQueue) {
|
|
|
|
offlineQueue = [NSOperationQueue new];
|
|
|
|
}
|
|
|
|
offlineQueue.name = @"Offline Queue";
|
2013-09-25 17:43:00 -07:00
|
|
|
NSLog(@"Operation queue: %lu", (unsigned long)offlineQueue.operationCount);
|
2013-07-15 18:25:09 -07:00
|
|
|
[offlineQueue cancelAllOperations];
|
|
|
|
[offlineQueue setMaxConcurrentOperationCount:1];
|
|
|
|
OfflineSyncUnreads *operationSyncUnreads = [[OfflineSyncUnreads alloc] init];
|
|
|
|
|
|
|
|
[offlineQueue addOperation:operationSyncUnreads];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)startOfflineFetchStories {
|
|
|
|
OfflineFetchStories *operationFetchStories = [[OfflineFetchStories alloc] init];
|
|
|
|
|
|
|
|
[offlineQueue addOperation:operationFetchStories];
|
2013-07-16 18:06:36 -07:00
|
|
|
|
|
|
|
NSLog(@"Done start offline fetch stories");
|
2013-07-15 18:25:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)startOfflineFetchImages {
|
|
|
|
OfflineFetchImages *operationFetchImages = [[OfflineFetchImages alloc] init];
|
|
|
|
|
|
|
|
[offlineQueue addOperation:operationFetchImages];
|
|
|
|
}
|
|
|
|
|
2013-09-04 15:56:37 -07:00
|
|
|
- (BOOL)isReachabileForOffline {
|
|
|
|
Reachability *reachability = [Reachability reachabilityForInternetConnection];
|
|
|
|
NetworkStatus remoteHostStatus = [reachability currentReachabilityStatus];
|
|
|
|
|
|
|
|
NSString *connection = [[NSUserDefaults standardUserDefaults]
|
|
|
|
stringForKey:@"offline_download_connection"];
|
|
|
|
|
|
|
|
NSLog(@"Reachable via: %d / %d", remoteHostStatus == ReachableViaWWAN, remoteHostStatus == ReachableViaWiFi);
|
|
|
|
if ([connection isEqualToString:@"wifi"] && remoteHostStatus != ReachableViaWiFi) {
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
return YES;
|
|
|
|
}
|
2013-07-15 18:25:09 -07:00
|
|
|
|
2013-09-05 16:34:39 -07:00
|
|
|
- (void)storeUserProfiles:(NSArray *)userProfiles {
|
|
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
|
|
|
|
(unsigned long)NULL), ^(void) {
|
|
|
|
[self.database inTransaction:^(FMDatabase *db, BOOL *rollback) {
|
|
|
|
for (NSDictionary *user in userProfiles) {
|
|
|
|
[db executeUpdate:@"INSERT INTO users "
|
|
|
|
"(user_id, username, location, image_url, user_json) VALUES "
|
|
|
|
"(?, ?, ?, ?, ?)",
|
|
|
|
[user objectForKey:@"user_id"],
|
|
|
|
[user objectForKey:@"username"],
|
|
|
|
[user objectForKey:@"location"],
|
|
|
|
[user objectForKey:@"photo_url"],
|
|
|
|
[user JSONRepresentation]
|
|
|
|
];
|
|
|
|
}
|
|
|
|
}];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2013-08-06 18:08:55 -07:00
|
|
|
- (void)queueReadStories:(NSDictionary *)feedsStories {
|
2013-09-05 16:34:39 -07:00
|
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
|
|
|
|
(unsigned long)NULL), ^(void) {
|
|
|
|
[self.database inTransaction:^(FMDatabase *db, BOOL *rollback) {
|
|
|
|
for (NSString *feedIdStr in [feedsStories allKeys]) {
|
|
|
|
for (NSString *storyHash in [feedsStories objectForKey:feedIdStr]) {
|
|
|
|
[db executeUpdate:@"INSERT INTO queued_read_hashes "
|
|
|
|
"(story_feed_id, story_hash) VALUES "
|
|
|
|
"(?, ?)", feedIdStr, storyHash];
|
|
|
|
}
|
2013-08-06 18:08:55 -07:00
|
|
|
}
|
2013-09-05 16:34:39 -07:00
|
|
|
}];
|
|
|
|
});
|
2013-08-06 18:08:55 -07:00
|
|
|
self.hasQueuedReadStories = YES;
|
|
|
|
}
|
|
|
|
|
2013-06-21 22:18:54 -07:00
|
|
|
- (void)flushQueuedReadStories:(BOOL)forceCheck withCallback:(void(^)())callback {
|
2013-07-15 18:25:09 -07:00
|
|
|
if (self.hasQueuedReadStories || forceCheck) {
|
2013-08-05 18:32:43 -07:00
|
|
|
OfflineCleanImages *operationCleanImages = [[OfflineCleanImages alloc] init];
|
|
|
|
if (!offlineCleaningQueue) {
|
|
|
|
offlineCleaningQueue = [NSOperationQueue new];
|
|
|
|
}
|
|
|
|
[offlineCleaningQueue addOperation:operationCleanImages];
|
2013-07-31 15:23:00 -07:00
|
|
|
|
|
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
|
|
|
|
(unsigned long)NULL), ^(void) {
|
2013-06-21 22:18:54 -07:00
|
|
|
[self.database inTransaction:^(FMDatabase *db, BOOL *rollback) {
|
|
|
|
NSMutableDictionary *hashes = [NSMutableDictionary dictionary];
|
|
|
|
FMResultSet *stories = [db executeQuery:@"SELECT * FROM queued_read_hashes"];
|
|
|
|
while ([stories next]) {
|
|
|
|
NSString *storyFeedId = [NSString stringWithFormat:@"%@", [stories objectForColumnName:@"story_feed_id"]];
|
|
|
|
NSString *storyHash = [stories objectForColumnName:@"story_hash"];
|
|
|
|
if (![hashes objectForKey:storyFeedId]) {
|
|
|
|
[hashes setObject:[NSMutableArray array] forKey:storyFeedId];
|
|
|
|
}
|
|
|
|
[[hashes objectForKey:storyFeedId] addObject:storyHash];
|
|
|
|
}
|
|
|
|
|
|
|
|
if ([[hashes allKeys] count]) {
|
2013-07-15 18:25:09 -07:00
|
|
|
self.hasQueuedReadStories = NO;
|
2013-06-21 22:18:54 -07:00
|
|
|
[self syncQueuedReadStories:db withStories:hashes withCallback:callback];
|
|
|
|
} else {
|
|
|
|
if (callback) callback();
|
|
|
|
}
|
|
|
|
}];
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
if (callback) callback();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)syncQueuedReadStories:(FMDatabase *)db withStories:(NSDictionary *)hashes withCallback:(void(^)())callback {
|
|
|
|
NSString *urlString = [NSString stringWithFormat:@"%@/reader/mark_feed_stories_as_read",
|
|
|
|
NEWSBLUR_URL];
|
|
|
|
NSURL *url = [NSURL URLWithString:urlString];
|
|
|
|
NSMutableArray *completedHashes = [NSMutableArray array];
|
|
|
|
for (NSArray *storyHashes in [hashes allValues]) {
|
|
|
|
[completedHashes addObjectsFromArray:storyHashes];
|
|
|
|
}
|
|
|
|
NSString *completedHashesStr = [completedHashes componentsJoinedByString:@"\",\""];
|
|
|
|
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
|
2013-08-06 18:08:55 -07:00
|
|
|
__weak ASIHTTPRequest *_request = request;
|
2013-06-21 22:18:54 -07:00
|
|
|
[request setPostValue:[hashes JSONRepresentation] forKey:@"feeds_stories"];
|
|
|
|
[request setDelegate:self];
|
|
|
|
[request setCompletionBlock:^{
|
2013-08-06 18:08:55 -07:00
|
|
|
if ([_request responseStatusCode] == 200) {
|
|
|
|
NSLog(@"Completed clearing %@ hashes", completedHashesStr);
|
|
|
|
[db executeUpdate:[NSString stringWithFormat:@"DELETE FROM queued_read_hashes "
|
|
|
|
"WHERE story_hash in (\"%@\")", completedHashesStr]];
|
|
|
|
} else {
|
|
|
|
NSLog(@"Failed mark read queued.");
|
|
|
|
self.hasQueuedReadStories = YES;
|
|
|
|
}
|
2013-06-21 22:18:54 -07:00
|
|
|
if (callback) callback();
|
|
|
|
}];
|
|
|
|
[request setFailedBlock:^{
|
|
|
|
NSLog(@"Failed mark read queued.");
|
2013-07-15 18:25:09 -07:00
|
|
|
self.hasQueuedReadStories = YES;
|
2013-06-21 22:18:54 -07:00
|
|
|
if (callback) callback();
|
|
|
|
}];
|
|
|
|
[request startAsynchronous];
|
|
|
|
}
|
|
|
|
|
2013-07-15 18:25:09 -07:00
|
|
|
- (void)prepareActiveCachedImages:(FMDatabase *)db {
|
|
|
|
activeCachedImages = [NSMutableDictionary dictionary];
|
|
|
|
NSArray *feedIds;
|
2013-07-18 18:24:38 -07:00
|
|
|
int cached = 0;
|
2013-06-16 21:39:38 -07:00
|
|
|
|
2013-07-15 18:25:09 -07:00
|
|
|
if (isRiverView) {
|
|
|
|
feedIds = activeFolderFeeds;
|
|
|
|
} else if (activeFeed) {
|
|
|
|
feedIds = @[[activeFeed objectForKey:@"id"]];
|
2013-06-16 14:09:28 -07:00
|
|
|
}
|
2013-07-15 18:25:09 -07:00
|
|
|
NSString *sql = [NSString stringWithFormat:@"SELECT c.image_url, c.story_hash FROM cached_images c "
|
2013-07-18 18:24:38 -07:00
|
|
|
"WHERE c.image_cached = 1 AND c.failed is null AND c.story_feed_id in (%@)",
|
2013-07-15 18:25:09 -07:00
|
|
|
[feedIds componentsJoinedByString:@","]];
|
|
|
|
FMResultSet *cursor = [db executeQuery:sql];
|
2013-06-16 14:09:28 -07:00
|
|
|
|
2013-07-15 18:25:09 -07:00
|
|
|
while ([cursor next]) {
|
|
|
|
NSString *storyHash = [cursor objectForColumnName:@"story_hash"];
|
|
|
|
NSMutableArray *imageUrls;
|
|
|
|
if (![activeCachedImages objectForKey:storyHash]) {
|
|
|
|
imageUrls = [NSMutableArray array];
|
|
|
|
[activeCachedImages setObject:imageUrls forKey:storyHash];
|
2013-06-21 22:18:54 -07:00
|
|
|
} else {
|
2013-07-15 18:25:09 -07:00
|
|
|
imageUrls = [activeCachedImages objectForKey:storyHash];
|
2013-07-11 18:36:09 -07:00
|
|
|
}
|
2013-07-15 18:25:09 -07:00
|
|
|
[imageUrls addObject:[cursor objectForColumnName:@"image_url"]];
|
|
|
|
[activeCachedImages setObject:imageUrls forKey:storyHash];
|
2013-07-18 18:24:38 -07:00
|
|
|
cached++;
|
2013-06-16 08:15:40 -07:00
|
|
|
}
|
2013-06-22 19:34:12 -07:00
|
|
|
|
2013-07-18 18:24:38 -07:00
|
|
|
NSLog(@"Pre-cached %d images", cached);
|
2013-06-16 08:15:40 -07:00
|
|
|
}
|
|
|
|
|
2013-07-15 18:25:09 -07:00
|
|
|
- (void)deleteAllCachedImages {
|
|
|
|
NSFileManager *fileManager = [[NSFileManager alloc] init];
|
|
|
|
NSError *error = nil;
|
|
|
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
|
|
|
NSString *cacheDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"story_images"];
|
|
|
|
NSArray *directoryContents = [fileManager contentsOfDirectoryAtPath:cacheDirectory error:&error];
|
|
|
|
int removed = 0;
|
2013-06-23 22:19:08 -07:00
|
|
|
|
2013-07-15 18:25:09 -07:00
|
|
|
if (error == nil) {
|
|
|
|
for (NSString *path in directoryContents) {
|
|
|
|
NSString *fullPath = [cacheDirectory stringByAppendingPathComponent:path];
|
|
|
|
BOOL removeSuccess = [fileManager removeItemAtPath:fullPath error:&error];
|
|
|
|
removed++;
|
|
|
|
if (!removeSuccess) {
|
|
|
|
continue;
|
|
|
|
}
|
2013-06-26 16:22:44 -07:00
|
|
|
}
|
2013-06-23 22:19:08 -07:00
|
|
|
}
|
2013-06-26 11:38:49 -07:00
|
|
|
|
2013-07-15 18:25:09 -07:00
|
|
|
NSLog(@"Deleted %d images.", removed);
|
2013-06-23 22:19:08 -07:00
|
|
|
}
|
|
|
|
|
2012-10-07 15:47:21 -04:00
|
|
|
@end
|
|
|
|
|
2013-05-30 18:45:51 -07:00
|
|
|
#pragma mark -
|
|
|
|
#pragma mark Unread Counts
|
|
|
|
|
2012-10-07 15:47:21 -04:00
|
|
|
|
2012-10-12 15:33:40 -04:00
|
|
|
@implementation UnreadCounts
|
2012-10-07 15:47:21 -04:00
|
|
|
|
|
|
|
@synthesize ps, nt, ng;
|
|
|
|
|
|
|
|
|
|
|
|
- (id)init {
|
|
|
|
if (self = [super init]) {
|
|
|
|
ps = 0;
|
|
|
|
nt = 0;
|
|
|
|
ng = 0;
|
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2012-10-12 15:33:40 -04:00
|
|
|
- (void)addCounts:(UnreadCounts *)counts {
|
2012-10-07 15:47:21 -04:00
|
|
|
ps += counts.ps;
|
|
|
|
nt += counts.nt;
|
|
|
|
ng += counts.ng;
|
|
|
|
}
|
|
|
|
|
2012-07-12 22:05:23 -07:00
|
|
|
@end
|