Massively speeding up the viewWillAppear on the feed list.

This commit is contained in:
Samuel Clay 2013-10-17 17:23:52 -07:00
parent 6f82e716e5
commit b8b57d5df4
10 changed files with 256 additions and 178 deletions

View file

@ -20,3 +20,4 @@
- (void)informLoadingMessage:(NSString *)message; - (void)informLoadingMessage:(NSString *)message;
@end @end

View file

@ -202,7 +202,7 @@ static UIFont *indicatorFont = nil;
font = [UIFont fontWithName:@"Helvetica-Bold" size:10]; font = [UIFont fontWithName:@"Helvetica-Bold" size:10];
} }
if (cell.highlighted || cell.selected) { if (cell.highlighted || cell.selected) {
textColor = UIColorFromRGB(0x686868); textColor = UIColorFromRGB(0x959595);
} }
[cell.storyAuthor [cell.storyAuthor
@ -220,7 +220,11 @@ static UIFont *indicatorFont = nil;
} }
if (cell.highlighted || cell.selected) { if (cell.highlighted || cell.selected) {
textColor = UIColorFromRGB(0x686868); if (cell.isRead) {
textColor = UIColorFromRGB(0xaaadc1);
} else {
textColor = UIColorFromRGB(0x5a5d91);
}
} }
paragraphStyle.alignment = NSTextAlignmentRight; paragraphStyle.alignment = NSTextAlignmentRight;

View file

@ -463,7 +463,7 @@
[unreadHashCursor close]; [unreadHashCursor close];
} }
dispatch_sync(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
if (!self.isOffline) { if (!self.isOffline) {
NSLog(@"Online before offline rendered. Tossing offline stories."); NSLog(@"Online before offline rendered. Tossing offline stories.");
return; return;
@ -1506,8 +1506,10 @@
[request setUserInfo:story]; [request setUserInfo:story];
[request startAsynchronous]; [request startAsynchronous];
[appDelegate markStoryRead:[story objectForKey:@"story_hash"] if ([appDelegate.dictFeeds objectForKey:[NSString stringWithFormat:@"%@", [story objectForKey:@"story_feed_id"]]]) {
feedId:[story objectForKey:@"story_feed_id"]]; [appDelegate markStoryRead:[story objectForKey:@"story_hash"]
feedId:[story objectForKey:@"story_feed_id"]];
}
} }
- (void)finishMarkAsRead:(ASIFormDataRequest *)request { - (void)finishMarkAsRead:(ASIFormDataRequest *)request {

View file

@ -36,6 +36,7 @@
@property (nonatomic) UnreadCountView *unreadCount; @property (nonatomic) UnreadCountView *unreadCount;
- (void)setupGestures; - (void)setupGestures;
- (void)redrawUnreadCounts;
@end @end
@ -43,4 +44,6 @@
@property (nonatomic) FeedTableCell *cell; @property (nonatomic) FeedTableCell *cell;
- (void)redrawUnreadCounts;
@end @end

View file

@ -92,6 +92,10 @@ static UIFont *textFont = nil;
self.shouldAnimatesIcons = NO; self.shouldAnimatesIcons = NO;
} }
- (void)redrawUnreadCounts {
[((FeedTableCellView *)cellContent) redrawUnreadCounts];
}
@end @end
@implementation FeedTableCellView @implementation FeedTableCellView
@ -182,6 +186,12 @@ static UIFont *textFont = nil;
} }
- (void)redrawUnreadCounts {
// [cell.unreadCount drawInRect:self.frame ps:cell.positiveCount nt:cell.neutralCount
// listType:(cell.isSocial ? NBFeedListSocial : NBFeedListFeed)];
cell.unreadCount.psCount = cell.positiveCount;
cell.unreadCount.ntCount = cell.neutralCount;
[cell.unreadCount setNeedsLayout];
}
@end @end

View file

