NewsBlur/clients/ios/Classes/NewsBlurViewController.m

2175 lines
92 KiB
Mathematica
Raw Normal View History

//
2010-06-20 11:04:23 -04:00
// NewsBlurViewController.m
// NewsBlur
//
// Created by Samuel Clay on 6/16/10.
// Copyright NewsBlur 2010. All rights reserved.
//
#import "NewsBlurViewController.h"
#import "NewsBlurAppDelegate.h"
#import "NBContainerViewController.h"
2012-07-10 16:48:05 -07:00
#import "DashboardViewController.h"
#import "InteractionsModule.h"
#import "ActivityModule.h"
#import "FeedTableCell.h"
#import "DashboardViewController.h"
2012-06-19 13:51:48 -07:00
#import "FeedsMenuViewController.h"
#import "FeedDetailMenuViewController.h"
#import "FeedDetailViewController.h"
#import "UserProfileViewController.h"
2012-07-24 16:03:16 -07:00
#import "StoryDetailViewController.h"
#import "StoryPageControl.h"
#import "MBProgressHUD.h"
#import "Base64.h"
#import "SBJson4.h"
#import "NSObject+SBJSON.h"
#import "NBNotifier.h"
#import "Utilities.h"
#import "UIBarButtonItem+Image.h"
#import "AddSiteViewController.h"
#import "FMDatabase.h"
#import "FMDatabaseAdditions.h"
2013-06-21 17:48:06 -07:00
#import "IASKAppSettingsViewController.h"
#import "IASKSettingsReader.h"
#import "UIImageView+AFNetworking.h"
#import "NBBarButtonItem.h"
#import "StoriesCollection.h"
static const CGFloat kPhoneTableViewRowHeight = 6.0f;
static const CGFloat kTableViewRowHeight = 6.0f;
static const CGFloat kBlurblogTableViewRowHeight = 7.0f;
static const CGFloat kPhoneBlurblogTableViewRowHeight = 7.0f;
static const CGFloat kFolderTitleHeight = 10.0f;
2013-10-18 18:37:11 -07:00
static UIFont *userLabelFont;
2012-08-09 10:18:15 -07:00
@interface NewsBlurViewController ()
@property (nonatomic, strong) NSMutableDictionary *updatedDictSocialFeeds_;
@property (nonatomic, strong) NSMutableDictionary *updatedDictFeeds_;
2012-08-16 20:10:50 -07:00
@property (readwrite) BOOL inPullToRefresh_;
2012-08-09 10:18:15 -07:00
@end
@implementation NewsBlurViewController
@synthesize appDelegate;
@synthesize feedTitlesTable;
2010-06-20 11:04:23 -04:00
@synthesize feedViewToolbar;
@synthesize feedScoreSlider;
2012-06-19 10:55:46 -07:00
@synthesize homeButton;
@synthesize intelligenceControl;
@synthesize activeFeedLocations;
@synthesize stillVisibleFeeds;
@synthesize visibleFolders;
@synthesize viewShowingAllFeeds;
@synthesize lastUpdate;
2011-10-14 09:51:27 -07:00
@synthesize imageCache;
@synthesize currentRowAtIndexPath;
@synthesize currentSection;
2012-08-15 19:31:34 -07:00
@synthesize noFocusMessage;
@synthesize toolbarLeftMargin;
2012-08-09 10:18:15 -07:00
@synthesize updatedDictFeeds_;
@synthesize updatedDictSocialFeeds_;
2012-08-16 20:10:50 -07:00
@synthesize inPullToRefresh_;
@synthesize addBarButton;
@synthesize settingsBarButton;
@synthesize activitiesButton;
@synthesize userAvatarButton;
@synthesize userInfoBarButton;
@synthesize neutralCount;
@synthesize positiveCount;
@synthesize userLabel;
@synthesize greenIcon;
@synthesize yellowIcon;
@synthesize notifier;
@synthesize isOffline;
@synthesize interactiveFeedDetailTransition;
@synthesize avatarImageView;
2010-06-20 11:04:23 -04:00
#pragma mark -
2011-08-24 21:44:16 -07:00
#pragma mark Globals
2010-06-20 11:04:23 -04:00
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
2010-06-20 11:04:23 -04:00
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
2017-09-27 12:19:58 -07:00
self.refreshControl = [UIRefreshControl new];
self.refreshControl.tintColor = UIColorFromLightDarkRGB(0x0, 0xffffff);
self.refreshControl.backgroundColor = UIColorFromRGB(0xE3E6E0);
[self.refreshControl addTarget:self action:@selector(refresh:) forControlEvents:UIControlEventValueChanged];
[self.feedTitlesTable addSubview:self.refreshControl];
2013-10-18 18:37:11 -07:00
userLabelFont = [UIFont fontWithName:@"Helvetica-Bold" size:14.0];
2011-08-24 21:44:16 -07:00
imageCache = [[NSCache alloc] init];
[imageCache setDelegate:self];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(returnToApp)
name:UIApplicationWillEnterForegroundNotification
object:nil];
2012-08-09 16:34:59 -07:00
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(settingDidChange:)
name:kIASKAppSettingChanged
object:nil];
2013-06-21 17:48:06 -07:00
2016-03-26 21:27:25 -07:00
[self updateIntelligenceControlForOrientation:UIInterfaceOrientationUnknown];
2012-08-15 19:31:34 -07:00
self.intelligenceControl.hidden = YES;
2016-03-26 21:27:25 -07:00
[self.intelligenceControl.subviews objectAtIndex:3].accessibilityLabel = @"All";
[self.intelligenceControl.subviews objectAtIndex:2].accessibilityLabel = @"Unread";
[self.intelligenceControl.subviews objectAtIndex:1].accessibilityLabel = @"Focus";
[self.intelligenceControl.subviews objectAtIndex:0].accessibilityLabel = @"Saved";
[[UIBarButtonItem appearance] setTintColor:UIColorFromRGB(0x8F918B)];
[[UIBarButtonItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName:
UIColorFromFixedRGB(0x8F918B)}
forState:UIControlStateNormal];
[[UIBarButtonItem appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName:
UIColorFromFixedRGB(0x4C4D4A)}
forState:UIControlStateHighlighted];
2017-10-18 21:18:19 -07:00
self.view.backgroundColor = UIColorFromRGB(0xf4f4f4);
self.navigationController.navigationBar.tintColor = UIColorFromRGB(0x8F918B);
self.navigationController.navigationBar.translucent = NO;
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
[self layoutForInterfaceOrientation:orientation];
UILongPressGestureRecognizer *longpress = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:@selector(handleLongPress:)];
longpress.minimumPressDuration = 1.0;
longpress.delegate = self;
[self.feedTitlesTable addGestureRecognizer:longpress];
2015-12-07 16:09:49 -08:00
[[ThemeManager themeManager] addThemeGestureRecognizerToView:self.feedTitlesTable];
self.notifier = [[NBNotifier alloc] initWithTitle:@"Fetching stories..."
2017-10-12 21:53:53 -07:00
withOffset:CGPointMake(0, 0)];
[self.view insertSubview:self.notifier belowSubview:self.feedViewToolbar];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.notifier attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.notifier attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.notifier attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:NOTIFIER_HEIGHT]];
self.notifier.topOffsetConstraint = [NSLayoutConstraint constraintWithItem:self.notifier attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.feedViewToolbar attribute:NSLayoutAttributeTop multiplier:1.0 constant:-20];
[self.view addConstraint:self.notifier.topOffsetConstraint];
2017-09-27 12:19:58 -07:00
// self.feedTitlesTable.backgroundColor = UIColorFromRGB(0xf4f4f4);
self.feedTitlesTable.separatorColor = [UIColor clearColor];
userAvatarButton.customView.hidden = YES;
userInfoBarButton.customView.hidden = YES;
[self.navigationController.interactivePopGestureRecognizer addTarget:self action:@selector(handleGesture:)];
[self addKeyCommandWithInput:@"e" modifierFlags:UIKeyModifierShift action:@selector(selectEverything:) discoverabilityTitle:@"Open All Stories"];
[self addKeyCommandWithInput:UIKeyInputLeftArrow modifierFlags:0 action:@selector(selectPreviousIntelligence:) discoverabilityTitle:@"Switch Views"];
[self addKeyCommandWithInput:UIKeyInputRightArrow modifierFlags:0 action:@selector(selectNextIntelligence:) discoverabilityTitle:@"Switch Views"];
[self addKeyCommandWithInput:@"a" modifierFlags:0 action:@selector(tapAddSite:) discoverabilityTitle:@"Add Site"];
2010-06-20 11:04:23 -04:00
}
- (void)viewWillAppear:(BOOL)animated {
// NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad &&
!self.interactiveFeedDetailTransition) {
[appDelegate.masterContainerViewController transitionFromFeedDetail];
}
// NSLog(@"Feed List timing 0: %f", [NSDate timeIntervalSinceReferenceDate] - start);
[super viewWillAppear:animated];
2012-07-16 19:45:14 -07:00
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
2016-03-26 21:27:25 -07:00
NSInteger intelligenceLevel = [userPreferences integerForKey:@"selectedIntelligence"];
2012-07-16 19:45:14 -07:00
2016-03-26 21:27:25 -07:00
if (intelligenceLevel == 2) {
self.viewShowingAllFeeds = NO;
[self.intelligenceControl setSelectedSegmentIndex:3];
[appDelegate setSelectedIntelligence:2];
} else if (intelligenceLevel == 1) {
2012-07-16 19:45:14 -07:00
self.viewShowingAllFeeds = NO;
[self.intelligenceControl setSelectedSegmentIndex:2];
[appDelegate setSelectedIntelligence:1];
2016-03-26 21:27:25 -07:00
} else if (intelligenceLevel == 0) {
2012-07-16 19:45:14 -07:00
self.viewShowingAllFeeds = NO;
[self.intelligenceControl setSelectedSegmentIndex:1];
[appDelegate setSelectedIntelligence:0];
} else {
// default state, ALL BLURBLOG STORIES
2012-07-16 19:45:14 -07:00
self.viewShowingAllFeeds = YES;
[self.intelligenceControl setSelectedSegmentIndex:0];
[appDelegate setSelectedIntelligence:0];
}
2015-03-12 19:43:39 -07:00
// [MBProgressHUD hideHUDForView:appDelegate.storyPageControl.view animated:NO];
2012-07-16 19:45:14 -07:00
2012-08-02 18:00:48 -07:00
// perform these only if coming from the feed detail view
if (appDelegate.inFeedDetail) {
appDelegate.inFeedDetail = NO;
// reload the data and then set the highlight again
// [self.feedTitlesTable reloadData];
// [self refreshHeaderCounts];
2012-08-02 18:00:48 -07:00
[self redrawUnreadCounts];
// [self.feedTitlesTable selectRowAtIndexPath:self.currentRowAtIndexPath
// animated:NO
// scrollPosition:UITableViewScrollPositionNone];
[self.notifier setNeedsLayout];
2012-08-02 18:00:48 -07:00
}
// NSLog(@"Feed List timing 2: %f", [NSDate timeIntervalSinceReferenceDate] - start);
}
- (void)viewDidAppear:(BOOL)animated {
2012-07-27 19:42:19 -07:00
// [self.feedTitlesTable selectRowAtIndexPath:self.currentRowAtIndexPath
// animated:NO
// scrollPosition:UITableViewScrollPositionNone];
2011-08-24 21:44:16 -07:00
[super viewDidAppear:animated];
[self performSelector:@selector(fadeSelectedCell) withObject:self afterDelay:0.2];
// self.navigationController.navigationBar.backItem.title = @"All Sites";
[self layoutHeaderCounts:0];
[self refreshHeaderCounts];
self.interactiveFeedDetailTransition = NO;
[self becomeFirstResponder];
}
- (void)handleGesture:(UIScreenEdgePanGestureRecognizer *)gesture {
if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) return;
self.interactiveFeedDetailTransition = YES;
CGPoint point = [gesture locationInView:self.view];
CGFloat viewWidth = CGRectGetWidth(self.view.frame);
CGFloat percentage = MIN(point.x, viewWidth) / viewWidth;
// NSLog(@"back gesture: %d, %f - %f/%f", (int)gesture.state, percentage, point.x, viewWidth);
if (gesture.state == UIGestureRecognizerStateBegan) {
if (appDelegate.storiesCollection.transferredFromDashboard) {
[appDelegate.dashboardViewController.storiesModule.storiesCollection
transferStoriesFromCollection:appDelegate.storiesCollection];
[appDelegate.dashboardViewController.storiesModule fadeSelectedCell:NO];
}
} else if (gesture.state == UIGestureRecognizerStateChanged) {
[appDelegate.masterContainerViewController interactiveTransitionFromFeedDetail:percentage];
} else if (gesture.state == UIGestureRecognizerStateEnded) {
CGPoint velocity = [gesture velocityInView:self.view];
if (velocity.x > 0) {
[appDelegate.masterContainerViewController transitionFromFeedDetail];
} else {
// // Returning back to view, cancelling pop animation.
// [appDelegate.masterContainerViewController transitionToFeedDetail:NO];
}
self.interactiveFeedDetailTransition = NO;
}
2012-07-27 19:42:19 -07:00
}
- (void)fadeSelectedCell {
NSIndexPath *indexPath = [self.feedTitlesTable indexPathForSelectedRow];
if (!indexPath) return;
[self.feedTitlesTable deselectRowAtIndexPath:indexPath
2012-07-18 17:23:57 -07:00
animated:YES];
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:indexPath.section];
id feedId = [[appDelegate.dictFolders objectForKey:folderName] objectAtIndex:indexPath.row];
NSString *feedIdStr = [NSString stringWithFormat:@"%@", feedId];
2014-03-04 18:09:43 -08:00
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
// NSLog(@"Show feeds after being read (%@): %d / %@ -> %@", feedIdStr, [preferences boolForKey:@"show_feeds_after_being_read"], [self.stillVisibleFeeds objectForKey:feedIdStr], self.stillVisibleFeeds);
NSIndexPath *visiblePath = [self.stillVisibleFeeds objectForKey:feedIdStr];
if (visiblePath) {
2014-03-04 18:09:43 -08:00
[self.feedTitlesTable beginUpdates];
2014-09-22 18:02:25 -07:00
NSMutableArray *paths = (indexPath.section == visiblePath.section &&
indexPath.row == visiblePath.row)
? @[indexPath].mutableCopy
: @[indexPath, visiblePath].mutableCopy;
if (![preferences boolForKey:@"show_feeds_after_being_read"]) {
[self.stillVisibleFeeds removeObjectForKey:feedIdStr];
for (NSString *feedId in [self.stillVisibleFeeds allKeys]) {
NSLog(@"Found inadvertantly still visible feed: %@", feedId);
[paths addObject:[self.stillVisibleFeeds objectForKey:feedId]];
}
}
[self.feedTitlesTable reloadRowsAtIndexPaths:paths
2014-03-04 18:09:43 -08:00
withRowAnimation:UITableViewRowAnimationFade];
[self.feedTitlesTable endUpdates];
if (![preferences boolForKey:@"show_feeds_after_being_read"]) {
[self.stillVisibleFeeds removeAllObjects];
}
2014-03-04 18:09:43 -08:00
}
}
2012-07-31 15:57:56 -07:00
- (void)fadeFeed:(id)feedId {
NSString *feedIdStr = [NSString stringWithFormat:@"%@", feedId];
[self.feedTitlesTable deselectRowAtIndexPath:[self.feedTitlesTable indexPathForSelectedRow]
animated:YES];
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
if (![preferences boolForKey:@"show_feeds_after_being_read"]) {
for (NSIndexPath *indexPath in [self.feedTitlesTable indexPathsForVisibleRows]) {
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:indexPath.section];
id cellFeedId = [[appDelegate.dictFolders objectForKey:folderName] objectAtIndex:indexPath.row];
if ([feedIdStr isEqualToString:[NSString stringWithFormat:@"%@", cellFeedId]]) {
[self.feedTitlesTable beginUpdates];
[self.feedTitlesTable reloadRowsAtIndexPaths:@[indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[self.feedTitlesTable endUpdates];
break;
}
}
}
}
- (void)viewWillDisappear:(BOOL)animated {
[self.appDelegate hidePopoverAnimated:YES];
2012-06-19 14:27:35 -07:00
[super viewWillDisappear:animated];
}
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
[self layoutForInterfaceOrientation:orientation];
[self.notifier setNeedsLayout];
} completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
[self.feedTitlesTable reloadData];
}];
2012-07-20 22:00:30 -07:00
}
- (void)layoutForInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
2017-09-27 12:19:58 -07:00
// CGSize toolbarSize = [self.feedViewToolbar sizeThatFits:self.view.frame.size];
// if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// self.feedViewToolbar.frame = CGRectMake(-10.0f,
// CGRectGetHeight(self.view.frame) - toolbarSize.height,
// toolbarSize.width + 20, toolbarSize.height);
// } else {
// self.feedViewToolbar.frame = (CGRect){CGPointMake(0.f, CGRectGetHeight(self.view.frame) - toolbarSize.height), toolbarSize};
// }
// self.innerView.frame = (CGRect){CGPointZero, CGSizeMake(CGRectGetWidth(self.view.frame), CGRectGetMinY(self.feedViewToolbar.frame))};
self.notifier.offset = CGPointMake(0, 0);
2016-03-26 21:27:25 -07:00
[self updateIntelligenceControlForOrientation:interfaceOrientation];
[self layoutHeaderCounts:interfaceOrientation];
[self refreshHeaderCounts];
}
2010-06-20 11:04:23 -04:00
2016-03-26 21:27:25 -07:00
- (void)updateIntelligenceControlForOrientation:(UIInterfaceOrientation)orientation {
if (orientation == UIInterfaceOrientationUnknown) {
orientation = [UIApplication sharedApplication].statusBarOrientation;
}
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad && !UIInterfaceOrientationIsLandscape(orientation)) {
[self.intelligenceControl setImage:[UIImage imageNamed:@"unread_yellow_icn.png"] forSegmentAtIndex:1];
[self.intelligenceControl setImage:[UIImage imageNamed:@"unread_green_icn.png"] forSegmentAtIndex:2];
[self.intelligenceControl setImage:[UIImage imageNamed:@"unread_blue_icn.png"] forSegmentAtIndex:3];
[self.intelligenceControl setWidth:45 forSegmentAtIndex:0];
[self.intelligenceControl setWidth:40 forSegmentAtIndex:1];
[self.intelligenceControl setWidth:40 forSegmentAtIndex:2];
[self.intelligenceControl setWidth:40 forSegmentAtIndex:3];
} else {
[self.intelligenceControl setImage:[UIImage imageNamed:@"unread_yellow.png"] forSegmentAtIndex:1];
[self.intelligenceControl setImage:[UIImage imageNamed:@"unread_green.png"] forSegmentAtIndex:2];
[self.intelligenceControl setImage:[UIImage imageNamed:@"unread_blue.png"] forSegmentAtIndex:3];
[self.intelligenceControl setWidth:40 forSegmentAtIndex:0];
2016-03-26 21:27:25 -07:00
[self.intelligenceControl setWidth:68 forSegmentAtIndex:1];
[self.intelligenceControl setWidth:62 forSegmentAtIndex:2];
[self.intelligenceControl setWidth:60 forSegmentAtIndex:3];
2016-03-26 21:27:25 -07:00
}
[self.intelligenceControl sizeToFit];
2017-09-27 12:19:58 -07:00
// NSInteger height = 16;
// if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone && UIInterfaceOrientationIsLandscape(orientation)) {
// height = 8;
// }
//
// CGRect intelFrame = self.intelligenceControl.frame;
// intelFrame.origin.x = (self.feedViewToolbar.frame.size.width / 2) - (intelFrame.size.width / 2) + 20;
// intelFrame.size.height = self.feedViewToolbar.frame.size.height - height;
// self.intelligenceControl.frame = intelFrame;
2016-03-26 21:27:25 -07:00
}
// allow keyboard comands
- (BOOL)canBecomeFirstResponder {
return YES;
}
2010-06-20 11:04:23 -04:00
#pragma mark -
#pragma mark Initialization
- (void)returnToApp {
NSDate *decayDate = [[NSDate alloc] initWithTimeIntervalSinceNow:(BACKGROUND_REFRESH_SECONDS)];
2011-08-24 21:44:16 -07:00
NSLog(@"Last Update: %@ - %f", self.lastUpdate, [self.lastUpdate timeIntervalSinceDate:decayDate]);
if ([self.lastUpdate timeIntervalSinceDate:decayDate] < 0) {
[appDelegate reloadFeedsView:YES];
2011-08-24 21:44:16 -07:00
}
2012-07-11 20:19:42 -07:00
}
2012-08-09 10:18:15 -07:00
-(void)fetchFeedList:(BOOL)showLoader {
2017-03-23 17:37:58 -07:00
NSString *urlFeedList;
NSLog(@"Fetching feed list");
[appDelegate cancelOfflineQueue];
2012-08-16 20:10:50 -07:00
if (self.inPullToRefresh_) {
2017-03-23 17:37:58 -07:00
urlFeedList = [NSString stringWithFormat:@"%@/reader/feeds?flat=true&update_counts=true",
self.appDelegate.url];
2012-08-16 20:10:50 -07:00
} else {
2017-03-23 17:37:58 -07:00
urlFeedList = [NSString stringWithFormat:@"%@/reader/feeds?flat=true&update_counts=false",
self.appDelegate.url];
2012-08-16 20:10:50 -07:00
}
if (appDelegate.backgroundCompletionHandler) {
urlFeedList = [urlFeedList stringByAppendingString:@"&background_ios=true"];
}
2017-03-23 17:37:58 -07:00
[appDelegate.networkManager GET:urlFeedList parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
[self finishLoadingFeedList:responseObject];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
[self finishedWithError:error statusCode:httpResponse.statusCode];
}];
2011-08-24 21:44:16 -07:00
self.lastUpdate = [NSDate date];
if (showLoader) {
// [self.notifier hide];
}
[self showRefreshNotifier];
2010-06-20 11:04:23 -04:00
}
2017-03-23 17:37:58 -07:00
- (void)finishedWithError:(NSError *)error statusCode:(NSInteger)statusCode {
2017-06-01 21:19:54 -07:00
[self finishRefresh];
2017-03-23 17:37:58 -07:00
if (statusCode == 403) {
NSLog(@"Showing login");
return [appDelegate showLogin];
2017-03-23 17:37:58 -07:00
} else if (statusCode >= 400) {
if (statusCode == 429) {
[self informError:@"Slow down. You're rate-limited."];
2017-03-23 17:37:58 -07:00
} else if (statusCode == 503) {
[self informError:@"In maintenance mode"];
} else {
[self informError:@"The server barfed!"];
}
self.isOffline = YES;
[self showOfflineNotifier];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[appDelegate.dashboardViewController refreshStories];
}
return;
}
2017-03-23 17:37:58 -07:00
[MBProgressHUD hideHUDForView:self.view animated:YES];
// User clicking on another link before the page loads is OK.
[self informError:error];
2017-03-23 17:37:58 -07:00
self.isOffline = YES;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[appDelegate.dashboardViewController refreshStories];
}
[self showOfflineNotifier];
[self loadNotificationStory];
[[NSNotificationCenter defaultCenter] postNotificationName:@"FinishedLoadingFeedsNotification" object:nil];
}
- (void)finishLoadingFeedList:(NSDictionary *)results {
appDelegate.hasNoSites = NO;
appDelegate.recentlyReadStories = [NSMutableDictionary dictionary];
appDelegate.unreadStoryHashes = [NSMutableDictionary dictionary];
self.isOffline = NO;
appDelegate.activeUsername = [results objectForKey:@"user"];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
(unsigned long)NULL), ^(void) {
[appDelegate.database inTransaction:^(FMDatabase *db, BOOL *rollback) {
[db executeUpdate:@"DELETE FROM accounts WHERE username = ?", appDelegate.activeUsername];
[db executeUpdate:@"INSERT INTO accounts"
"(username, download_date, feeds_json) VALUES "
"(?, ?, ?)",
appDelegate.activeUsername,
[NSDate date],
[results JSONRepresentation]
];
for (NSDictionary *feed in [results objectForKey:@"social_feeds"]) {
[db executeUpdate:@"INSERT INTO unread_counts (feed_id, ps, nt, ng) VALUES "
"(?, ?, ?, ?)",
[feed objectForKey:@"id"],
[feed objectForKey:@"ps"],
[feed objectForKey:@"nt"],
[feed objectForKey:@"ng"]];
}
for (NSString *feedId in [results objectForKey:@"feeds"]) {
NSDictionary *feed = [[results objectForKey:@"feeds"] objectForKey:feedId];
[db executeUpdate:@"INSERT INTO unread_counts (feed_id, ps, nt, ng) VALUES "
"(?, ?, ?, ?)",
[feed objectForKey:@"id"],
[feed objectForKey:@"ps"],
[feed objectForKey:@"nt"],
[feed objectForKey:@"ng"]];
}
}];
dispatch_async(dispatch_get_main_queue(), ^{
[self finishLoadingFeedListWithDict:results finished:YES];
});
});
}
- (void)finishLoadingFeedListWithDict:(NSDictionary *)results finished:(BOOL)finished {
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
2011-08-24 21:44:16 -07:00
[MBProgressHUD hideHUDForView:self.view animated:YES];
self.stillVisibleFeeds = [NSMutableDictionary dictionary];
2012-06-26 11:45:42 -07:00
appDelegate.activeUsername = [results objectForKey:@"user"];
if (appDelegate.activeUsername) {
[userPreferences setObject:appDelegate.activeUsername forKey:@"active_username"];
[userPreferences synchronize];
}
2012-08-11 18:03:28 -07:00
// Bottom toolbar
2017-09-27 12:19:58 -07:00
// UIImage *addImage = [UIImage imageNamed:@"nav_icn_add.png"];
// UIImage *settingsImage = [UIImage imageNamed:@"nav_icn_settings.png"];
// addBarButton.enabled = YES;
addBarButton.accessibilityLabel = @"Add site";
2017-09-27 12:19:58 -07:00
// settingsBarButton.enabled = YES;
settingsBarButton.accessibilityLabel = @"Settings";
2017-09-27 12:19:58 -07:00
// NBBarButtonItem *addButton = [NBBarButtonItem buttonWithType:UIButtonTypeCustom];
// [addButton setImage:[[ThemeManager themeManager] themedImage:addImage] forState:UIControlStateNormal];
// [addButton sizeToFit];
// [addButton addTarget:self action:@selector(tapAddSite:)
// forControlEvents:UIControlEventTouchUpInside];
// addButton.accessibilityLabel = @"Add feed";
// [addBarButton setCustomView:addButton];
// NBBarButtonItem *settingsButton = [NBBarButtonItem buttonWithType:UIButtonTypeCustom];
// settingsButton.onRightSide = YES;
// [settingsButton setImage:[[ThemeManager themeManager] themedImage:settingsImage] forState:UIControlStateNormal];
// [settingsButton sizeToFit];
// [settingsButton addTarget:self action:@selector(showSettingsPopover:)
// forControlEvents:UIControlEventTouchUpInside];
// settingsButton.accessibilityLabel = @"Settings";
// [settingsBarButton setCustomView:settingsButton];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
UIImage *activityImage = [UIImage imageNamed:@"nav_icn_activity_hover.png"];
NBBarButtonItem *activityButton = [NBBarButtonItem buttonWithType:UIButtonTypeCustom];
2017-09-27 12:19:58 -07:00
activityButton.accessibilityLabel = @"Activities";
[activityButton setImage:activityImage forState:UIControlStateNormal];
2017-09-27 12:19:58 -07:00
// [activityButton sizeToFit];
// [activityButton setContentEdgeInsets:UIEdgeInsetsMake(0, -6, -0, -6)];
// [activityButton setFrame:CGRectInset(activityButton.frame, 0, -6)];
[activityButton setImageEdgeInsets:UIEdgeInsetsMake(4, 4, 4, 4)];
[activityButton addTarget:self
action:@selector(showInteractionsPopover:)
forControlEvents:UIControlEventTouchUpInside];
activitiesButton = [[UIBarButtonItem alloc]
initWithCustomView:activityButton];
self.navigationItem.rightBarButtonItem = activitiesButton;
}
2012-07-12 11:35:32 -07:00
NSMutableDictionary *sortedFolders = [[NSMutableDictionary alloc] init];
2011-10-14 17:15:48 -07:00
NSArray *sortedArray;
// Set up dictSocialProfile and userActivitiesArray
appDelegate.dictUnreadCounts = [NSMutableDictionary dictionary];
appDelegate.dictSocialProfile = [results objectForKey:@"social_profile"];
appDelegate.dictUserProfile = [results objectForKey:@"user_profile"];
appDelegate.dictSocialServices = [results objectForKey:@"social_services"];
2012-07-26 23:07:47 -07:00
appDelegate.userActivitiesArray = [results objectForKey:@"activities"];
2012-08-11 18:03:28 -07:00
2012-06-26 12:29:37 -07:00
// Set up dictSocialFeeds
2012-06-26 11:45:42 -07:00
NSArray *socialFeedsArray = [results objectForKey:@"social_feeds"];
2012-06-25 15:02:20 -07:00
NSMutableArray *socialFolder = [[NSMutableArray alloc] init];
NSMutableDictionary *socialDict = [[NSMutableDictionary alloc] init];
2012-07-15 15:06:06 -07:00
NSMutableDictionary *tempActiveFeeds = [[NSMutableDictionary alloc] init];
appDelegate.dictActiveFeeds = tempActiveFeeds;
2012-06-25 15:02:20 -07:00
2012-06-26 11:45:42 -07:00
for (int i = 0; i < socialFeedsArray.count; i++) {
2012-06-25 15:02:20 -07:00
NSString *userKey = [NSString stringWithFormat:@"%@",
2012-06-26 11:45:42 -07:00
[[socialFeedsArray objectAtIndex:i] objectForKey:@"id"]];
[socialFolder addObject: [[socialFeedsArray objectAtIndex:i] objectForKey:@"id"]];
[socialDict setObject:[socialFeedsArray objectAtIndex:i]
2012-06-25 15:02:20 -07:00
forKey:userKey];
}
2012-07-01 18:26:39 -07:00
2012-06-25 15:02:20 -07:00
appDelegate.dictSocialFeeds = socialDict;
2012-07-10 16:48:05 -07:00
2012-06-26 12:29:37 -07:00
// set up dictFolders
2012-08-02 19:43:55 -07:00
NSMutableDictionary * allFolders = [[NSMutableDictionary alloc] init];
if (![[results objectForKey:@"flat_folders"] isKindOfClass:[NSArray class]]) {
allFolders = [[results objectForKey:@"flat_folders"] mutableCopy];
}
[allFolders setValue:socialFolder forKey:@"river_blurblogs"];
[allFolders setValue:[[NSMutableArray alloc] init] forKey:@"river_global"];
NSArray *savedStories = [appDelegate updateStarredStoryCounts:results];
[allFolders setValue:savedStories forKey:@"saved_stories"];
2012-06-26 12:29:37 -07:00
appDelegate.dictFolders = allFolders;
// set up dictFeeds
2012-07-27 16:10:13 -07:00
appDelegate.dictFeeds = [[results objectForKey:@"feeds"] mutableCopy];
[appDelegate populateDictUnreadCounts];
[appDelegate populateDictTextFeeds];
2012-06-26 12:29:37 -07:00
// sort all the folders
appDelegate.dictFoldersArray = [NSMutableArray array];
for (id f in appDelegate.dictFolders) {
NSArray *folder = [appDelegate.dictFolders objectForKey:f];
NSString *folderTitle;
if ([f isEqualToString:@" "]) {
folderTitle = @"everything";
} else {
folderTitle = f;
}
[appDelegate.dictFoldersArray addObject:folderTitle];
2012-06-26 12:29:37 -07:00
sortedArray = [folder sortedArrayUsingComparator:^NSComparisonResult(id id1, id id2) {
NSString *feedTitleA;
NSString *feedTitleB;
if ([appDelegate isSocialFeed:[NSString stringWithFormat:@"%@", id1]]) {
feedTitleA = [[appDelegate.dictSocialFeeds
objectForKey:[NSString stringWithFormat:@"%@", id1]]
objectForKey:@"feed_title"];
feedTitleB = [[appDelegate.dictSocialFeeds
objectForKey:[NSString stringWithFormat:@"%@", id2]]
objectForKey:@"feed_title"];
} else {
feedTitleA = [[appDelegate.dictFeeds
objectForKey:[NSString stringWithFormat:@"%@", id1]]
objectForKey:@"feed_title"];
feedTitleB = [[appDelegate.dictFeeds
objectForKey:[NSString stringWithFormat:@"%@", id2]]
objectForKey:@"feed_title"];
}
return [feedTitleA caseInsensitiveCompare:feedTitleB];
}];
[sortedFolders setValue:sortedArray forKey:folderTitle];
2012-06-26 12:29:37 -07:00
}
2011-10-14 17:15:48 -07:00
appDelegate.dictFolders = sortedFolders;
[appDelegate.dictFoldersArray sortUsingSelector:@selector(caseInsensitiveCompare:)];
// Move River Blurblog and Everything to the top
if ([appDelegate.dictFoldersArray containsObject:@"river_global"]) {
[appDelegate.dictFoldersArray removeObject:@"river_global"];
[appDelegate.dictFoldersArray insertObject:@"river_global" atIndex:0];
}
if ([appDelegate.dictFoldersArray containsObject:@"river_blurblogs"]) {
[appDelegate.dictFoldersArray removeObject:@"river_blurblogs"];
[appDelegate.dictFoldersArray insertObject:@"river_blurblogs" atIndex:1];
}
if ([appDelegate.dictFoldersArray containsObject:@"everything"]) {
[appDelegate.dictFoldersArray removeObject:@"everything"];
[appDelegate.dictFoldersArray insertObject:@"everything" atIndex:2];
}
2014-10-22 16:39:37 -07:00
// Add Read Stories folder
[appDelegate.dictFoldersArray removeObject:@"read_stories"];
[appDelegate.dictFoldersArray insertObject:@"read_stories" atIndex:appDelegate.dictFoldersArray.count];
// Add Saved Stories folder
[appDelegate.dictFoldersArray removeObject:@"saved_stories"];
if (appDelegate.savedStoriesCount) {
[appDelegate.dictFoldersArray insertObject:@"saved_stories" atIndex:appDelegate.dictFoldersArray.count];
}
2012-08-02 19:43:55 -07:00
// test for empty
2012-08-02 19:43:55 -07:00
if ([[appDelegate.dictFeeds allKeys] count] == 0 &&
[[appDelegate.dictSocialFeeds allKeys] count] == 0) {
appDelegate.hasNoSites = YES;
2012-08-02 19:43:55 -07:00
}
[self calculateFeedLocations];
[self.feedTitlesTable reloadData];
2013-02-15 16:41:20 -08:00
[self refreshHeaderCounts];
2012-06-27 10:04:44 -07:00
// assign categories for FTUX
if (![[results objectForKey:@"categories"] isKindOfClass:[NSNull class]]){
appDelegate.categories = [[results objectForKey:@"categories"] objectForKey:@"categories"];
appDelegate.categoryFeeds = [[results objectForKey:@"categories"] objectForKey:@"feeds"];
}
if (!self.isOffline) {
// start up the first time user experience
if ([[results objectForKey:@"social_feeds"] count] == 0 &&
[[[results objectForKey:@"feeds"] allKeys] count] == 0) {
[appDelegate showFirstTimeUser];
return;
}
if (self.inPullToRefresh_) {
[self showSyncingNotifier];
[self.appDelegate flushQueuedReadStories:YES withCallback:^{
[self refreshFeedList];
// [self.appDelegate startOfflineQueue];
}];
} else {
[self showSyncingNotifier];
[self.appDelegate flushQueuedReadStories:YES withCallback:^{
[self refreshFeedList];
}];
}
2012-08-16 20:10:50 -07:00
}
2012-08-12 16:50:34 -07:00
2012-08-15 19:31:34 -07:00
self.intelligenceControl.hidden = NO;
[self showExplainerOnEmptyFeedlist];
[self layoutHeaderCounts:0];
[self refreshHeaderCounts];
[appDelegate checkForFeedNotifications];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad && finished) {
[appDelegate.dashboardViewController refreshStories];
}
[self loadNotificationStory];
[[NSNotificationCenter defaultCenter] postNotificationName:@"FinishedLoadingFeedsNotification" object:nil];
}
- (void)loadOfflineFeeds:(BOOL)failed {
__block __typeof__(self) _self = self;
self.isOffline = YES;
NSLog(@"Loading offline feeds: %d", failed);
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
if (!appDelegate.activeUsername) {
appDelegate.activeUsername = [userPreferences stringForKey:@"active_username"];
if (!appDelegate.activeUsername) {
if (failed) {
return;
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[self fetchFeedList:YES];
});
return;
}
}
}
[self showRefreshNotifier];
[appDelegate.database inDatabase:^(FMDatabase *db) {
NSDictionary *results;
FMResultSet *cursor = [db executeQuery:@"SELECT * FROM accounts WHERE username = ? LIMIT 1",
appDelegate.activeUsername];
while ([cursor next]) {
NSDictionary *feedsCache = [cursor resultDictionary];
results = [NSJSONSerialization
JSONObjectWithData:[[feedsCache objectForKey:@"feeds_json"]
dataUsingEncoding:NSUTF8StringEncoding]
options:0 error:nil];
break;
}
[cursor close];
dispatch_async(dispatch_get_main_queue(), ^{
[_self finishLoadingFeedListWithDict:results finished:failed];
[_self fetchFeedList:NO];
});
}];
}
- (void)loadNotificationStory {
dispatch_async(dispatch_get_main_queue(), ^{
if (appDelegate.tryFeedFeedId && !appDelegate.isTryFeedView) {
[appDelegate loadFeed:appDelegate.tryFeedFeedId withStory:appDelegate.tryFeedStoryId animated:NO];
}
});
}
- (void)showUserProfile {
appDelegate.activeUserProfileId = [NSString stringWithFormat:@"%@", [appDelegate.dictSocialProfile objectForKey:@"user_id"]];
appDelegate.activeUserProfileName = [NSString stringWithFormat:@"%@", [appDelegate.dictSocialProfile objectForKey:@"username"]];
2012-08-09 10:18:15 -07:00
// appDelegate.activeUserProfileName = @"You";
[appDelegate showUserProfileModal:[self.navigationItem.leftBarButtonItems
objectAtIndex:1]];
}
2012-07-31 15:57:56 -07:00
- (IBAction)tapAddSite:(id)sender {
2016-03-17 20:40:09 -07:00
[self.appDelegate.addSiteNavigationController popToRootViewControllerAnimated:NO];
2016-03-18 21:29:42 -07:00
2016-03-19 21:26:56 -07:00
// if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
2017-09-27 12:19:58 -07:00
[self.appDelegate showPopoverWithViewController:self.appDelegate.addSiteNavigationController contentSize:CGSizeMake(320, 96) barButtonItem:self.addBarButton];
// [self.appDelegate showPopoverWithViewController:self.appDelegate.addSiteNavigationController contentSize:CGSizeMake(320, 96) sourceView:self.addBarButton sourceRect:CGRectMake(35.0, 0.0, 0.0, 0.0) permittedArrowDirections:UIPopoverArrowDirectionDown];
2016-03-19 21:26:56 -07:00
// } else {
// [self.appDelegate showPopoverWithViewController:self.appDelegate.addSiteNavigationController contentSize:CGSizeMake(320, 96) barButtonItem:self.addBarButton];
// }
2016-03-18 21:29:42 -07:00
[self.appDelegate.addSiteViewController reload];
2012-07-31 15:57:56 -07:00
}
- (IBAction)showSettingsPopover:(id)sender {
[self.appDelegate.feedsMenuViewController view];
NSInteger menuCount = [self.appDelegate.feedsMenuViewController.menuOptions count];
2017-10-12 21:05:28 -07:00
[self.appDelegate showPopoverWithViewController:self.appDelegate.feedsMenuViewController contentSize:CGSizeMake(250, 38 * (menuCount + 2)) barButtonItem:self.settingsBarButton];
}
- (IBAction)showInteractionsPopover:(id)sender {
if (self.presentedViewController) {
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
return;
}
CGSize size = CGSizeMake(self.view.frame.size.width - 36,
self.view.frame.size.height - 60);
[self.appDelegate showPopoverWithViewController:self.appDelegate.dashboardViewController contentSize:size barButtonItem:self.activitiesButton];
[appDelegate.dashboardViewController refreshInteractions];
[appDelegate.dashboardViewController refreshActivity];
}
- (void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer {
CGPoint p = [gestureRecognizer locationInView:self.feedTitlesTable];
NSIndexPath *indexPath = [self.feedTitlesTable indexPathForRowAtPoint:p];
if (gestureRecognizer.state != UIGestureRecognizerStateBegan) return;
if (indexPath == nil) return;
FeedTableCell *cell = (FeedTableCell *)[self.feedTitlesTable cellForRowAtIndexPath:indexPath];
if (!cell.highlighted) return;
2014-03-04 18:09:43 -08:00
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
NSString *longPressTitle = [preferences stringForKey:@"long_press_feed_title"];
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:indexPath.section];
id feedId = [[appDelegate.dictFolders objectForKey:folderName] objectAtIndex:indexPath.row];
NSString *feedIdStr = [NSString stringWithFormat:@"%@",feedId];
2015-11-13 21:54:32 -08:00
// BOOL isSocial = [appDelegate isSocialFeed:feedIdStr];
2016-03-26 21:27:25 -07:00
BOOL isSaved = [appDelegate isSavedFeed:feedIdStr] || self.appDelegate.isSavedStoriesIntelligenceMode;
if (isSaved) return;
2013-10-10 14:12:04 -07:00
[self performSelector:@selector(highlightCell:) withObject:cell afterDelay:0.0];
2014-03-04 18:09:43 -08:00
if ([longPressTitle isEqualToString:@"mark_read_choose_days"]) {
2015-11-13 21:54:32 -08:00
// NSDictionary *feed = isSocial ?
// [appDelegate.dictSocialFeeds objectForKey:feedIdStr] :
// [appDelegate.dictFeeds objectForKey:feedIdStr];
[self.appDelegate showMarkReadMenuWithFeedIds:@[feedIdStr] collectionTitle:@"site" sourceView:self.feedTitlesTable sourceRect:cell.frame completionHandler:^(BOOL marked){
2015-11-13 21:54:32 -08:00
for (FeedTableCell *cell in [self.feedTitlesTable visibleCells]) {
if (cell.highlighted) {
[self performSelector:@selector(unhighlightCell:) withObject:cell afterDelay:0.0];
break;
}
}
}];
2014-03-04 18:09:43 -08:00
} else if ([longPressTitle isEqualToString:@"mark_read_immediate"]) {
[self markFeedRead:feedId cutoffDays:0];
// if ([preferences boolForKey:@"show_feeds_after_being_read"]) {
2014-03-04 18:09:43 -08:00
[self.stillVisibleFeeds setObject:indexPath forKey:feedIdStr];
// }
2014-03-04 18:09:43 -08:00
[self.feedTitlesTable beginUpdates];
[self.feedTitlesTable reloadRowsAtIndexPaths:@[indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[self.feedTitlesTable endUpdates];
}
2013-10-10 14:12:04 -07:00
}
- (void)highlightCell:(FeedTableCell *)cell {
[cell setHighlighted:YES];
}
- (void)unhighlightCell:(FeedTableCell *)cell {
[cell setHighlighted:NO];
2014-03-04 18:09:43 -08:00
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
NSLog(@"unhighlight cell");
2014-03-04 18:09:43 -08:00
if (![preferences boolForKey:@"show_feeds_after_being_read"]) {
NSIndexPath *indexPath = [self.feedTitlesTable indexPathForCell:cell];
[self.feedTitlesTable beginUpdates];
[self.feedTitlesTable reloadRowsAtIndexPaths:@[indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[self.feedTitlesTable endUpdates];
}
}
#pragma mark -
#pragma mark Preferences
2015-12-07 16:09:49 -08:00
- (void)settingsViewControllerWillAppear:(IASKAppSettingsViewController *)sender {
[[ThemeManager themeManager] updatePreferencesTheme];
}
2013-06-21 17:48:06 -07:00
- (void)settingsViewControllerDidEnd:(IASKAppSettingsViewController*)sender {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[appDelegate.masterContainerViewController dismissViewControllerAnimated:YES completion:nil];
} else {
[appDelegate.navigationController dismissViewControllerAnimated:YES completion:nil];
}
[self resizeFontSize];
[self resetupGestures];
}
- (void)resizeFontSize {
appDelegate.fontDescriptorTitleSize = nil;
2013-11-23 13:03:14 -08:00
[self.feedTitlesTable reloadData];
appDelegate.feedDetailViewController.invalidateFontCache = YES;
[appDelegate.feedDetailViewController reloadData];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[appDelegate.dashboardViewController.storiesModule reloadData];
}
2013-06-21 17:48:06 -07:00
}
2015-12-07 16:09:49 -08:00
- (void)updateTheme {
[super updateTheme];
if (![self.presentedViewController isKindOfClass:[UINavigationController class]] || (((UINavigationController *)self.presentedViewController).topViewController != (UIViewController *)self.appDelegate.fontSettingsViewController && ![((UINavigationController *)self.presentedViewController).topViewController conformsToProtocol:@protocol(IASKViewController)])) {
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
}
[self.appDelegate hidePopoverAnimated:YES];
self.navigationController.navigationBar.tintColor = [UINavigationBar appearance].tintColor;
self.navigationController.navigationBar.barTintColor = [UINavigationBar appearance].barTintColor;
self.navigationController.toolbar.tintColor = [UIToolbar appearance].tintColor;
self.navigationController.toolbar.barTintColor = [UIToolbar appearance].barTintColor;
self.feedViewToolbar.tintColor = [UINavigationBar appearance].tintColor;
self.feedViewToolbar.barTintColor = [UINavigationBar appearance].barTintColor;
self.addBarButton.tintColor = UIColorFromRGB(0x8F918B);
self.intelligenceControl.tintColor = UIColorFromRGB(0x8F918B);
self.settingsBarButton.tintColor = UIColorFromRGB(0x8F918B);
self.refreshControl.tintColor = UIColorFromLightDarkRGB(0x0, 0xffffff);
self.refreshControl.backgroundColor = UIColorFromRGB(0xE3E6E0);
2017-10-18 21:18:19 -07:00
self.view.backgroundColor = UIColorFromRGB(0xf4f4f4);
2015-12-07 16:09:49 -08:00
2016-03-19 21:26:56 -07:00
NBBarButtonItem *barButton = self.addBarButton.customView;
[barButton setImage:[[ThemeManager themeManager] themedImage:[UIImage imageNamed:@"nav_icn_add.png"]] forState:UIControlStateNormal];
barButton = self.settingsBarButton.customView;
[barButton setImage:[[ThemeManager themeManager] themedImage:[UIImage imageNamed:@"nav_icn_settings.png"]] forState:UIControlStateNormal];
[self layoutHeaderCounts:0];
[self refreshHeaderCounts];
2015-12-07 16:09:49 -08:00
2017-09-27 12:19:58 -07:00
// self.feedTitlesTable.backgroundColor = UIColorFromRGB(0xf4f4f4);
2015-12-07 16:09:49 -08:00
[self.feedTitlesTable reloadData];
[self resetupGestures];
2015-12-07 16:09:49 -08:00
}
- (void)updateThemeBrightness {
if ([[ThemeManager themeManager] autoChangeTheme]) {
[[ThemeManager themeManager] updateTheme];
}
}
- (void)updateThemeStyle {
[[ThemeManager themeManager] updateTheme];
}
2013-06-21 17:48:06 -07:00
- (void)settingDidChange:(NSNotification*)notification {
2015-12-07 16:09:49 -08:00
NSString *identifier = notification.object;
if ([identifier isEqual:@"offline_allowed"]) {
BOOL enabled = [[notification.userInfo objectForKey:@"offline_allowed"] boolValue];
[appDelegate.preferencesViewController setHiddenKeys:enabled ? nil :
[NSSet setWithObjects:@"offline_image_download",
@"offline_download_connection",
@"offline_store_limit",
nil] animated:YES];
2015-12-07 16:09:49 -08:00
} else if ([identifier isEqual:@"use_system_font_size"]) {
BOOL enabled = [[notification.userInfo objectForKey:@"use_system_font_size"] boolValue];
[appDelegate.preferencesViewController setHiddenKeys:!enabled ? nil :
[NSSet setWithObjects:@"feed_list_font_size",
nil] animated:YES];
2015-12-07 16:09:49 -08:00
} else if ([identifier isEqual:@"feed_list_font_size"]) {
[self resizeFontSize];
2015-12-07 16:09:49 -08:00
} else if ([identifier isEqual:@"theme_auto_toggle"]) {
BOOL enabled = [[notification.userInfo objectForKey:@"theme_auto_toggle"] boolValue];
[appDelegate.preferencesViewController setHiddenKeys:!enabled ? [NSSet setWithObject:@"theme_auto_brightness"] : [NSSet setWithObjects:@"theme_style", @"theme_gesture", nil] animated:YES];
} else if ([identifier isEqual:@"theme_auto_brightness"]) {
[self updateThemeBrightness];
} else if ([identifier isEqual:@"theme_style"]) {
[self updateThemeStyle];
} else if ([identifier isEqual:@"story_list_preview_images"]) {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[appDelegate.dashboardViewController.storiesModule reloadData];
}
}
}
- (void)settingsViewController:(IASKAppSettingsViewController*)sender buttonTappedForSpecifier:(IASKSpecifier*)specifier {
if ([specifier.key isEqualToString:@"offline_cache_empty_stories"]) {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
dispatch_sync(dispatch_get_main_queue(), ^{
[[NSUserDefaults standardUserDefaults] setObject:@"Deleting..." forKey:specifier.key];
});
2017-04-04 15:33:08 -07:00
[appDelegate.database inDatabase:^(FMDatabase *db) {
[db executeUpdate:@"VACUUM"];
[appDelegate setupDatabase:db force:YES];
[appDelegate deleteAllCachedImages];
dispatch_sync(dispatch_get_main_queue(), ^{
[[NSUserDefaults standardUserDefaults] setObject:@"Cleared all stories and images!"
forKey:specifier.key];
});
}];
});
2013-06-21 17:48:06 -07:00
}
}
2010-06-20 11:04:23 -04:00
#pragma mark -
#pragma mark Table View - Feed List
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (appDelegate.hasNoSites) {
return 0;
2012-08-02 19:43:55 -07:00
}
return [appDelegate.dictFoldersArray count];
2010-06-20 11:04:23 -04:00
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [appDelegate.dictFoldersArray objectAtIndex:section];
2010-06-20 11:04:23 -04:00
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (appDelegate.hasNoSites) {
2012-08-02 19:43:55 -07:00
return 1;
}
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:section];
return [[appDelegate.dictFolders objectForKey:folderName] count];
2010-06-20 11:04:23 -04:00
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:indexPath.section];
id feedId = [[appDelegate.dictFolders objectForKey:folderName] objectAtIndex:indexPath.row];
NSString *feedIdStr = [NSString stringWithFormat:@"%@",feedId];
BOOL isSocial = [appDelegate isSocialFeed:feedIdStr];
BOOL isSaved = [appDelegate isSavedFeed:feedIdStr];
2016-03-26 21:27:25 -07:00
BOOL isSavedStoriesFeed = self.appDelegate.isSavedStoriesIntelligenceMode && [self.appDelegate savedStoriesCountForFeed:feedIdStr] > 0;
BOOL isFolderCollapsed = [appDelegate isFolderCollapsed:folderName];
2013-10-18 14:17:01 -07:00
NSString *CellIdentifier;
if (isFolderCollapsed || ![self isFeedVisible:feedIdStr]) {
CellIdentifier = @"BlankCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
return cell;
} else if (indexPath.section == 0 || indexPath.section == 1) {
CellIdentifier = @"BlurblogCellIdentifier";
} else if (isSaved) {
CellIdentifier = @"SavedCellIdentifier";
} else {
CellIdentifier = @"FeedCellIdentifier";
}
FeedTableCell *cell = (FeedTableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
BOOL newCell = cell == nil;
if (newCell) {
cell = [[FeedTableCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
2013-07-26 17:58:58 -07:00
cell.appDelegate = appDelegate;
2011-08-24 21:44:16 -07:00
}
NSDictionary *feed = isSocial ?
[appDelegate.dictSocialFeeds objectForKey:feedIdStr] :
isSaved ?
[appDelegate.dictSavedStoryTags objectForKey:feedIdStr] :
[appDelegate.dictFeeds objectForKey:feedIdStr];
NSDictionary *unreadCounts = [appDelegate.dictUnreadCounts objectForKey:feedIdStr];
cell.feedFavicon = [appDelegate getFavicon:feedIdStr isSocial:isSocial isSaved:isSaved];
cell.feedTitle = [feed objectForKey:@"feed_title"];
2012-06-27 10:18:29 -07:00
cell.isSocial = isSocial;
cell.isSaved = isSaved;
2011-08-24 21:44:16 -07:00
if (newCell) {
[cell setupGestures];
}
2016-03-26 21:27:25 -07:00
if (isSavedStoriesFeed) {
cell.positiveCount = 0;
cell.neutralCount = 0;
cell.negativeCount = 0;
cell.savedStoriesCount = (int)[self.appDelegate savedStoriesCountForFeed:feedIdStr];
} else {
cell.positiveCount = [[unreadCounts objectForKey:@"ps"] intValue];
cell.neutralCount = [[unreadCounts objectForKey:@"nt"] intValue];
cell.negativeCount = [[unreadCounts objectForKey:@"ng"] intValue];
cell.savedStoriesCount = 0;
}
if (cell.neutralCount) {
cell.accessibilityLabel = [NSString stringWithFormat:@"%@ feed, %@ unread stories", cell.feedTitle, @(cell.neutralCount)];
} else {
cell.accessibilityLabel = [NSString stringWithFormat:@"%@ feed", cell.feedTitle];
}
2013-10-01 19:32:40 -07:00
[cell setNeedsDisplay];
2011-08-24 21:44:16 -07:00
return cell;
2010-06-20 11:04:23 -04:00
}
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
2012-07-27 19:42:19 -07:00
if (appDelegate.hasNoSites) {
2012-08-02 19:43:55 -07:00
return;
}
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[appDelegate.dashboardViewController.storiesModule.view endEditing:YES];
}
[appDelegate.storiesCollection reset];
2012-08-02 19:43:55 -07:00
2012-07-27 19:42:19 -07:00
// set the current row pointer
self.currentRowAtIndexPath = indexPath;
self.currentSection = 0;
2012-07-27 19:42:19 -07:00
NSString *folderName;
if (indexPath.section == 0) {
folderName = @"river_global";
} else if (indexPath.section == 1) {
folderName = @"river_blurblogs";
} else if (indexPath.section == 2) {
folderName = @"everything";
} else {
folderName = [appDelegate.dictFoldersArray objectAtIndex:indexPath.section];
}
id feedId = [[appDelegate.dictFolders objectForKey:folderName] objectAtIndex:indexPath.row];
2011-08-24 21:44:16 -07:00
NSString *feedIdStr = [NSString stringWithFormat:@"%@",feedId];
NSDictionary *feed;
appDelegate.storiesCollection.isReadView = NO;
2012-06-26 16:24:19 -07:00
if ([appDelegate isSocialFeed:feedIdStr]) {
2012-06-25 15:02:20 -07:00
feed = [appDelegate.dictSocialFeeds objectForKey:feedIdStr];
appDelegate.storiesCollection.isSocialView = YES;
appDelegate.storiesCollection.isSavedView = NO;
} else if ([appDelegate isSavedFeed:feedIdStr]) {
feed = [appDelegate.dictSavedStoryTags objectForKey:feedIdStr];
appDelegate.storiesCollection.isSocialView = NO;
appDelegate.storiesCollection.isSavedView = YES;
appDelegate.storiesCollection.activeSavedStoryTag = [feed objectForKey:@"tag"];
2012-06-25 15:02:20 -07:00
} else {
feed = [appDelegate.dictFeeds objectForKey:feedIdStr];
appDelegate.storiesCollection.isSocialView = NO;
appDelegate.storiesCollection.isSavedView = NO;
2012-06-25 15:02:20 -07:00
}
2011-08-24 21:44:16 -07:00
// If all feeds are already showing, no need to remember this one.
// NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
if (!self.viewShowingAllFeeds) {
// [preferences boolForKey:@"show_feeds_after_being_read"]) {
2011-08-24 21:44:16 -07:00
[self.stillVisibleFeeds setObject:indexPath forKey:feedIdStr];
}
[appDelegate.storiesCollection setActiveFeed:feed];
[appDelegate.storiesCollection setActiveFolder:folderName];
2011-08-24 21:44:16 -07:00
appDelegate.readStories = [NSMutableArray array];
[appDelegate.folderCountCache removeObjectForKey:folderName];
appDelegate.storiesCollection.activeClassifiers = [NSMutableDictionary dictionary];
2011-08-24 21:44:16 -07:00
[appDelegate loadFeedDetailView];
2010-06-20 11:04:23 -04:00
}
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (appDelegate.hasNoSites) {
2012-08-02 19:43:55 -07:00
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
return kBlurblogTableViewRowHeight;
} else {
return kPhoneBlurblogTableViewRowHeight;
}
}
NSString *folderName;
if (indexPath.section == 0) {
folderName = @"river_global";
} else if (indexPath.section == 1) {
folderName = @"river_blurblogs";
} else {
folderName = [appDelegate.dictFoldersArray objectAtIndex:indexPath.section];
}
bool isFolderCollapsed = [appDelegate isFolderCollapsed:folderName];
if (isFolderCollapsed) {
return 0;
}
id feedId = [[appDelegate.dictFolders objectForKey:folderName] objectAtIndex:indexPath.row];
if (![self isFeedVisible:feedId]) {
return 0;
}
NSInteger height;
if ([folderName isEqualToString:@"river_blurblogs"] ||
[folderName isEqualToString:@"river_global"]) { // blurblogs
2012-08-02 12:01:42 -07:00
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
height = kBlurblogTableViewRowHeight;
2012-08-02 12:01:42 -07:00
} else {
height = kPhoneBlurblogTableViewRowHeight;
2012-08-02 12:01:42 -07:00
}
} else {
2012-08-02 12:01:42 -07:00
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
height = kTableViewRowHeight;
2012-08-02 12:01:42 -07:00
} else {
height = kPhoneTableViewRowHeight;
}
}
UIFontDescriptor *fontDescriptor = [self fontDescriptorUsingPreferredSize:UIFontTextStyleCaption1];
UIFont *font = [UIFont fontWithDescriptor:fontDescriptor size:0.0];
return height + font.pointSize*2;
}
- (UIFontDescriptor *)fontDescriptorUsingPreferredSize:(NSString *)textStyle {
UIFontDescriptor *fontDescriptor = appDelegate.fontDescriptorTitleSize;
if (fontDescriptor) return fontDescriptor;
fontDescriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:textStyle];
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
if (![userPreferences boolForKey:@"use_system_font_size"]) {
if ([[userPreferences stringForKey:@"feed_list_font_size"] isEqualToString:@"xs"]) {
fontDescriptor = [fontDescriptor fontDescriptorWithSize:10.0f];
} else if ([[userPreferences stringForKey:@"feed_list_font_size"] isEqualToString:@"small"]) {
fontDescriptor = [fontDescriptor fontDescriptorWithSize:11.0f];
} else if ([[userPreferences stringForKey:@"feed_list_font_size"] isEqualToString:@"medium"]) {
fontDescriptor = [fontDescriptor fontDescriptorWithSize:12.0f];
} else if ([[userPreferences stringForKey:@"feed_list_font_size"] isEqualToString:@"large"]) {
fontDescriptor = [fontDescriptor fontDescriptorWithSize:15.0f];
} else if ([[userPreferences stringForKey:@"feed_list_font_size"] isEqualToString:@"xl"]) {
fontDescriptor = [fontDescriptor fontDescriptorWithSize:17.0f];
2012-08-02 12:01:42 -07:00
}
}
return fontDescriptor;
}
- (UIView *)tableView:(UITableView *)tableView
viewForHeaderInSection:(NSInteger)section {
UIFontDescriptor *fontDescriptor = [self fontDescriptorUsingPreferredSize:UIFontTextStyleCaption1];
UIFont *font = [UIFont fontWithDescriptor:fontDescriptor size:0.0];
NSInteger height = kFolderTitleHeight;
CGRect rect = CGRectMake(0.0, 0.0, tableView.frame.size.width, height + font.pointSize*2);
FolderTitleView *folderTitle = [[FolderTitleView alloc] initWithFrame:rect];
folderTitle.section = (int)section;
return folderTitle;
}
- (IBAction)sectionTapped:(UIButton *)button {
button.backgroundColor = UIColorFromRGB(0x214607);
}
2012-08-08 10:57:38 -07:00
- (IBAction)sectionUntapped:(UIButton *)button {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.15 * NSEC_PER_SEC),
dispatch_get_main_queue(), ^{
button.backgroundColor = [UIColor clearColor];
});
}
- (IBAction)sectionUntappedOutside:(UIButton *)button {
button.backgroundColor = [UIColor clearColor];
}
- (CGFloat)tableView:(UITableView *)tableView
heightForHeaderInSection:(NSInteger)section {
if ([appDelegate.dictFoldersArray count] == 0) return 0;
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:section];
2012-07-20 22:00:30 -07:00
BOOL visibleFeeds = [[self.visibleFolders objectForKey:folderName] boolValue];
2014-10-22 16:39:37 -07:00
if (!visibleFeeds && section != 2 && section != 0 &&
![folderName isEqualToString:@"saved_stories"] &&
![folderName isEqualToString:@"read_stories"]) {
2012-07-20 22:00:30 -07:00
return 0;
}
UIFontDescriptor *fontDescriptor = [self fontDescriptorUsingPreferredSize:UIFontTextStyleCaption1];
UIFont *font = [UIFont fontWithDescriptor:fontDescriptor size:0.0];
NSInteger height = kFolderTitleHeight;
return height + font.pointSize*2;
}
- (void)didSelectSectionHeader:(UIButton *)button {
2015-11-05 16:43:43 -08:00
[self didSelectSectionHeaderWithTag:button.tag];
}
- (void)didSelectSectionHeaderWithTag:(NSInteger)tag {
if (self.appDelegate.inFeedDetail) {
return;
}
2012-07-27 19:42:19 -07:00
// reset pointer to the cells
self.currentRowAtIndexPath = nil;
2015-11-05 16:43:43 -08:00
self.currentSection = tag;
NSString *folder;
if (tag == 0) {
folder = @"river_global";
} else if (tag == 1) {
folder = @"river_blurblogs";
} else if (tag == 2) {
folder = @"everything";
} else {
2015-11-05 16:43:43 -08:00
folder = [NSString stringWithFormat:@"%ld", (long)tag];
}
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[appDelegate.dashboardViewController.storiesModule.view endEditing:YES];
}
2015-11-05 16:43:43 -08:00
[appDelegate loadRiverFeedDetailView:appDelegate.feedDetailViewController withFolder:folder];
}
- (void)selectEverything:(id)sender {
[self didSelectSectionHeaderWithTag:2];
}
#pragma mark - MCSwipeTableViewCellDelegate
// When the user starts swiping the cell this method is called
- (void)swipeTableViewCellDidStartSwiping:(MCSwipeTableViewCell *)cell {
// NSLog(@"Did start swiping the cell!");
}
// When the user is dragging, this method is called and return the dragged percentage from the border
- (void)swipeTableViewCell:(MCSwipeTableViewCell *)cell didSwipWithPercentage:(CGFloat)percentage {
// NSLog(@"Did swipe with percentage : %f", percentage);
}
- (void)swipeTableViewCell:(MCSwipeTableViewCell *)cell didEndSwipingSwipingWithState:(MCSwipeTableViewCellState)state mode:(MCSwipeTableViewCellMode)mode {
NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
NSIndexPath *indexPath = [self.feedTitlesTable indexPathForCell:cell];
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:indexPath.section];
NSString *feedId = [NSString stringWithFormat:@"%@",
[[appDelegate.dictFolders objectForKey:folderName]
objectAtIndex:indexPath.row]];
if (state == MCSwipeTableViewCellState1) {
if (indexPath.section == 1) {
// Profile
NSDictionary *feed = [appDelegate.dictSocialFeeds objectForKey:feedId];
appDelegate.activeUserProfileId = [NSString stringWithFormat:@"%@", [feed objectForKey:@"user_id"]];
appDelegate.activeUserProfileName = [NSString stringWithFormat:@"%@", [feed objectForKey:@"username"]];
[appDelegate showUserProfileModal:cell];
} else if ([[preferences stringForKey:@"feed_swipe_left"] isEqualToString:@"notifications"]) {
[appDelegate openNotificationsWithFeed:feedId sender:cell];
} else {
// Train
appDelegate.storiesCollection.activeFeed = [appDelegate.dictFeeds objectForKey:feedId];
[appDelegate openTrainSiteWithFeedLoaded:NO from:cell];
}
} else if (state == MCSwipeTableViewCellState3) {
// Mark read
[self markFeedRead:feedId cutoffDays:0];
2014-03-04 18:09:43 -08:00
if ([preferences boolForKey:@"show_feeds_after_being_read"]) {
[self.stillVisibleFeeds setObject:indexPath forKey:feedId];
}
[self.feedTitlesTable beginUpdates];
[self.feedTitlesTable reloadRowsAtIndexPaths:@[indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[self.feedTitlesTable endUpdates];
[self refreshHeaderCounts];
}
}
#pragma mark -
#pragma mark Mark Feeds as read
- (void)markFeedRead:(NSString *)feedId cutoffDays:(NSInteger)days {
[self markFeedsRead:@[feedId] cutoffDays:days];
}
- (void)markFeedsRead:(NSArray *)feedIds cutoffDays:(NSInteger)days {
if (feedIds.count == 1 && [feedIds.firstObject isEqual:@"everything"]) {
[self markEverythingReadWithDays:days];
return;
}
NSTimeInterval cutoffTimestamp = [[NSDate date] timeIntervalSince1970];
cutoffTimestamp -= (days * 60*60*24);
NSString *urlString = [NSString stringWithFormat:@"%@/reader/mark_feed_as_read",
2016-01-21 22:11:37 -08:00
self.appDelegate.url];
2017-03-19 18:15:36 -07:00
NSMutableDictionary *params = [NSMutableDictionary dictionary];
[params setObject:feedIds forKey:@"feed_id"];
if (days) {
[params setObject:[NSNumber numberWithInteger:cutoffTimestamp]
forKey:@"cutoff_timestamp"];
}
2017-03-19 18:15:36 -07:00
[appDelegate.networkManager POST:urlString parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
2017-04-03 12:49:01 -07:00
[self finishMarkAllAsRead:params];
2017-03-19 18:15:36 -07:00
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
[self requestFailedMarkStoryRead:error withParams:params];
}];
if (!days) {
for (NSString *feedId in feedIds) {
[appDelegate markFeedAllRead:feedId];
}
} else {
// [self showRefreshNotifier];
}
}
- (void)markEverythingReadWithDays:(NSInteger)days {
NSArray *feedIds = [appDelegate allFeedIds];
NSString *urlString = [NSString stringWithFormat:@"%@/reader/mark_all_as_read",
2016-01-21 22:11:37 -08:00
self.appDelegate.url];
2017-03-19 18:15:36 -07:00
NSMutableDictionary *params = [NSMutableDictionary dictionary];
[params setObject:[NSNumber numberWithInteger:days]
2017-03-19 18:15:36 -07:00
forKey:@"days"];
[appDelegate.networkManager POST:urlString parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
2017-04-03 12:49:01 -07:00
[self finishMarkAllAsRead:params];
2017-03-19 18:15:36 -07:00
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
[self requestFailedMarkStoryRead:error withParams:params];
}];
if (!days) {
for (NSString *feedId in feedIds) {
[appDelegate markFeedAllRead:feedId];
}
} else {
// [self showRefreshNotifier];
}
}
2015-11-13 21:54:32 -08:00
- (void)markVisibleStoriesRead {
NSDictionary *feedsStories = [appDelegate markVisibleStoriesRead];
NSString *urlString = [NSString stringWithFormat:@"%@/reader/mark_feed_stories_as_read",
2016-01-21 22:11:37 -08:00
self.appDelegate.url];
2017-04-03 12:49:01 -07:00
NSMutableDictionary *params = [NSMutableDictionary dictionary];
[params setObject:[feedsStories JSONRepresentation] forKey:@"feeds_stories"];
2017-04-03 12:49:01 -07:00
[appDelegate.networkManager POST:urlString parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
[self finishMarkAllAsRead:params];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
[self requestFailedMarkStoryRead:error withParams:params];
}];
2015-11-13 21:54:32 -08:00
}
2017-03-19 18:15:36 -07:00
- (void)requestFailedMarkStoryRead:(NSError *)error withParams:(NSDictionary *)params {
[appDelegate markStoriesRead:[params objectForKey:@"stories"]
inFeeds:[params objectForKey:@"feed_id"]
cutoffTimestamp:[[params objectForKey:@"cutoff_timestamp"] integerValue]];
[self showOfflineNotifier];
self.isOffline = YES;
[self.feedTitlesTable reloadData];
}
2017-03-19 18:15:36 -07:00
- (void)finishMarkAllAsRead:(NSDictionary *)params {
2017-04-03 12:49:01 -07:00
// This seems fishy post-ASI rewrite. This needs to know about a cutoff timestamp which it is never given.
self.isOffline = NO;
2017-03-19 18:15:36 -07:00
if ([[params objectForKey:@"cutoff_timestamp"] integerValue]) {
id feed;
2017-03-19 18:15:36 -07:00
if ([[params objectForKey:@"feed_id"] count] == 1) {
feed = [[params objectForKey:@"feed_id"] objectAtIndex:0];
}
[self refreshFeedList:feed];
2017-03-19 18:15:36 -07:00
} else if ([params objectForKey:@"feed_id"]) {
[appDelegate markFeedReadInCache:[params objectForKey:@"feed_id"]];
}
}
#pragma mark - Table Actions
- (void)didCollapseFolder:(UIButton *)button {
NSString *folderName;
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
if (button.tag == 0) {
folderName = @"river_global";
} else if (button.tag == 1) {
folderName = @"river_blurblogs";
} else {
folderName = [appDelegate.dictFoldersArray objectAtIndex:button.tag];
}
NSString *collapseKey = [NSString stringWithFormat:@"folderCollapsed:%@", folderName];
bool isFolderCollapsed = [userPreferences boolForKey:collapseKey];
if (isFolderCollapsed) {
// Expand folder
[userPreferences setBool:NO forKey:collapseKey];
} else {
// Collapse folder
[userPreferences setBool:YES forKey:collapseKey];
}
[userPreferences synchronize];
appDelegate.collapsedFolders = nil;
[self.feedTitlesTable beginUpdates];
[self.feedTitlesTable reloadSections:[NSIndexSet indexSetWithIndex:button.tag]
withRowAnimation:UITableViewRowAnimationFade];
[self.feedTitlesTable endUpdates];
// Scroll to section header if collapse causes it to scroll far off screen
NSArray *indexPathsVisibleCells = [self.feedTitlesTable indexPathsForVisibleRows];
BOOL firstFeedInFolderVisible = NO;
for (NSIndexPath *indexPath in indexPathsVisibleCells) {
if (indexPath.row == 0 && indexPath.section == button.tag) {
firstFeedInFolderVisible = YES;
}
}
if (!firstFeedInFolderVisible) {
CGRect headerRect = [self.feedTitlesTable rectForHeaderInSection:button.tag];
CGPoint headerPoint = CGPointMake(headerRect.origin.x, headerRect.origin.y);
[self.feedTitlesTable setContentOffset:headerPoint animated:YES];
}
}
- (BOOL)isFeedVisible:(id)feedId {
2013-10-18 14:17:01 -07:00
if (![feedId isKindOfClass:[NSString class]]) {
feedId = [NSString stringWithFormat:@"%@",feedId];
}
2016-03-26 21:27:25 -07:00
NSDictionary *unreadCounts = self.appDelegate.dictUnreadCounts[feedId];
NSIndexPath *stillVisible = self.stillVisibleFeeds[feedId];
if (!stillVisible && self.appDelegate.isSavedStoriesIntelligenceMode) {
return [self.appDelegate savedStoriesCountForFeed:feedId] > 0 || [self.appDelegate isSavedFeed:feedId];
} else if (!stillVisible &&
appDelegate.selectedIntelligence >= 1 &&
[[unreadCounts objectForKey:@"ps"] intValue] <= 0) {
return NO;
} else if (!stillVisible &&
!self.viewShowingAllFeeds &&
([[unreadCounts objectForKey:@"ps"] intValue] <= 0 &&
[[unreadCounts objectForKey:@"nt"] intValue] <= 0)) {
return NO;
}
return YES;
}
2012-08-12 16:50:34 -07:00
- (void)changeToAllMode {
[self.intelligenceControl setSelectedSegmentIndex:0];
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
2012-08-12 16:50:34 -07:00
[userPreferences setInteger:-1 forKey:@"selectedIntelligence"];
[userPreferences synchronize];
}
- (void)selectPreviousIntelligence:(id)sender {
NSInteger selectedSegmentIndex = intelligenceControl.selectedSegmentIndex;
if (selectedSegmentIndex <= 0)
return;
[intelligenceControl setSelectedSegmentIndex:selectedSegmentIndex - 1];
[self selectIntelligence];
}
- (void)selectNextIntelligence:(id)sender {
NSInteger selectedSegmentIndex = intelligenceControl.selectedSegmentIndex;
2016-03-26 21:27:25 -07:00
if (selectedSegmentIndex >= intelligenceControl.numberOfSegments - 1)
return;
[intelligenceControl setSelectedSegmentIndex:selectedSegmentIndex + 1];
[self selectIntelligence];
}
- (IBAction)selectIntelligence {
[MBProgressHUD hideHUDForView:self.feedTitlesTable animated:NO];
2017-09-27 12:19:58 -07:00
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.mode = MBProgressHUDModeText;
hud.removeFromSuperViewOnHide = YES;
NSIndexPath *topRow;
if ([[self.feedTitlesTable indexPathsForVisibleRows] count]) {
topRow = [[self.feedTitlesTable indexPathsForVisibleRows] objectAtIndex:0];
}
NSInteger selectedSegmentIndex = [self.intelligenceControl selectedSegmentIndex];
self.stillVisibleFeeds = [NSMutableDictionary dictionary];
NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults];
int direction;
if (selectedSegmentIndex == 0) {
hud.labelText = @"All Stories";
2012-07-16 19:45:14 -07:00
[userPreferences setInteger:-1 forKey:@"selectedIntelligence"];
[userPreferences synchronize];
direction = -1;
2012-07-09 17:42:32 -07:00
self.viewShowingAllFeeds = YES;
[appDelegate setSelectedIntelligence:0];
2016-03-26 21:27:25 -07:00
} else if (selectedSegmentIndex == 1) {
hud.labelText = @"Unread Stories";
2012-07-16 19:45:14 -07:00
[userPreferences setInteger:0 forKey:@"selectedIntelligence"];
[userPreferences synchronize];
direction = self.viewShowingAllFeeds ? 1 : -1;
2012-07-09 17:42:32 -07:00
self.viewShowingAllFeeds = NO;
[appDelegate setSelectedIntelligence:0];
2016-03-26 21:27:25 -07:00
} else if (selectedSegmentIndex == 2) {
hud.labelText = @"Focus Stories";
2012-07-16 19:45:14 -07:00
[userPreferences setInteger:1 forKey:@"selectedIntelligence"];
[userPreferences synchronize];
direction = 1;
self.viewShowingAllFeeds = NO;
[appDelegate setSelectedIntelligence:1];
2016-03-26 21:27:25 -07:00
} else {
hud.labelText = @"Saved Stories";
[userPreferences setInteger:2 forKey:@"selectedIntelligence"];
[userPreferences synchronize];
direction = 1;
self.viewShowingAllFeeds = NO;
[appDelegate setSelectedIntelligence:2];
2011-08-24 21:44:16 -07:00
}
2015-12-07 16:09:49 -08:00
[self calculateFeedLocations];
[self.feedTitlesTable reloadData];
2012-06-26 12:29:37 -07:00
NSIndexPath *newMiddleRow;
if (topRow && [self.feedTitlesTable numberOfRowsInSection:topRow.section] == 0) {
newMiddleRow = [[self.feedTitlesTable indexPathsForVisibleRows] objectAtIndex:0];
} else if (topRow) {
newMiddleRow = [NSIndexPath indexPathForRow:0 inSection:topRow.section];
}
if (newMiddleRow) {
[self.feedTitlesTable scrollToRowAtIndexPath:newMiddleRow
atScrollPosition:UITableViewScrollPositionTop
animated:NO];
}
[self.feedTitlesTable
reloadRowsAtIndexPaths:[self.feedTitlesTable indexPathsForVisibleRows]
withRowAnimation:direction == 1 ? UITableViewRowAnimationLeft : UITableViewRowAnimationRight];
2013-10-18 14:17:01 -07:00
for (UITableViewCell *cell in self.feedTitlesTable.visibleCells) {
[cell setNeedsDisplay];
}
[hud hide:YES afterDelay:0.5];
[self showExplainerOnEmptyFeedlist];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
2016-03-26 21:27:25 -07:00
FeedDetailViewController *storiesModule = self.appDelegate.dashboardViewController.storiesModule;
storiesModule.storiesCollection.feedPage = 0;
storiesModule.storiesCollection.storyCount = 0;
storiesModule.pageFinished = NO;
[storiesModule.storiesCollection calculateStoryLocations];
[storiesModule reloadData];
}
}
- (void)showExplainerOnEmptyFeedlist {
NSInteger intelligenceLevel = [appDelegate selectedIntelligence];
if (intelligenceLevel > 0) {
BOOL hasFocusStory = NO;
for (id feedId in appDelegate.dictUnreadCounts) {
NSDictionary *unreadCounts = [appDelegate.dictUnreadCounts objectForKey:feedId];
if ([[unreadCounts objectForKey:@"ps"] intValue] > 0) {
hasFocusStory = YES;
break;
}
}
if (!hasFocusStory) {
self.noFocusMessage.hidden = NO;
} else {
self.noFocusMessage.hidden = YES;
}
} else {
self.noFocusMessage.hidden = YES;
}
}
- (void)redrawUnreadCounts {
FeedTableCell *cell = (FeedTableCell *)[self.feedTitlesTable
cellForRowAtIndexPath:self.currentRowAtIndexPath];
if (cell) {
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:self.currentRowAtIndexPath.section];
id feedId = [[appDelegate.dictFolders objectForKey:folderName] objectAtIndex:self.currentRowAtIndexPath.row];
NSString *feedIdStr = [NSString stringWithFormat:@"%@",feedId];
NSDictionary *unreadCounts = [appDelegate.dictUnreadCounts objectForKey:feedIdStr];
if (![cell respondsToSelector:@selector(setPositiveCount:)]) return;
[cell setPositiveCount:[[unreadCounts objectForKey:@"ps"] intValue]];
[cell setNeutralCount:[[unreadCounts objectForKey:@"nt"] intValue]];
[cell setNegativeCount:[[unreadCounts objectForKey:@"ng"] intValue]];
} else {
[self.feedTitlesTable reloadData];
}
}
- (void)resetupGestures {
while ([self.feedTitlesTable dequeueReusableCellWithIdentifier:@"FeedCellIdentifier"]) {}
[self.feedTitlesTable reloadData];
}
- (void)calculateFeedLocations {
self.activeFeedLocations = [NSMutableDictionary dictionary];
self.visibleFolders = [NSMutableDictionary dictionary];
for (NSString *folderName in appDelegate.dictFoldersArray) {
if ([folderName isEqualToString:@"river_global"]) continue;
NSArray *folder = [appDelegate.dictFolders objectForKey:folderName];
2011-08-24 21:44:16 -07:00
NSMutableArray *feedLocations = [NSMutableArray array];
2012-06-26 11:45:42 -07:00
for (int f = 0; f < [folder count]; f++) {
2011-08-24 21:44:16 -07:00
id feedId = [folder objectAtIndex:f];
if ([self isFeedVisible:feedId]) {
2011-08-24 21:44:16 -07:00
NSNumber *location = [NSNumber numberWithInt:f];
[feedLocations addObject:location];
if (![[self.visibleFolders objectForKey:folderName] boolValue]) {
[self.visibleFolders setObject:[NSNumber numberWithBool:YES] forKey:folderName];
2011-08-24 21:44:16 -07:00
}
}
}
[self.activeFeedLocations setObject:feedLocations forKey:folderName];
}
}
+ (int)computeMaxScoreForFeed:(NSDictionary *)feed {
2011-08-24 21:44:16 -07:00
int maxScore = -2;
if ([[feed objectForKey:@"ng"] intValue] > 0) maxScore = -1;
if ([[feed objectForKey:@"nt"] intValue] > 0) maxScore = 0;
if ([[feed objectForKey:@"ps"] intValue] > 0) maxScore = 1;
return maxScore;
}
#pragma mark -
#pragma mark Favicons
- (void)loadFavicons {
NSString *urlString = [NSString stringWithFormat:@"%@/reader/favicons",
2016-01-21 22:11:37 -08:00
self.appDelegate.url];
2017-03-24 17:30:46 -07:00
[appDelegate.networkManager GET:urlString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
[self saveAndDrawFavicons:responseObject];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
[self requestFailed:error];
}];
}
2012-06-26 11:45:42 -07:00
- (void)loadAvatars {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0ul);
2012-06-26 11:45:42 -07:00
dispatch_async(queue, ^{
for (NSString *feed_id in [appDelegate.dictSocialFeeds allKeys]) {
2012-06-26 11:45:42 -07:00
NSDictionary *feed = [appDelegate.dictSocialFeeds objectForKey:feed_id];
NSURL *imageURL = [NSURL URLWithString:[feed objectForKey:@"photo_url"]];
2012-06-26 11:45:42 -07:00
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
if (!imageData) continue;
2012-06-26 11:45:42 -07:00
UIImage *faviconImage = [UIImage imageWithData:imageData];
if (!faviconImage) continue;
2012-07-11 18:08:07 -07:00
faviconImage = [Utilities roundCorneredImage:faviconImage radius:6];
[appDelegate saveFavicon:faviconImage feedId:feed_id];
2012-06-26 11:45:42 -07:00
}
dispatch_async(dispatch_get_main_queue(), ^{
2012-06-26 11:45:42 -07:00
[self.feedTitlesTable reloadData];
});
});
}
2012-07-11 18:08:07 -07:00
2017-03-24 17:30:46 -07:00
- (void)saveAndDrawFavicons:(NSDictionary *)results {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0ul);
dispatch_async(queue, ^{
for (id feed_id in results) {
// NSMutableDictionary *feed = [[appDelegate.dictFeeds objectForKey:feed_id] mutableCopy];
// [feed setValue:[results objectForKey:feed_id] forKey:@"favicon"];
// [appDelegate.dictFeeds setValue:feed forKey:feed_id];
if (![appDelegate.dictFeeds objectForKey:feed_id]) continue;
NSString *favicon = [results objectForKey:feed_id];
if ((NSNull *)favicon != [NSNull null] && [favicon length] > 0) {
NSData *imageData = [NSData dataWithBase64EncodedString:favicon];
UIImage *faviconImage = [UIImage imageWithData:imageData];
[appDelegate saveFavicon:faviconImage feedId:feed_id];
}
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.feedTitlesTable reloadData];
[self loadAvatars];
});
});
}
2017-03-24 17:30:46 -07:00
- (void)requestFailed:(NSError *)error {
NSLog(@"Error: %@", error);
[appDelegate informError:error];
}
#pragma mark -
#pragma mark PullToRefresh
- (void)refresh:(UIRefreshControl *)refreshControl {
2012-08-16 20:10:50 -07:00
self.inPullToRefresh_ = YES;
[appDelegate reloadFeedsView:NO];
}
- (void)finishRefresh {
self.inPullToRefresh_ = NO;
[self.refreshControl endRefreshing];
}
- (void)refreshFeedList {
[self refreshFeedList:nil];
}
- (void)refreshFeedList:(id)feedId {
// refresh the feed
NSString *urlString;
2016-03-26 21:27:25 -07:00
if (feedId) {
urlString = [NSString stringWithFormat:@"%@/reader/feed_unread_count?feed_id=%@",
2016-01-21 22:11:37 -08:00
self.appDelegate.url, feedId];
} else {
urlString = [NSString stringWithFormat:@"%@/reader/refresh_feeds",
2016-01-21 22:11:37 -08:00
self.appDelegate.url];
}
if (!feedId) {
[self.appDelegate cancelOfflineQueue];
}
2017-03-24 17:30:46 -07:00
[appDelegate.networkManager GET:urlString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
[self finishRefreshingFeedList:responseObject feedId:feedId];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
2017-06-01 21:19:54 -07:00
[self finishRefresh];
2017-03-24 17:30:46 -07:00
if ([httpResponse statusCode] == 403) {
NSLog(@"Showing login after refresh");
return [appDelegate showLogin];
} else if ([httpResponse statusCode] == 503) {
return [self informError:@"In maintenance mode"];
} else if ([httpResponse statusCode] >= 500) {
return [self informError:@"The server barfed!"];
}
2017-06-01 21:19:54 -07:00
2017-03-24 17:30:46 -07:00
[self requestFailed:error];
}];
dispatch_async(dispatch_get_main_queue(), ^{
if (!feedId) {
[self showCountingNotifier];
}
});
}
2017-03-24 17:30:46 -07:00
- (void)finishRefreshingFeedList:(NSDictionary *)results feedId:(NSString *)feedId {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
(unsigned long)NULL), ^(void) {
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;
// Check if a feed goes from visible to hidden, but doesn't disappear.
if ((intelligenceLevel > 0 &&
[[unreadCount objectForKey:@"ps"] intValue] > 0 &&
[[newFeedCount objectForKey:@"ps"] intValue] == 0) ||
(intelligenceLevel == 0 &&
([[unreadCount objectForKey:@"ps"] intValue] > 0 ||
[[unreadCount objectForKey:@"nt"] intValue] > 0) &&
[[newFeedCount objectForKey:@"ps"] intValue] == 0 &&
[[newFeedCount objectForKey:@"nt"] intValue] == 0)) {
NSIndexPath *indexPath;
for (int s=0; s < [appDelegate.dictFoldersArray count]; s++) {
NSString *folderName = [appDelegate.dictFoldersArray objectAtIndex:s];
NSArray *activeFolderFeeds = [self.activeFeedLocations objectForKey:folderName];
NSArray *originalFolder = [appDelegate.dictFolders objectForKey:folderName];
for (int l=0; l < [activeFolderFeeds count]; l++) {
if ([[originalFolder objectAtIndex:[[activeFolderFeeds objectAtIndex:l] intValue]] intValue] == [feed intValue]) {
indexPath = [NSIndexPath indexPathForRow:l inSection:s];
break;
}
}
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];
2012-08-09 10:18:15 -07:00
}
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;
[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];
}
dispatch_async(dispatch_get_main_queue(), ^{
[appDelegate.folderCountCache removeAllObjects];
[self.feedTitlesTable reloadData];
[self refreshHeaderCounts];
2017-03-24 17:30:46 -07:00
if (!feedId) {
[self.appDelegate startOfflineQueue];
}
[self loadFavicons];
});
});
}
- (void)resetToolbar {
self.navigationItem.leftBarButtonItem = nil;
self.navigationItem.titleView = nil;
self.navigationItem.rightBarButtonItem = nil;
}
- (void)layoutHeaderCounts:(UIInterfaceOrientation)orientation {
if (!orientation) {
orientation = [UIApplication sharedApplication].statusBarOrientation;
}
BOOL isShort = NO;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone &&
UIInterfaceOrientationIsLandscape(orientation)) {
isShort = YES;
}
int yOffset = isShort ? 0 : 6;
UIView *userInfoView = [[UIView alloc]
initWithFrame:CGRectMake(0, 0,
self.navigationController.toolbar.frame.size.width,
self.navigationController.toolbar.frame.size.height)];
// adding user avatar to left
NSURL *imageURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@",
[appDelegate.dictSocialProfile
2013-12-06 16:29:15 -08:00
objectForKey:@"large_photo_url"]]];
userAvatarButton = [UIBarButtonItem barItemWithImage:[UIImage alloc]
target:self
action:@selector(showUserProfile)];
2017-09-27 12:19:58 -07:00
userAvatarButton.customView.frame = CGRectMake(0, yOffset + 1, 32, 32);
userAvatarButton.accessibilityLabel = @"User info";
userAvatarButton.accessibilityHint = @"Double-tap for information about your account.";
NSMutableURLRequest *avatarRequest = [NSMutableURLRequest requestWithURL:imageURL];
[avatarRequest addValue:@"image/*" forHTTPHeaderField:@"Accept"];
[avatarRequest setTimeoutInterval:30.0];
avatarImageView = [[UIImageView alloc] initWithFrame:userAvatarButton.customView.frame];
typeof(self) __weak weakSelf = self;
[avatarImageView setImageWithURLRequest:avatarRequest placeholderImage:nil success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
typeof(weakSelf) __strong strongSelf = weakSelf;
2017-10-03 18:39:06 -07:00
image = [Utilities imageWithImage:image convertToSize:CGSizeMake(32, 32)];
2013-12-06 16:29:15 -08:00
image = [Utilities roundCorneredImage:image radius:6];
[(UIButton *)strongSelf.userAvatarButton.customView setImage:image forState:UIControlStateNormal];
2017-10-03 18:39:06 -07:00
} failure:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nonnull response, NSError * _Nonnull error) {
NSLog(@"Could not fetch user avatar: %@", error);
}];
// self.navigationItem.leftBarButtonItem = userInfoBarButton;
// [userInfoView addSubview:userAvatarButton];
2017-10-03 18:39:06 -07:00
userLabel = [[UILabel alloc] initWithFrame:CGRectMake(8, yOffset, userInfoView.frame.size.width, 16)];
2013-02-15 16:41:20 -08:00
userLabel.text = appDelegate.activeUsername;
2013-10-18 18:37:11 -07:00
userLabel.font = userLabelFont;
2013-02-15 16:41:20 -08:00
userLabel.textColor = UIColorFromRGB(0x404040);
userLabel.backgroundColor = [UIColor clearColor];
userLabel.accessibilityLabel = [NSString stringWithFormat:@"Logged in as %@", appDelegate.activeUsername];
[userLabel sizeToFit];
2013-02-15 16:41:20 -08:00
[userInfoView addSubview:userLabel];
[appDelegate.folderCountCache removeObjectForKey:@"everything"];
yellowIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"g_icn_unread"]];
[userInfoView addSubview:yellowIcon];
2013-02-15 16:41:20 -08:00
neutralCount = [[UILabel alloc] init];
neutralCount.font = [UIFont fontWithName:@"Helvetica" size:11];
2013-02-15 16:41:20 -08:00
neutralCount.textColor = UIColorFromRGB(0x707070);
neutralCount.backgroundColor = [UIColor clearColor];
[userInfoView addSubview:neutralCount];
greenIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"g_icn_focus"]];
[userInfoView addSubview:greenIcon];
2013-02-15 16:41:20 -08:00
positiveCount = [[UILabel alloc] init];
positiveCount.font = [UIFont fontWithName:@"Helvetica" size:11];
2013-02-15 16:41:20 -08:00
positiveCount.textColor = UIColorFromRGB(0x707070);
positiveCount.backgroundColor = [UIColor clearColor];
[userInfoView addSubview:positiveCount];
[userInfoView sizeToFit];
userInfoBarButton = [[UIBarButtonItem alloc]
initWithCustomView:userInfoView];
UIBarButtonItem *spacer = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil
action:nil];
spacer.width = -8;
self.navigationItem.leftBarButtonItems = [NSArray arrayWithObjects:
spacer,
userAvatarButton,
userInfoBarButton, nil];
2013-02-15 16:41:20 -08:00
}
- (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]];
positiveCount.accessibilityLabel = [NSString stringWithFormat:@"%@ focused stories", positiveCount.text];
neutralCount.text = [formatter stringFromNumber:[NSNumber numberWithInt:counts.nt]];
neutralCount.accessibilityLabel = [NSString stringWithFormat:@"%@ unread stories", neutralCount.text];
yellowIcon.frame = CGRectMake(CGRectGetMinX(userLabel.frame), CGRectGetMaxY(userLabel.frame) + 4, 8, 8);
neutralCount.frame = CGRectMake(CGRectGetMaxX(yellowIcon.frame) + 2,
CGRectGetMinY(yellowIcon.frame) - 2, 100, 16);
[neutralCount sizeToFit];
greenIcon.frame = CGRectMake(CGRectGetMaxX(neutralCount.frame) + 8,
CGRectGetMinY(yellowIcon.frame), 8, 8);
positiveCount.frame = CGRectMake(CGRectGetMaxX(greenIcon.frame) + 2,
CGRectGetMinY(greenIcon.frame) - 2, 100, 16);
[positiveCount sizeToFit];
2017-05-10 22:31:20 -07:00
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *appUnreadBadge = [prefs stringForKey:@"app_unread_badge"];
if ([appUnreadBadge isEqualToString:@"unread"]) {
[appDelegate registerForBadgeNotifications];
2017-05-10 22:31:20 -07:00
[UIApplication sharedApplication].applicationIconBadgeNumber = counts.ps + counts.nt;
} else if ([appUnreadBadge isEqualToString:@"focus"]) {
[appDelegate registerForBadgeNotifications];
2017-05-10 22:31:20 -07:00
[UIApplication sharedApplication].applicationIconBadgeNumber = counts.ps;
} else {
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
}
}
- (void)showRefreshNotifier {
self.notifier.style = NBSyncingStyle;
self.notifier.title = @"On its way...";
[self.notifier setProgress:0];
[self.notifier show];
}
- (void)showCountingNotifier {
self.notifier.style = NBSyncingStyle;
self.notifier.title = @"Counting is difficult...";
[self.notifier setProgress:0];
[self.notifier show];
2016-11-02 17:56:08 -07:00
[self finishRefresh];
}
- (void)showSyncingNotifier {
self.notifier.style = NBSyncingStyle;
self.notifier.title = @"Syncing stories...";
[self.notifier setProgress:0];
[self.notifier show];
2016-11-02 17:56:08 -07:00
[self finishRefresh];
}
- (void)showDoneNotifier {
self.notifier.style = NBDoneStyle;
self.notifier.title = @"All done";
[self.notifier setProgress:0];
[self.notifier show];
[self finishRefresh];
}
- (void)showSyncingNotifier:(float)progress hoursBack:(NSInteger)hours {
// [self.notifier hide];
self.notifier.style = NBSyncingProgressStyle;
if (hours < 2) {
self.notifier.title = @"Storing past hour";
} else if (hours < 24) {
self.notifier.title = [NSString stringWithFormat:@"Storing past %ld hours", (long)hours];
} else if (hours < 48) {
self.notifier.title = @"Storing yesterday";
} else {
self.notifier.title = [NSString stringWithFormat:@"Storing past %d days", (int)round(hours / 24.f)];
}
[self.notifier setProgress:progress];
[self.notifier setNeedsDisplay];
[self.notifier show];
}
- (void)showCachingNotifier:(float)progress hoursBack:(NSInteger)hours {
// [self.notifier hide];
self.notifier.style = NBSyncingProgressStyle;
if (hours < 2) {
self.notifier.title = @"Images from last hour";
} else if (hours < 24) {
self.notifier.title = [NSString stringWithFormat:@"Images from %ld hours ago", (long)hours];
} else if (hours < 48) {
self.notifier.title = @"Images from yesterday";
} else {
self.notifier.title = [NSString stringWithFormat:@"Images from %d days ago", (int)round(hours / 24.f)];
}
[self.notifier setProgress:progress];
[self.notifier setNeedsDisplay];
[self.notifier show];
}
- (void)showOfflineNotifier {
self.notifier.style = NBOfflineStyle;
self.notifier.title = @"Offline";
[self.notifier show];
}
- (void)hideNotifier {
2013-07-16 18:06:36 -07:00
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.25 * NSEC_PER_SEC),
dispatch_get_main_queue(), ^{
[self.notifier hide];
});
}
@end