diff --git a/WordPress/Classes/CommentsViewController.m b/WordPress/Classes/CommentsViewController.m index ce9637052522..22520ebb726a 100644 --- a/WordPress/Classes/CommentsViewController.m +++ b/WordPress/Classes/CommentsViewController.m @@ -62,11 +62,6 @@ - (void)viewDidLoad { self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; } -- (UIColor *)backgroundColorForRefreshHeaderView -{ - return [WPStyleGuide itsEverywhereGrey]; -} - - (void)viewWillAppear:(BOOL)animated { WPFLogMethod(); @@ -145,7 +140,7 @@ - (void)setWantedCommentId:(NSNumber *)wantedCommentId { [self willChangeValueForKey:@"wantedCommentId"]; _wantedCommentId = wantedCommentId; [self didChangeValueForKey:@"wantedCommentId"]; - [self syncItemsWithUserInteraction:NO]; + [self syncItems]; } } } @@ -228,7 +223,7 @@ - (UITableViewCell *)newCell { return cell; } -- (void)syncItemsWithUserInteraction:(BOOL)userInteraction success:(void (^)())success failure:(void (^)(NSError *))failure { +- (void)syncItemsWithSuccess:(void (^)())success failure:(void (^)(NSError *))failure { [self.blog syncCommentsWithSuccess:success failure:failure]; } diff --git a/WordPress/Classes/NotificationsViewController.m b/WordPress/Classes/NotificationsViewController.m index 5b53f02fc34a..e36402c33d8d 100644 --- a/WordPress/Classes/NotificationsViewController.m +++ b/WordPress/Classes/NotificationsViewController.m @@ -77,9 +77,13 @@ - (void)viewDidAppear:(BOOL)animated { } _isPushingViewController = NO; - // If table is at the top, simulate a pull to refresh - BOOL simulatePullToRefresh = (self.tableView.contentOffset.y == 0); - [self syncItemsWithUserInteraction:simulatePullToRefresh]; + + // If table is at the top (i.e. freshly opened), do some extra work + if (self.tableView.contentOffset.y == 0) { + [self pruneOldNotes]; + } + + [self syncItems]; [self refreshUnreadNotes]; } @@ -89,10 +93,6 @@ - (void)viewDidDisappear:(BOOL)animated { [self pruneOldNotes]; } -- (UIColor *)backgroundColorForRefreshHeaderView -{ - return [WPStyleGuide itsEverywhereGrey]; -} #pragma mark - Custom methods @@ -141,7 +141,7 @@ - (void)refreshFromPushNotification { [self.panelNavigationController popToRootViewControllerAnimated:YES]; [self.tableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES]; if (![self isSyncing]) { - [self syncItemsWithUserInteraction:NO]; + [self syncItems]; } } @@ -234,10 +234,12 @@ - (void)configureCell:(NewNotificationsTableViewCell *)cell atIndexPath:(NSIndex cell.note = [self.resultsController objectAtIndexPath:indexPath]; } -- (void)syncItemsWithUserInteraction:(BOOL)userInteraction success:(void (^)())success failure:(void (^)(NSError *error))failure { - if (userInteraction) { - [self pruneOldNotes]; - } +- (void)syncItemsViaUserInteractionWithSuccess:(void (^)())success failure:(void (^)(NSError *))failure { + [self pruneOldNotes]; + [self syncItemsWithSuccess:success failure:failure]; +} + +- (void)syncItemsWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure { NSNumber *timestamp; NSArray *notes = [self.resultsController fetchedObjects]; if ([notes count] > 0) { diff --git a/WordPress/Classes/PagesViewController.m b/WordPress/Classes/PagesViewController.m index f472ce3857a0..5cff28c6935e 100644 --- a/WordPress/Classes/PagesViewController.m +++ b/WordPress/Classes/PagesViewController.m @@ -33,7 +33,7 @@ - (NSString *)noResultsText } -- (void)syncItemsWithUserInteraction:(BOOL)userInteraction success:(void (^)())success failure:(void (^)(NSError *))failure { +- (void)syncItemsWithSuccess:(void (^)())success failure:(void (^)(NSError *))failure { [self.blog syncPagesWithSuccess:success failure:failure loadMore: NO]; } diff --git a/WordPress/Classes/PostsViewController.m b/WordPress/Classes/PostsViewController.m index 41877a88b982..8e2ae4631fb6 100644 --- a/WordPress/Classes/PostsViewController.m +++ b/WordPress/Classes/PostsViewController.m @@ -126,11 +126,6 @@ - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } -- (UIColor *)backgroundColorForRefreshHeaderView -{ - return [WPStyleGuide itsEverywhereGrey]; -} - - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { WordPressAppDelegate *delegate = (WordPressAppDelegate*)[[UIApplication sharedApplication] delegate]; @@ -248,7 +243,7 @@ - (void)deletePostAtIndexPath:(NSIndexPath *)indexPath{ } else { [[NSNotificationCenter defaultCenter] postNotificationName:kXML_RPC_ERROR_OCCURS object:error userInfo:errInfo]; } - [self syncItemsWithUserInteraction:NO]; + [self syncItems]; if(IS_IPAD && self.postReaderViewController) { if(self.postReaderViewController.apost == post) { //push an the W logo on the right. @@ -368,13 +363,13 @@ - (NSString *)sectionNameKeyPath { return @"remoteStatusNumber"; } -- (void)syncItemsWithUserInteraction:(BOOL)userInteraction success:(void (^)())success failure:(void (^)(NSError *))failure { +- (void)syncItemsViaUserInteractionWithSuccess:(void (^)())success failure:(void (^)(NSError *))failure { // If triggered by a pull to refresh, sync categories, post formats, ... - if (userInteraction) { - [self.blog syncBlogPostsWithSuccess:success failure:failure]; - } else { - [self.blog syncPostsWithSuccess:success failure:failure loadMore:NO]; - } + [self.blog syncBlogPostsWithSuccess:success failure:failure]; +} + +- (void)syncItemsWithSuccess:(void (^)())success failure:(void (^)(NSError *))failure { + [self.blog syncPostsWithSuccess:success failure:failure loadMore:NO]; } - (UITableViewCell *)newCell { diff --git a/WordPress/Classes/ReaderPostsViewController.m b/WordPress/Classes/ReaderPostsViewController.m index e8d7041cf3f3..0952dd9bc1ec 100644 --- a/WordPress/Classes/ReaderPostsViewController.m +++ b/WordPress/Classes/ReaderPostsViewController.m @@ -54,7 +54,6 @@ - (void)fetchBlogsAndPrimaryBlog; - (void)handleReblogButtonTapped:(id)sender; - (void)showReblogForm; - (void)hideReblogForm; -- (void)syncItemsWithSuccess:(void (^)())success failure:(void (^)(NSError *))failure; - (void)onSyncSuccess:(AFHTTPRequestOperation *)operation response:(id)responseObject; - (void)handleKeyboardDidShow:(NSNotification *)notification; - (void)handleKeyboardWillHide:(NSNotification *)notification; @@ -629,11 +628,11 @@ - (BOOL)hasMoreContent { } -- (void)syncItemsWithUserInteraction:(BOOL)userInteraction success:(void (^)())success failure:(void (^)(NSError *))failure { +- (void)syncItemsWithSuccess:(void (^)())success failure:(void (^)(NSError *))failure { WPFLogMethod(); // if needs auth. if([WPCookie hasCookieForURL:[NSURL URLWithString:@"https://wordpress.com"] andUsername:[[WPAccount defaultWordPressComAccount] username]]) { - [self syncItemsWithSuccess:success failure:failure]; + [self syncReaderItemsWithSuccess:success failure:failure]; return; } @@ -656,17 +655,17 @@ - (void)syncItemsWithUserInteraction:(BOOL)userInteraction success:(void (^)())s AFHTTPRequestOperation *authRequest = [[AFHTTPRequestOperation alloc] initWithRequest:mRequest]; [authRequest setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { [[WordPressAppDelegate sharedWordPressApplicationDelegate] useAppUserAgent]; - [self syncItemsWithSuccess:success failure:failure]; + [self syncReaderItemsWithSuccess:success failure:failure]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { [[WordPressAppDelegate sharedWordPressApplicationDelegate] useAppUserAgent]; - [self syncItemsWithSuccess:success failure:failure]; + [self syncReaderItemsWithSuccess:success failure:failure]; }]; [authRequest start]; } -- (void)syncItemsWithSuccess:(void (^)())success failure:(void (^)(NSError *))failure { +- (void)syncReaderItemsWithSuccess:(void (^)())success failure:(void (^)(NSError *))failure { WPFLogMethod(); NSString *endpoint = [ReaderPost currentEndpoint]; NSNumber *numberToSync = [NSNumber numberWithInteger:ReaderPostsToSync]; @@ -834,9 +833,6 @@ - (void)readerTopicChanged { if ([WordPressAppDelegate sharedWordPressApplicationDelegate].connectionAvailable == YES && ![self isSyncing] ) { [[NSUserDefaults standardUserDefaults] removeObjectForKey:ReaderLastSyncDateKey]; [NSUserDefaults resetStandardUserDefaults]; - if (IS_IPAD) { - [self simulatePullToRefresh]; - } } if ([self isCurrentCategoryFreshlyPressed]) { diff --git a/WordPress/Classes/WPTableViewController.h b/WordPress/Classes/WPTableViewController.h index 023c3a37a6e7..8695eccecdfb 100644 --- a/WordPress/Classes/WPTableViewController.h +++ b/WordPress/Classes/WPTableViewController.h @@ -9,16 +9,13 @@ #import "Blog.h" #import "SettingsViewControllerDelegate.h" -//@interface WPTableViewController : UITableViewController -@interface WPTableViewController : UIViewController +@interface WPTableViewController : UITableViewController @property (nonatomic, strong) Blog *blog; -@property (nonatomic, strong) UITableView *tableView; @property (nonatomic, readonly) BOOL isScrolling; @property (nonatomic) BOOL incrementalLoadingSupported; - (void)promptForPassword; -- (UIColor *)backgroundColorForRefreshHeaderView; - (NSString *)noResultsText; @end diff --git a/WordPress/Classes/WPTableViewController.m b/WordPress/Classes/WPTableViewController.m index ebe02ee8b34e..7e3fef7b37ab 100644 --- a/WordPress/Classes/WPTableViewController.m +++ b/WordPress/Classes/WPTableViewController.m @@ -8,7 +8,6 @@ #import "WPTableViewController.h" #import "WPTableViewControllerSubclass.h" -#import "EGORefreshTableHeaderView.h" #import "WordPressAppDelegate.h" #import "EditSiteViewController.h" #import "ReachabilityUtils.h" @@ -19,7 +18,7 @@ NSTimeInterval const WPTableViewControllerRefreshTimeout = 300; // 5 minutes -@interface WPTableViewController () +@interface WPTableViewController () @property (nonatomic, strong) NSFetchedResultsController *resultsController; @property (nonatomic) BOOL swipeActionsEnabled; @@ -40,7 +39,6 @@ - (void)configureNoResultsView; @end @implementation WPTableViewController { - EGORefreshTableHeaderView *_refreshHeaderView; EditSiteViewController *editSiteViewController; UIView *noResultsView; NSIndexPath *_indexPathSelectedBeforeUpdates; @@ -79,21 +77,13 @@ - (void)viewDidLoad { [super viewDidLoad]; - self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds]; self.tableView.delegate = self; self.tableView.dataSource = self; self.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - [self.view addSubview:self.tableView]; - - if (_refreshHeaderView == nil) { - _refreshHeaderView = [[EGORefreshTableHeaderView alloc] initWithFrame:CGRectMake(0.0f, 0.0f - self.tableView.bounds.size.height, self.tableView.frame.size.width, self.tableView.bounds.size.height)]; - _refreshHeaderView.delegate = self; - _refreshHeaderView.backgroundColor = [self backgroundColorForRefreshHeaderView]; - [self.tableView addSubview:_refreshHeaderView]; - } - - // update the last update date - [_refreshHeaderView refreshLastUpdatedDate]; + + UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init]; + [refreshControl addTarget:self action:@selector(refresh) forControlEvents:UIControlEventValueChanged]; + self.refreshControl = refreshControl; self.tableView.allowsSelectionDuringEditing = YES; self.tableView.backgroundColor = TABLE_VIEW_BACKGROUND_COLOR; @@ -122,7 +112,6 @@ - (void)viewDidUnload self.tableView.delegate = nil; self.tableView.dataSource = nil; self.tableView = nil; - _refreshHeaderView = nil; if (self.swipeActionsEnabled) { [self disableSwipeGestureRecognizer]; @@ -154,13 +143,8 @@ - (void)viewDidAppear:(BOOL)animated { } NSDate *lastSynced = [self lastSyncDate]; if (lastSynced == nil || ABS([lastSynced timeIntervalSinceNow]) > WPTableViewControllerRefreshTimeout) { - // If table is at the original scroll position, simulate a pull to refresh - if (self.tableView.contentOffset.y == 0) { - [self simulatePullToRefresh]; - } else { - // Otherwise, just update in the background - [self syncItemsWithUserInteraction:NO]; - } + // Update in the background + [self syncItems]; } } @@ -180,7 +164,6 @@ - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interface - (void)setEditing:(BOOL)editing animated:(BOOL)animated { [self removeSwipeView:NO]; [super setEditing:editing animated:animated]; - _refreshHeaderView.hidden = editing; } @@ -205,11 +188,6 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N } -- (UIColor *)backgroundColorForRefreshHeaderView -{ - return _refreshHeaderView.backgroundColor; -} - - (NSString *)noResultsText { NSString *ttl = NSLocalizedString(@"No %@ yet", @"A string format. The '%@' will be replaced by the relevant type of object, posts, pages or comments."); @@ -228,9 +206,7 @@ - (void)setBlog:(Blog *)blog { self.resultsController = nil; [self.tableView reloadData]; WordPressAppDelegate *appDelegate = [WordPressAppDelegate sharedWordPressApplicationDelegate]; - if ( appDelegate.connectionAvailable == YES && [self.resultsController.fetchedObjects count] == 0 && ![self isSyncing] ) { - [self simulatePullToRefresh]; - } else { + if (!(appDelegate.connectionAvailable == YES && [self.resultsController.fetchedObjects count] == 0 && ![self isSyncing])) { [self configureNoResultsView]; } } @@ -487,35 +463,18 @@ - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id } } -#pragma mark - EGORefreshTableHeaderDelegate Methods +#pragma mark - UIRefreshControl Methods -- (void)egoRefreshTableHeaderDidTriggerRefresh:(EGORefreshTableHeaderView *)view{ +- (void)refresh { didTriggerRefresh = YES; - [self syncItemsWithUserInteraction:YES]; + [self syncItemsViaUserInteraction]; [noResultsView removeFromSuperview]; } -- (BOOL)egoRefreshTableHeaderDataSourceIsLoading:(EGORefreshTableHeaderView *)view{ - return [self isSyncing]; // should return if data source model is reloading -} - -- (NSDate*)egoRefreshTableHeaderDataSourceLastUpdated:(EGORefreshTableHeaderView *)view{ - return [self lastSyncDate]; // should return date data source was last changed -} #pragma mark - #pragma mark UIScrollViewDelegate Methods -- (void)scrollViewDidScroll:(UIScrollView *)scrollView{ - if (!self.editing) - [_refreshHeaderView egoRefreshScrollViewDidScroll:scrollView]; -} - -- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{ - if (!self.editing) - [_refreshHeaderView egoRefreshScrollViewDidEndDragging:scrollView]; -} - - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { _isScrolling = YES; if (self.panelNavigationController) { @@ -631,7 +590,7 @@ - (UIView *)createNoResultsView { } - (void)hideRefreshHeader { - [_refreshHeaderView egoRefreshScrollViewDataSourceDidFinishedLoading:self.tableView]; + [self.refreshControl endRefreshing]; if ([self isViewLoaded] && self.tableView.window && didTriggerRefresh) { [SoundUtil playRollupSound]; } @@ -642,22 +601,21 @@ - (void)dismissModal:(id)sender { [self dismissViewControllerAnimated:YES completion:nil]; } -- (void)simulatePullToRefresh { - if(!_refreshHeaderView) return; - - CGPoint offset = self.tableView.contentOffset; - offset.y = - 65.0f; - [self.tableView setContentOffset:offset]; - [_refreshHeaderView egoRefreshScrollViewDidEndDragging:self.tableView]; +- (void)syncItems { + [self syncItemsViaUserInteraction:NO]; +} + +- (void)syncItemsViaUserInteraction { + [self syncItemsViaUserInteraction:YES]; } -- (void)syncItemsWithUserInteraction:(BOOL)userInteraction { +- (void)syncItemsViaUserInteraction:(BOOL)userInteraction { if ([self isSyncing]) { return; } _isSyncing = YES; - [self syncItemsWithUserInteraction:userInteraction success:^{ + [self syncItemsWithSuccess:^{ [self hideRefreshHeader]; _isSyncing = NO; [self configureNoResultsView]; @@ -933,10 +891,15 @@ - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPa AssertSubclassMethod(); } -- (void)syncItemsWithUserInteraction:(BOOL)userInteraction success:(void (^)())success failure:(void (^)(NSError *))failure { +- (void)syncItemsWithSuccess:(void (^)())success failure:(void (^)(NSError *))failure { AssertSubclassMethod(); } +- (void)syncItemsViaUserInteractionWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure { + // By default, sync items the same way. Subclasses can override if they need different behavior. + [self syncItemsWithSuccess:success failure:failure]; +} + - (BOOL)isSyncing { return _isSyncing; } diff --git a/WordPress/Classes/WPTableViewControllerSubclass.h b/WordPress/Classes/WPTableViewControllerSubclass.h index 59528b1d8e02..d5eba681959a 100644 --- a/WordPress/Classes/WPTableViewControllerSubclass.h +++ b/WordPress/Classes/WPTableViewControllerSubclass.h @@ -29,22 +29,23 @@ */ @property (nonatomic, readonly, strong) UIView *noResultsView; + /** Sync content with the server Subclasses can call this method if they need to invoke a refresh, but it's not meant to be implemented by subclasses. - Override syncItemsWithUserInteraction:success:failure: instead - - @param userInteraction Pass YES if the sync is generated by user action + Override syncItemsWithSuccess:failure: instead. */ -- (void)syncItemsWithUserInteraction:(BOOL)userInteraction; +- (void)syncItems; /** - Simulate a pull to refresh. + Special case method to invoke syncing via user interaction, which could do extra processing, show errors, etc. - Subclasses can call this method if they need to simulate a pull to refresh, but it is not meant to be implemented by subclasses. + Subclasses can call this method when the user invokes a refresh, but it's not meant to be implemented by subclasses. + Override syncItemsViaUserInteraction:success:failure: instead. */ -- (void)simulatePullToRefresh; +- (void)syncItemsViaUserInteraction; + /// ---------------------------------------------- /// @name Methods that subclasses should implement @@ -119,7 +120,16 @@ @param success A block that's executed if the sync was successful @param failure A block that's executed if there was any error */ -- (void)syncItemsWithUserInteraction:(BOOL)userInteraction success:(void (^)())success failure:(void (^)(NSError *error))failure; +- (void)syncItemsWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure; + +/** + Performs syncing of items when the user performs an explicit action, such as pulling to refresh. + By default, simply calls syncItemsWithSuccess:failure: but subclasses can override. + + @param success A block that's executed if the sync was successful + @param failure A block that's executed if there was any error + */ +- (void)syncItemsViaUserInteractionWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure; /** Returns a boolean indicating if the blog is syncing that type of item right now