@ -193,7 +193,10 @@
// [[UISegmentedControl appearance] setBackgroundColor:UIColorFromRGB(0x8F918B)]; // [[UISegmentedControl appearance] setBackgroundColor:UIColorFromRGB(0x8F918B)];
[self createDatabaseConnection]; [self createDatabaseConnection];
[self.feedsViewController loadOfflineFeeds:NO]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
(unsigned long)NULL), ^(void) {
[self.feedsViewController loadOfflineFeeds:NO];
});
[[PocketAPI sharedAPI] setConsumerKey:@"16638-05adf4465390446398e53b8b"]; [[PocketAPI sharedAPI] setConsumerKey:@"16638-05adf4465390446398e53b8b"];
@ -646,10 +649,9 @@
} }
} }
NSDictionary *feed = nil; NSDictionary *feed = [self getFeed:feedId];
if (social) { if (social) {
feed = [self.dictSocialFeeds objectForKey:feedId];
self.isSocialView = YES; self.isSocialView = YES;
self.inFindingStoryMode = YES; self.inFindingStoryMode = YES;
@ -658,7 +660,6 @@
self.isTryFeedView = YES; self.isTryFeedView = YES;
} }
} else { } else {
feed = [self.dictFeeds objectForKey:feedId];
if (feed == nil) { if (feed == nil) {
feed = user; feed = user;
self.isTryFeedView = YES; self.isTryFeedView = YES;
@ -1571,7 +1572,7 @@
continue; continue;
} }
NSString *feedIdStr = [NSString stringWithFormat:@"%@",[story objectForKey:@"story_feed_id"]]; NSString *feedIdStr = [NSString stringWithFormat:@"%@",[story objectForKey:@"story_feed_id"]];
NSDictionary *feed = [self.dictFeeds objectForKey:feedIdStr]; NSDictionary *feed = [self getFeed:feedIdStr];
if (![feedsStories objectForKey:feedIdStr]) { if (![feedsStories objectForKey:feedIdStr]) {
[feedsStories setObject:[NSMutableArray array] forKey:feedIdStr]; [feedsStories setObject:[NSMutableArray array] forKey:feedIdStr];
} }
@ -1584,7 +1585,7 @@
- (void)markStoryRead:(NSString *)storyId feedId:(id)feedId { - (void)markStoryRead:(NSString *)storyId feedId:(id)feedId {
NSString *feedIdStr = [NSString stringWithFormat:@"%@",feedId]; NSString *feedIdStr = [NSString stringWithFormat:@"%@",feedId];
NSDictionary *feed = [self.dictFeeds objectForKey:feedIdStr]; NSDictionary *feed = [self getFeed:feedIdStr];
NSDictionary *story = nil; NSDictionary *story = nil;
for (NSDictionary *s in self.activeFeedStories) { for (NSDictionary *s in self.activeFeedStories) {
if ([[s objectForKey:@"story_hash"] isEqualToString:storyId]) { if ([[s objectForKey:@"story_hash"] isEqualToString:storyId]) {
@ -1671,7 +1672,7 @@
- (void)markStoryUnread:(NSString *)storyId feedId:(id)feedId { - (void)markStoryUnread:(NSString *)storyId feedId:(id)feedId {
NSString *feedIdStr = [NSString stringWithFormat:@"%@",feedId]; NSString *feedIdStr = [NSString stringWithFormat:@"%@",feedId];
NSDictionary *feed = [self.dictFeeds objectForKey:feedIdStr]; NSDictionary *feed = [self getFeed:feedIdStr];
NSDictionary *story = nil; NSDictionary *story = nil;
for (NSDictionary *s in self.activeFeedStories) { for (NSDictionary *s in self.activeFeedStories) {
if ([[s objectForKey:@"story_hash"] isEqualToString:storyId]) { if ([[s objectForKey:@"story_hash"] isEqualToString:storyId]) {

View file

@ -19,7 +19,7 @@
@class NewsBlurAppDelegate; @class NewsBlurAppDelegate;
@interface NewsBlurViewController : BaseViewController @interface NewsBlurViewController : BaseViewController
<UITableViewDelegate, UITableViewDataSource, <UITableViewDelegate, UITableViewDataSource,
UIAlertViewDelegate, PullToRefreshViewDelegate, UIAlertViewDelegate, PullToRefreshViewDelegate,
ASIHTTPRequestDelegate, NSCacheDelegate, ASIHTTPRequestDelegate, NSCacheDelegate,
@ -64,6 +64,12 @@ UIActionSheetDelegate> {
@property (nonatomic) IBOutlet UIBarButtonItem * addBarButton; @property (nonatomic) IBOutlet UIBarButtonItem * addBarButton;
@property (nonatomic) IBOutlet UIBarButtonItem * settingsBarButton; @property (nonatomic) IBOutlet UIBarButtonItem * settingsBarButton;
@property (nonatomic) IBOutlet UIBarButtonItem * activitiesButton; @property (nonatomic) IBOutlet UIBarButtonItem * activitiesButton;
@property (nonatomic) IBOutlet UIBarButtonItem *userInfoBarButton;
@property (nonatomic) IBOutlet UIBarButtonItem *userAvatarButton;
@property (nonatomic) IBOutlet UILabel *neutralCount;
@property (nonatomic) IBOutlet UILabel *positiveCount;
@property (nonatomic) IBOutlet UILabel *userLabel;
@property (nonatomic) IBOutlet UIImageView *greenIcon;
@property (nonatomic) NSMutableDictionary *activeFeedLocations; @property (nonatomic) NSMutableDictionary *activeFeedLocations;
@property (nonatomic) NSMutableDictionary *stillVisibleFeeds; @property (nonatomic) NSMutableDictionary *stillVisibleFeeds;
@property (nonatomic) NSMutableDictionary *visibleFolders; @property (nonatomic) NSMutableDictionary *visibleFolders;
@ -75,6 +81,7 @@ UIActionSheetDelegate> {
@property (nonatomic) IBOutlet UISegmentedControl * intelligenceControl; @property (nonatomic) IBOutlet UISegmentedControl * intelligenceControl;
@property (nonatomic, retain) WEPopoverController *popoverController; @property (nonatomic, retain) WEPopoverController *popoverController;
@property (nonatomic) NSIndexPath *currentRowAtIndexPath; @property (nonatomic) NSIndexPath *currentRowAtIndexPath;
@property (nonatomic) NSInteger currentSection;
@property (strong, nonatomic) IBOutlet UIView *noFocusMessage; @property (strong, nonatomic) IBOutlet UIView *noFocusMessage;
@property (strong, nonatomic) IBOutlet UIBarButtonItem *toolbarLeftMargin; @property (strong, nonatomic) IBOutlet UIBarButtonItem *toolbarLeftMargin;
@property (nonatomic, retain) NBNotifier *notifier; @property (nonatomic, retain) NBNotifier *notifier;
@ -118,8 +125,8 @@ UIActionSheetDelegate> {
- (IBAction)tapAddSite:(id)sender; - (IBAction)tapAddSite:(id)sender;
- (void)resetToolbar; - (void)resetToolbar;
- (void)layoutHeaderCounts:(UIInterfaceOrientation)orientation;
- (void)refreshHeaderCounts; - (void)refreshHeaderCounts;
- (void)refreshHeaderCounts:(UIInterfaceOrientation)orientation;
- (void)settingsViewControllerDidEnd:(IASKAppSettingsViewController*)sender; - (void)settingsViewControllerDidEnd:(IASKAppSettingsViewController*)sender;
- (void)settingDidChange:(NSNotification*)notification; - (void)settingDidChange:(NSNotification*)notification;

View file

@ -67,6 +67,7 @@ static const CGFloat kFolderTitleHeight = 28.0f;
@synthesize imageCache; @synthesize imageCache;
@synthesize popoverController; @synthesize popoverController;
@synthesize currentRowAtIndexPath; @synthesize currentRowAtIndexPath;
@synthesize currentSection;
@synthesize noFocusMessage; @synthesize noFocusMessage;
@synthesize toolbarLeftMargin; @synthesize toolbarLeftMargin;
@synthesize updatedDictFeeds_; @synthesize updatedDictFeeds_;
@ -75,6 +76,12 @@ static const CGFloat kFolderTitleHeight = 28.0f;
@synthesize addBarButton; @synthesize addBarButton;
@synthesize settingsBarButton; @synthesize settingsBarButton;
@synthesize activitiesButton; @synthesize activitiesButton;
@synthesize userAvatarButton;
@synthesize userInfoBarButton;
@synthesize neutralCount;
@synthesize positiveCount;
@synthesize userLabel;
@synthesize greenIcon;
@synthesize notifier; @synthesize notifier;
@synthesize isOffline; @synthesize isOffline;
@ -144,13 +151,23 @@ static const CGFloat kFolderTitleHeight = 28.0f;
inView:self.view inView:self.view
withOffset:CGPointMake(0, self.feedViewToolbar.frame.size.height)]; withOffset:CGPointMake(0, self.feedViewToolbar.frame.size.height)];
[self.view insertSubview:self.notifier belowSubview:self.feedViewToolbar]; [self.view insertSubview:self.notifier belowSubview:self.feedViewToolbar];
UIColor *bgColor = [UIColor colorWithRed:0.95 green:0.95 blue:0.95 alpha:1.0];
self.feedTitlesTable.backgroundColor = bgColor;
self.feedTitlesTable.separatorColor = [UIColor clearColor];
[self layoutHeaderCounts:nil];
userAvatarButton.customView.hidden = YES;
userInfoBarButton.customView.hidden = YES;
} }
- (void)viewWillAppear:(BOOL)animated { - (void)viewWillAppear:(BOOL)animated {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[appDelegate.masterContainerViewController transitionFromFeedDetail]; [appDelegate.masterContainerViewController transitionFromFeedDetail];
} }
NSDate *start = [NSDate date];
NSLog(@"Feed List timing 0: %f", (double)[start timeIntervalSinceNow] * -1000.0);
[super viewWillAppear:animated]; [super viewWillAppear:animated];
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults]; NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
@ -170,39 +187,28 @@ static const CGFloat kFolderTitleHeight = 28.0f;
[appDelegate setSelectedIntelligence:0]; [appDelegate setSelectedIntelligence:0];
} }
// self.feedTitlesTable.separatorStyle = UITableViewCellSeparatorStyleNone; // DO NOT USE. THIS BREAKS SHIT.
UIColor *bgColor = [UIColor colorWithRed:0.95 green:0.95 blue:0.95 alpha:1.0];
self.feedTitlesTable.backgroundColor = bgColor;
self.feedTitlesTable.separatorColor = [UIColor clearColor];
[MBProgressHUD hideHUDForView:appDelegate.storyPageControl.view animated:NO]; [MBProgressHUD hideHUDForView:appDelegate.storyPageControl.view animated:NO];
if (appDelegate.activeFeed || appDelegate.isRiverView) { NSLog(@"Feed List timing 1: %f", (double)[start timeIntervalSinceNow] * -1000.0);
NSInteger previousLevel = [self.intelligenceControl selectedSegmentIndex] - 1;
NSInteger newLevel = [appDelegate selectedIntelligence];
if (newLevel != previousLevel) {
[appDelegate setSelectedIntelligence:newLevel];
[self calculateFeedLocations];
[self.feedTitlesTable beginUpdates];
[self.feedTitlesTable endUpdates];
[self redrawUnreadCounts];
}
}
// perform these only if coming from the feed detail view // perform these only if coming from the feed detail view
if (appDelegate.inFeedDetail) { if (appDelegate.inFeedDetail) {
appDelegate.inFeedDetail = NO; appDelegate.inFeedDetail = NO;
// reload the data and then set the highlight again // reload the data and then set the highlight again
[self.feedTitlesTable reloadData]; // [self.feedTitlesTable reloadData];
NSLog(@"Feed List timing 1a: %f", (double)[start timeIntervalSinceNow] * -1000.0);
[self refreshHeaderCounts]; [self refreshHeaderCounts];
NSLog(@"Feed List timing 1b: %f", (double)[start timeIntervalSinceNow] * -1000.0);
[self redrawUnreadCounts]; [self redrawUnreadCounts];
[self.feedTitlesTable selectRowAtIndexPath:self.currentRowAtIndexPath NSLog(@"Feed List timing 1c: %f", (double)[start timeIntervalSinceNow] * -1000.0);
animated:NO // [self.feedTitlesTable selectRowAtIndexPath:self.currentRowAtIndexPath
scrollPosition:UITableViewScrollPositionNone]; // animated:NO
// scrollPosition:UITableViewScrollPositionNone];
NSLog(@"Feed List timing 1d: %f", (double)[start timeIntervalSinceNow] * -1000.0);
[self.notifier setNeedsLayout]; [self.notifier setNeedsLayout];
NSLog(@"Feed List timing 1e: %f", (double)[start timeIntervalSinceNow] * -1000.0);
} }
NSLog(@"Feed List timing 2: %f", (double)[start timeIntervalSinceNow] * -1000.0);
} }
- (void)viewDidAppear:(BOOL)animated { - (void)viewDidAppear:(BOOL)animated {
@ -240,7 +246,6 @@ static const CGFloat kFolderTitleHeight = 28.0f;
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration { duration:(NSTimeInterval)duration {
[self layoutForInterfaceOrientation:toInterfaceOrientation]; [self layoutForInterfaceOrientation:toInterfaceOrientation];
[self refreshHeaderCounts:toInterfaceOrientation];
} }
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
@ -255,15 +260,15 @@ static const CGFloat kFolderTitleHeight = 28.0f;
} }
- (void)layoutForInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { - (void)layoutForInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
CGSize toolbarSize = [self.feedViewToolbar sizeThatFits:self.view.bounds.size]; CGSize toolbarSize = [self.feedViewToolbar sizeThatFits:self.view.frame.size];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
self.feedViewToolbar.frame = CGRectMake(-10.0f, self.feedViewToolbar.frame = CGRectMake(-10.0f,
CGRectGetHeight(self.view.bounds) - toolbarSize.height, CGRectGetHeight(self.view.frame) - toolbarSize.height,
toolbarSize.width + 20, toolbarSize.height); toolbarSize.width + 20, toolbarSize.height);
} else { } else {
self.feedViewToolbar.frame = (CGRect){CGPointMake(0.f, CGRectGetHeight(self.view.bounds) - toolbarSize.height), toolbarSize}; self.feedViewToolbar.frame = (CGRect){CGPointMake(0.f, CGRectGetHeight(self.view.frame) - toolbarSize.height), toolbarSize};
} }
self.innerView.frame = (CGRect){CGPointZero, CGSizeMake(CGRectGetWidth(self.view.bounds), CGRectGetMinY(self.feedViewToolbar.frame))}; self.innerView.frame = (CGRect){CGPointZero, CGSizeMake(CGRectGetWidth(self.view.frame), CGRectGetMinY(self.feedViewToolbar.frame))};
self.notifier.offset = CGPointMake(0, self.feedViewToolbar.frame.size.height); self.notifier.offset = CGPointMake(0, self.feedViewToolbar.frame.size.height);
int height = 16; int height = 16;
@ -277,7 +282,8 @@ static const CGFloat kFolderTitleHeight = 28.0f;
self.intelligenceControl.frame.size.width, self.intelligenceControl.frame.size.width,
self.feedViewToolbar.frame.size.height - self.feedViewToolbar.frame.size.height -
height); height);
[self refreshHeaderCounts:interfaceOrientation]; [self layoutHeaderCounts:interfaceOrientation];
[self refreshHeaderCounts];
} }
@ -367,35 +373,40 @@ static const CGFloat kFolderTitleHeight = 28.0f;
appDelegate.activeUsername = [results objectForKey:@"user"]; appDelegate.activeUsername = [results objectForKey:@"user"];
[appDelegate.database inTransaction:^(FMDatabase *db, BOOL *rollback) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
[db executeUpdate:@"DELETE FROM accounts WHERE username = ?", appDelegate.activeUsername]; (unsigned long)NULL), ^(void) {
[db executeUpdate:@"INSERT INTO accounts" [appDelegate.database inTransaction:^(FMDatabase *db, BOOL *rollback) {
"(username, download_date, feeds_json) VALUES " [db executeUpdate:@"DELETE FROM accounts WHERE username = ?", appDelegate.activeUsername];
"(?, ?, ?)", [db executeUpdate:@"INSERT INTO accounts"
appDelegate.activeUsername, "(username, download_date, feeds_json) VALUES "
[NSDate date], "(?, ?, ?)",
[results JSONRepresentation] appDelegate.activeUsername,
]; [NSDate date],
for (NSDictionary *feed in [results objectForKey:@"social_feeds"]) { [results JSONRepresentation]
[db executeUpdate:@"INSERT INTO unread_counts (feed_id, ps, nt, ng) VALUES " ];
"(?, ?, ?, ?)", for (NSDictionary *feed in [results objectForKey:@"social_feeds"]) {
[feed objectForKey:@"id"], [db executeUpdate:@"INSERT INTO unread_counts (feed_id, ps, nt, ng) VALUES "
[feed objectForKey:@"ps"], "(?, ?, ?, ?)",
[feed objectForKey:@"nt"], [feed objectForKey:@"id"],
[feed objectForKey:@"ng"]]; [feed objectForKey:@"ps"],
} [feed objectForKey:@"nt"],
for (NSString *feedId in [results objectForKey:@"feeds"]) { [feed objectForKey:@"ng"]];
NSDictionary *feed = [[results objectForKey:@"feeds"] objectForKey:feedId]; }
[db executeUpdate:@"INSERT INTO unread_counts (feed_id, ps, nt, ng) VALUES " for (NSString *feedId in [results objectForKey:@"feeds"]) {
"(?, ?, ?, ?)", NSDictionary *feed = [[results objectForKey:@"feeds"] objectForKey:feedId];
[feed objectForKey:@"id"], [db executeUpdate:@"INSERT INTO unread_counts (feed_id, ps, nt, ng) VALUES "
[feed objectForKey:@"ps"], "(?, ?, ?, ?)",
[feed objectForKey:@"nt"], [feed objectForKey:@"id"],
[feed objectForKey:@"ng"]]; [feed objectForKey:@"ps"],
} [feed objectForKey:@"nt"],
}]; [feed objectForKey:@"ng"]];
}
}];
dispatch_async(dispatch_get_main_queue(), ^{
[self finishLoadingFeedListWithDict:results];
});
});
[self finishLoadingFeedListWithDict:results];
} }
- (void)finishLoadingFeedListWithDict:(NSDictionary *)results { - (void)finishLoadingFeedListWithDict:(NSDictionary *)results {
@ -616,7 +627,7 @@ static const CGFloat kFolderTitleHeight = 28.0f;
[self showSyncingNotifier]; [self showSyncingNotifier];
[self.appDelegate flushQueuedReadStories:YES withCallback:^{ [self.appDelegate flushQueuedReadStories:YES withCallback:^{
[self refreshFeedList]; [self refreshFeedList];
[self.appDelegate startOfflineQueue]; // [self.appDelegate startOfflineQueue];
}]; }];
} else { } else {
[self showSyncingNotifier]; [self showSyncingNotifier];
@ -629,6 +640,8 @@ static const CGFloat kFolderTitleHeight = 28.0f;
self.intelligenceControl.hidden = NO; self.intelligenceControl.hidden = NO;
[self showExplainerOnEmptyFeedlist]; [self showExplainerOnEmptyFeedlist];
[self layoutHeaderCounts:nil];
[self refreshHeaderCounts];
} }
@ -643,7 +656,9 @@ static const CGFloat kFolderTitleHeight = 28.0f;
if (failed) { if (failed) {
return; return;
} else { } else {
[self fetchFeedList:YES]; dispatch_async(dispatch_get_main_queue(), ^{
[self fetchFeedList:YES];
});
return; return;
} }
} }
@ -964,6 +979,7 @@ static const CGFloat kFolderTitleHeight = 28.0f;
// set the current row pointer // set the current row pointer
self.currentRowAtIndexPath = indexPath; self.currentRowAtIndexPath = indexPath;
self.currentSection = nil;
NSString *folderName; NSString *folderName;
if (indexPath.section == 0) { if (indexPath.section == 0) {
@ -1051,7 +1067,7 @@ static const CGFloat kFolderTitleHeight = 28.0f;
- (UIView *)tableView:(UITableView *)tableView - (UIView *)tableView:(UITableView *)tableView
viewForHeaderInSection:(NSInteger)section { viewForHeaderInSection:(NSInteger)section {
CGRect rect = CGRectMake(0.0, 0.0, tableView.bounds.size.width, kFolderTitleHeight); CGRect rect = CGRectMake(0.0, 0.0, tableView.frame.size.width, kFolderTitleHeight);
FolderTitleView *folderTitle = [[FolderTitleView alloc] initWithFrame:rect]; FolderTitleView *folderTitle = [[FolderTitleView alloc] initWithFrame:rect];
folderTitle.section = section; folderTitle.section = section;
@ -1090,6 +1106,7 @@ heightForHeaderInSection:(NSInteger)section {
- (void)didSelectSectionHeader:(UIButton *)button { - (void)didSelectSectionHeader:(UIButton *)button {
// reset pointer to the cells // reset pointer to the cells
self.currentRowAtIndexPath = nil; self.currentRowAtIndexPath = nil;
self.currentSection = button.tag;
appDelegate.readStories = [NSMutableArray array]; appDelegate.readStories = [NSMutableArray array];
@ -1420,13 +1437,18 @@ heightForHeaderInSection:(NSInteger)section {
} }
- (void)redrawUnreadCounts { - (void)redrawUnreadCounts {
for (UITableViewCell *cell in self.feedTitlesTable.visibleCells) { FeedTableCell *cell = (FeedTableCell *)[self.feedTitlesTable
[cell setNeedsDisplay]; cellForRowAtIndexPath:self.currentRowAtIndexPath];
} if (cell) {
for (UIView *view in self.feedTitlesTable.subviews) { NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:self.currentRowAtIndexPath.section];
if ([view class] == [FolderTitleView class]) { id feedId = [[appDelegate.dictFolders objectForKey:folderName] objectAtIndex:self.currentRowAtIndexPath.row];
[view setNeedsDisplay]; NSString *feedIdStr = [NSString stringWithFormat:@"%@",feedId];
} NSDictionary *unreadCounts = [appDelegate.dictUnreadCounts objectForKey:feedIdStr];
cell.positiveCount = [[unreadCounts objectForKey:@"ps"] intValue];
cell.neutralCount = [[unreadCounts objectForKey:@"nt"] intValue];
cell.negativeCount = [[unreadCounts objectForKey:@"ng"] intValue];
} else {
[self.feedTitlesTable reloadData];
} }
} }
@ -1598,75 +1620,80 @@ heightForHeaderInSection:(NSInteger)section {
[pull finishedLoading]; [pull finishedLoading];
return [self informError:@"The server barfed!"]; return [self informError:@"The server barfed!"];
} }
NSString *responseString = [request responseString];
NSData *responseData=[responseString dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
NSDictionary *results = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
NSDictionary *newFeedCounts = [results objectForKey:@"feeds"]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
NSInteger intelligenceLevel = [appDelegate selectedIntelligence]; (unsigned long)NULL), ^(void) {
for (id feed in newFeedCounts) { NSString *responseString = [request responseString];
NSString *feedIdStr = [NSString stringWithFormat:@"%@", feed]; NSData *responseData=[responseString dataUsingEncoding:NSUTF8StringEncoding];
NSMutableDictionary *unreadCount = [[appDelegate.dictUnreadCounts objectForKey:feedIdStr] mutableCopy]; NSError *error;
NSMutableDictionary *newFeedCount = [newFeedCounts objectForKey:feed]; NSDictionary *results = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
NSDictionary *newFeedCounts = [results objectForKey:@"feeds"];
NSInteger intelligenceLevel = [appDelegate selectedIntelligence];
for (id feed in newFeedCounts) {
NSString *feedIdStr = [NSString stringWithFormat:@"%@", feed];
NSMutableDictionary *unreadCount = [[appDelegate.dictUnreadCounts objectForKey:feedIdStr] mutableCopy];
NSMutableDictionary *newFeedCount = [newFeedCounts objectForKey:feed];
if (![unreadCount isKindOfClass:[NSDictionary class]]) continue; if (![unreadCount isKindOfClass:[NSDictionary class]]) continue;
// Check if a feed goes from visible to hidden, but doesn't disappear. // Check if a feed goes from visible to hidden, but doesn't disappear.
if ((intelligenceLevel > 0 && if ((intelligenceLevel > 0 &&
[[unreadCount objectForKey:@"ps"] intValue] > 0 && [[unreadCount objectForKey:@"ps"] intValue] > 0 &&
[[newFeedCount objectForKey:@"ps"] intValue] == 0) || [[newFeedCount objectForKey:@"ps"] intValue] == 0) ||
(intelligenceLevel == 0 && (intelligenceLevel == 0 &&
([[unreadCount objectForKey:@"ps"] intValue] > 0 || ([[unreadCount objectForKey:@"ps"] intValue] > 0 ||
[[unreadCount objectForKey:@"nt"] intValue] > 0) && [[unreadCount objectForKey:@"nt"] intValue] > 0) &&
[[newFeedCount objectForKey:@"ps"] intValue] == 0 && [[newFeedCount objectForKey:@"ps"] intValue] == 0 &&
[[newFeedCount objectForKey:@"nt"] intValue] == 0)) { [[newFeedCount objectForKey:@"nt"] intValue] == 0)) {
NSIndexPath *indexPath; NSIndexPath *indexPath;
for (int s=0; s < [appDelegate.dictFoldersArray count]; s++) { for (int s=0; s < [appDelegate.dictFoldersArray count]; s++) {
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:s]; NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:s];
NSArray *activeFolderFeeds = [self.activeFeedLocations objectForKey:folderName]; NSArray *activeFolderFeeds = [self.activeFeedLocations objectForKey:folderName];
NSArray *originalFolder = [appDelegate.dictFolders objectForKey:folderName]; NSArray *originalFolder = [appDelegate.dictFolders objectForKey:folderName];
for (int l=0; l < [activeFolderFeeds count]; l++) { for (int l=0; l < [activeFolderFeeds count]; l++) {
if ([[originalFolder objectAtIndex:[[activeFolderFeeds objectAtIndex:l] intValue]] intValue] == [feed intValue]) { if ([[originalFolder objectAtIndex:[[activeFolderFeeds objectAtIndex:l] intValue]] intValue] == [feed intValue]) {
indexPath = [NSIndexPath indexPathForRow:l inSection:s]; indexPath = [NSIndexPath indexPathForRow:l inSection:s];
break; break;
}
} }
if (indexPath) break;
}
if (indexPath) {
[self.stillVisibleFeeds setObject:indexPath forKey:feedIdStr];
} }
if (indexPath) break;
}
if (indexPath) {
[self.stillVisibleFeeds setObject:indexPath forKey:feedIdStr];
} }
[unreadCount setObject:[newFeedCount objectForKey:@"ng"] forKey:@"ng"];
[unreadCount setObject:[newFeedCount objectForKey:@"nt"] forKey:@"nt"];
[unreadCount setObject:[newFeedCount objectForKey:@"ps"] forKey:@"ps"];
[appDelegate.dictUnreadCounts setObject:unreadCount forKey:feedIdStr];
} }
[unreadCount setObject:[newFeedCount objectForKey:@"ng"] forKey:@"ng"];
[unreadCount setObject:[newFeedCount objectForKey:@"nt"] forKey:@"nt"]; NSDictionary *newSocialFeedCounts = [results objectForKey:@"social_feeds"];
[unreadCount setObject:[newFeedCount objectForKey:@"ps"] forKey:@"ps"]; for (id feed in newSocialFeedCounts) {
[appDelegate.dictUnreadCounts setObject:unreadCount forKey:feedIdStr]; NSString *feedIdStr = [NSString stringWithFormat:@"%@", feed];
} NSMutableDictionary *unreadCount = [[appDelegate.dictUnreadCounts objectForKey:feedIdStr] mutableCopy];
NSMutableDictionary *newFeedCount = [newSocialFeedCounts objectForKey:feed];
NSDictionary *newSocialFeedCounts = [results objectForKey:@"social_feeds"];
for (id feed in newSocialFeedCounts) {
NSString *feedIdStr = [NSString stringWithFormat:@"%@", feed];
NSMutableDictionary *unreadCount = [[appDelegate.dictUnreadCounts objectForKey:feedIdStr] mutableCopy];
NSMutableDictionary *newFeedCount = [newSocialFeedCounts objectForKey:feed];
if (![unreadCount isKindOfClass:[NSDictionary class]]) continue; if (![unreadCount isKindOfClass:[NSDictionary class]]) continue;
[unreadCount setObject:[newFeedCount objectForKey:@"ng"] forKey:@"ng"]; [unreadCount setObject:[newFeedCount objectForKey:@"ng"] forKey:@"ng"];
[unreadCount setObject:[newFeedCount objectForKey:@"nt"] forKey:@"nt"]; [unreadCount setObject:[newFeedCount objectForKey:@"nt"] forKey:@"nt"];
[unreadCount setObject:[newFeedCount objectForKey:@"ps"] forKey:@"ps"]; [unreadCount setObject:[newFeedCount objectForKey:@"ps"] forKey:@"ps"];
[appDelegate.dictUnreadCounts setObject:unreadCount forKey:feedIdStr]; [appDelegate.dictUnreadCounts setObject:unreadCount forKey:feedIdStr];
} }
[appDelegate.folderCountCache removeAllObjects]; dispatch_async(dispatch_get_main_queue(), ^{
[self.feedTitlesTable reloadData]; [appDelegate.folderCountCache removeAllObjects];
[self refreshHeaderCounts]; [self.feedTitlesTable reloadData];
if (![request.userInfo objectForKey:@"feedId"]) { [self refreshHeaderCounts];
[self.appDelegate startOfflineQueue]; if (![request.userInfo objectForKey:@"feedId"]) {
} [self.appDelegate startOfflineQueue];
}
});
});
} }
// called when the date shown needs to be updated, optional // called when the date shown needs to be updated, optional
@ -1732,20 +1759,17 @@ heightForHeaderInSection:(NSInteger)section {
self.navigationItem.rightBarButtonItem = nil; self.navigationItem.rightBarButtonItem = nil;
} }
- (void)refreshHeaderCounts { - (void)layoutHeaderCounts:(UIInterfaceOrientation)orientation {
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; if (!orientation) {
[self refreshHeaderCounts:orientation]; orientation = [UIApplication sharedApplication].statusBarOrientation;
} }
- (void)refreshHeaderCounts:(UIInterfaceOrientation)orientation {
if (!appDelegate.activeUsername) return;
BOOL isShort = NO; BOOL isShort = NO;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone && if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone &&
UIInterfaceOrientationIsLandscape(orientation)) { UIInterfaceOrientationIsLandscape(orientation)) {
isShort = YES; isShort = YES;
} }
int yOffset = isShort ? 0 : 6; int yOffset = isShort ? 0 : 6;
UIView *userInfoView = [[UIView alloc] UIView *userInfoView = [[UIView alloc]
initWithFrame:CGRectMake(0, 0, initWithFrame:CGRectMake(0, 0,
@ -1755,9 +1779,9 @@ heightForHeaderInSection:(NSInteger)section {
NSURL *imageURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@", NSURL *imageURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@",
[appDelegate.dictSocialProfile [appDelegate.dictSocialProfile
objectForKey:@"photo_url"]]]; objectForKey:@"photo_url"]]];
UIBarButtonItem *userAvatarButton = [UIBarButtonItem barItemWithImage:[UIImage alloc] userAvatarButton = [UIBarButtonItem barItemWithImage:[UIImage alloc]
target:self target:self
action:@selector(showUserProfile)]; action:@selector(showUserProfile)];
userAvatarButton.customView.frame = CGRectMake(0, yOffset + 1, isShort ? 28 : 32, isShort ? 28 : 32); userAvatarButton.customView.frame = CGRectMake(0, yOffset + 1, isShort ? 28 : 32, isShort ? 28 : 32);
NSMutableURLRequest *avatarRequest = [NSMutableURLRequest requestWithURL:imageURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0]; NSMutableURLRequest *avatarRequest = [NSMutableURLRequest requestWithURL:imageURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];
@ -1769,10 +1793,10 @@ heightForHeaderInSection:(NSInteger)section {
[(UIButton *)userAvatarButton.customView setImage:image forState:UIControlStateNormal]; [(UIButton *)userAvatarButton.customView setImage:image forState:UIControlStateNormal];
} failure:nil]; } failure:nil];
// self.navigationItem.leftBarButtonItem = userInfoBarButton; // self.navigationItem.leftBarButtonItem = userInfoBarButton;
// [userInfoView addSubview:userAvatarButton];
UILabel *userLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, yOffset, userInfoView.frame.size.width, 16)]; // [userInfoView addSubview:userAvatarButton];
userLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, yOffset, userInfoView.frame.size.width, 16)];
userLabel.text = appDelegate.activeUsername; userLabel.text = appDelegate.activeUsername;
userLabel.font = [UIFont fontWithName:@"Helvetica-Bold" size:14.0]; userLabel.font = [UIFont fontWithName:@"Helvetica-Bold" size:14.0];
userLabel.textColor = UIColorFromRGB(0x404040); userLabel.textColor = UIColorFromRGB(0x404040);
@ -1782,43 +1806,37 @@ heightForHeaderInSection:(NSInteger)section {
[userInfoView addSubview:userLabel]; [userInfoView addSubview:userLabel];
[appDelegate.folderCountCache removeObjectForKey:@"everything"]; [appDelegate.folderCountCache removeObjectForKey:@"everything"];
UnreadCounts *counts = [appDelegate splitUnreadCountForFolder:@"everything"];
UIImageView *yellow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"g_icn_unread"]]; UIImageView *yellow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"g_icn_unread"]];
yellow.frame = CGRectMake(0, userLabel.frame.origin.y + userLabel.frame.size.height + 4, 8, 8); yellow.frame = CGRectMake(0, userLabel.frame.origin.y + userLabel.frame.size.height + 4, 8, 8);
[userInfoView addSubview:yellow]; [userInfoView addSubview:yellow];
NSNumberFormatter *formatter = [NSNumberFormatter new]; neutralCount = [[UILabel alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
UILabel *neutralCount = [[UILabel alloc] init];
neutralCount.frame = CGRectMake(yellow.frame.size.width + yellow.frame.origin.x + 2, neutralCount.frame = CGRectMake(yellow.frame.size.width + yellow.frame.origin.x + 2,
yellow.frame.origin.y - 3, 100, 16); yellow.frame.origin.y - 3, 100, 16);
neutralCount.text = [formatter stringFromNumber:[NSNumber numberWithInt:counts.nt]];
neutralCount.font = [UIFont fontWithName:@"Helvetica" size:11]; neutralCount.font = [UIFont fontWithName:@"Helvetica" size:11];
neutralCount.textColor = UIColorFromRGB(0x707070); neutralCount.textColor = UIColorFromRGB(0x707070);
neutralCount.backgroundColor = [UIColor clearColor]; neutralCount.backgroundColor = [UIColor clearColor];
[neutralCount sizeToFit]; [neutralCount sizeToFit];
[userInfoView addSubview:neutralCount]; [userInfoView addSubview:neutralCount];
UIImageView *green = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"g_icn_focus"]]; greenIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"g_icn_focus"]];
green.frame = CGRectMake(neutralCount.frame.origin.x + neutralCount.frame.size.width + 8, greenIcon.frame = CGRectMake(neutralCount.frame.origin.x + neutralCount.frame.size.width + 8,
yellow.frame.origin.y, 8, 8); yellow.frame.origin.y, 8, 8);
[userInfoView addSubview:green]; [userInfoView addSubview:greenIcon];
UILabel *positiveCount = [[UILabel alloc] init]; positiveCount = [[UILabel alloc] init];
positiveCount.frame = CGRectMake(green.frame.size.width + green.frame.origin.x + 2, positiveCount.frame = CGRectMake(greenIcon.frame.size.width + greenIcon.frame.origin.x + 2,
green.frame.origin.y - 3, 100, 16); greenIcon.frame.origin.y - 3, 100, 16);
positiveCount.text = [formatter stringFromNumber:[NSNumber numberWithInt:counts.ps]];
positiveCount.font = [UIFont fontWithName:@"Helvetica" size:11]; positiveCount.font = [UIFont fontWithName:@"Helvetica" size:11];
positiveCount.textColor = UIColorFromRGB(0x707070); positiveCount.textColor = UIColorFromRGB(0x707070);
positiveCount.backgroundColor = [UIColor clearColor]; positiveCount.backgroundColor = [UIColor clearColor];
[positiveCount sizeToFit]; [positiveCount sizeToFit];
[userInfoView addSubview:positiveCount]; [userInfoView addSubview:positiveCount];
[userInfoView sizeToFit]; [userInfoView sizeToFit];
UIBarButtonItem *userInfoBarButton = [[UIBarButtonItem alloc] userInfoBarButton = [[UIBarButtonItem alloc]
initWithCustomView:userInfoView]; initWithCustomView:userInfoView];
UIBarButtonItem *spacer = [[UIBarButtonItem alloc] UIBarButtonItem *spacer = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil target:nil
@ -1830,6 +1848,38 @@ heightForHeaderInSection:(NSInteger)section {
userInfoBarButton, nil]; userInfoBarButton, nil];
} }
- (void)refreshHeaderCounts {
if (!appDelegate.activeUsername) {
userAvatarButton.customView.hidden = YES;
userInfoBarButton.customView.hidden = YES;
return;
}
userAvatarButton.customView.hidden = NO;
userInfoBarButton.customView.hidden = NO;
[appDelegate.folderCountCache removeObjectForKey:@"everything"];
NSNumberFormatter *formatter = [NSNumberFormatter new];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
UnreadCounts *counts = [appDelegate splitUnreadCountForFolder:@"everything"];
positiveCount.text = [formatter stringFromNumber:[NSNumber numberWithInt:counts.ps]];
CGRect yellow = CGRectMake(0, userLabel.frame.origin.y + userLabel.frame.size.height + 4, 8, 8);
neutralCount.text = [formatter stringFromNumber:[NSNumber numberWithInt:counts.nt]];
neutralCount.frame = CGRectMake(yellow.size.width + yellow.origin.x + 2,
yellow.origin.y - 3, 100, 16);
[neutralCount sizeToFit];
greenIcon.frame = CGRectMake(neutralCount.frame.origin.x + neutralCount.frame.size.width + 8,
yellow.origin.y, 8, 8);
positiveCount.frame = CGRectMake(greenIcon.frame.size.width + greenIcon.frame.origin.x + 2,
greenIcon.frame.origin.y - 3, 100, 16);
[positiveCount sizeToFit];
[userInfoBarButton.customView sizeToFit];
}
- (void)showRefreshNotifier { - (void)showRefreshNotifier {
self.notifier.style = NBSyncingStyle; self.notifier.style = NBSyncingStyle;
self.notifier.title = @"On its way..."; self.notifier.title = @"On its way...";

View file

@ -2606,7 +2606,7 @@
"-all_load", "-all_load",
); );
PRODUCT_NAME = NewsBlur; PRODUCT_NAME = NewsBlur;
PROVISIONING_PROFILE = "A0156932-124B-4F8E-8B93-EE6598D778F0"; PROVISIONING_PROFILE = "EB97D956-BB90-4F2F-9919-F71949B04B3F";
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
"WARNING_CFLAGS[arch=*]" = "-Wall"; "WARNING_CFLAGS[arch=*]" = "-Wall";
}; };
@ -2638,7 +2638,7 @@
"-all_load", "-all_load",
); );
PRODUCT_NAME = NewsBlur; PRODUCT_NAME = NewsBlur;
PROVISIONING_PROFILE = "A0156932-124B-4F8E-8B93-EE6598D778F0"; PROVISIONING_PROFILE = "EB97D956-BB90-4F2F-9919-F71949B04B3F";
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
}; };

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="4510" systemVersion="12F37" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="4510" systemVersion="12F45" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<dependencies> <dependencies>
<deployment defaultVersion="1792" identifier="iOS"/> <deployment defaultVersion="1792" identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3742"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3742"/>
@ -36,7 +36,7 @@
</connections> </connections>
</tableView> </tableView>
<view hidden="YES" opaque="NO" contentMode="scaleToFill" id="122"> <view hidden="YES" opaque="NO" contentMode="scaleToFill" id="122">
<rect key="frame" x="92.499999999999986" y="170.5" width="135" height="195"/> <rect key="frame" x="92.5" y="170.5" width="135" height="195"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<subviews> <subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="You have no unread stories in Focus mode." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="123"> <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="You have no unread stories in Focus mode." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="123">