Brion VIBBER has submitted this change and it was merged. Change subject: Custom pull-to-refresh for articles. ......................................................................
Custom pull-to-refresh for articles. Change-Id: Id76ad6518cf0cdc2f2b1a05a59e09c93e7146b7a --- M Wikipedia-iOS/View Controllers/Preview/PreviewAndSaveViewController.m M Wikipedia-iOS/View Controllers/WebView/WebViewController.h M Wikipedia-iOS/View Controllers/WebView/WebViewController.m M Wikipedia-iOS/en.lproj/Localizable.strings M Wikipedia-iOS/qqq.lproj/Localizable.strings 5 files changed, 171 insertions(+), 23 deletions(-) Approvals: Dr0ptp4kt: Looks good to me, but someone else must approve Brion VIBBER: Verified; Looks good to me, approved Siebrand: Looks good to me, but someone else must approve diff --git a/Wikipedia-iOS/View Controllers/Preview/PreviewAndSaveViewController.m b/Wikipedia-iOS/View Controllers/Preview/PreviewAndSaveViewController.m index 5b9e811..3cfe8c8 100644 --- a/Wikipedia-iOS/View Controllers/Preview/PreviewAndSaveViewController.m +++ b/Wikipedia-iOS/View Controllers/Preview/PreviewAndSaveViewController.m @@ -314,32 +314,15 @@ UploadSectionWikiTextOp *uploadWikiTextOp = [[UploadSectionWikiTextOp alloc] initForPageTitle:section.article.title domain:section.article.domain section:section.index wikiText:self.wikiText summary:editSummary captchaId:self.captchaId captchaWord:self.captchaViewController.captchaTextBox.text completionBlock:^(NSString *result){ - // Mark article for refreshing so its data will be reloaded. - // (Needs to be done on worker context as worker context changes bubble up through - // main context too - so web view controller accessing main context will see changes.) + // Mark article for refreshing and reload it. if (articleID) { - [articleDataContext_.workerContext performBlockAndWait:^(){ - Article *article = (Article *)[articleDataContext_.workerContext objectWithID:articleID]; - if (article) { - article.needsRefresh = @YES; - NSError *error = nil; - [articleDataContext_.workerContext save:&error]; - NSLog(@"error = %@", error); - } + [[NSOperationQueue mainQueue] addOperationWithBlock: ^ { + WebViewController *webVC = [self.navigationController searchNavStackForViewControllerOfClass:[WebViewController class]]; + [webVC reloadCurrentArticleInvalidatingCache]; + [self.navigationController popToViewController:webVC animated:YES]; + isAleadySaving = NO; }]; } - - [[NSOperationQueue mainQueue] addOperationWithBlock: ^ { - - // Cause the web view to reload - now that its sections are gone it will try to reload them. - - WebViewController *webVC = [self.navigationController searchNavStackForViewControllerOfClass:[WebViewController class]]; - [webVC reloadCurrentArticle]; - [self.navigationController popToViewController:webVC animated:YES]; - - isAleadySaving = NO; - - }]; } cancelledBlock:^(NSError *error){ NSString *errorMsg = error.localizedDescription; diff --git a/Wikipedia-iOS/View Controllers/WebView/WebViewController.h b/Wikipedia-iOS/View Controllers/WebView/WebViewController.h index 7790ae8..9b6dc71 100644 --- a/Wikipedia-iOS/View Controllers/WebView/WebViewController.h +++ b/Wikipedia-iOS/View Controllers/WebView/WebViewController.h @@ -17,6 +17,8 @@ -(void)tocToggle; -(void)saveWebViewScrollOffset; + -(void)reloadCurrentArticle; +-(void)reloadCurrentArticleInvalidatingCache; @end diff --git a/Wikipedia-iOS/View Controllers/WebView/WebViewController.m b/Wikipedia-iOS/View Controllers/WebView/WebViewController.m index f1439d8..f770cd0 100644 --- a/Wikipedia-iOS/View Controllers/WebView/WebViewController.m +++ b/Wikipedia-iOS/View Controllers/WebView/WebViewController.m @@ -79,6 +79,10 @@ @property (weak, nonatomic) IBOutlet NSLayoutConstraint *webViewLeftConstraint; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *webViewRightConstraint; +@property (weak, nonatomic) IBOutlet NSLayoutConstraint *pullToRefreshViewBottomConstraint; +@property (strong, nonatomic) UILabel *pullToRefreshLabel; +@property (strong, nonatomic) UIView *pullToRefreshView; + - (IBAction)tocButtonPushed:(id)sender; - (IBAction)backButtonPushed:(id)sender; - (IBAction)forwardButtonPushed:(id)sender; @@ -133,6 +137,8 @@ self.webView.backgroundColor = [UIColor colorWithRed:0.98 green:0.98 blue:0.98 alpha:1.0]; [self reloadCurrentArticle]; + + [self setupPullToRefresh]; } -(void)viewDidAppear:(BOOL)animated @@ -474,6 +480,8 @@ TOCViewController *tocVC = [self searchForChildViewControllerOfClass:[TOCViewController class]]; if (tocVC) [tocVC centerCellForWebViewTopMostSection]; + + self.pullToRefreshView.alpha = 0.0f; } } @@ -565,6 +573,8 @@ [self hideKeyboard]; //NSLog(@"Keyboard Hidden!"); } + + [self updatePullToRefreshForScrollView:scrollView]; } - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView @@ -607,6 +617,30 @@ NSString *title = [SessionSingleton sharedInstance].currentArticleTitle; NSString *domain = [SessionSingleton sharedInstance].currentArticleDomain; [self navigateToPage:title domain:domain discoveryMethod:DISCOVERY_METHOD_SEARCH]; +} + +-(void)reloadCurrentArticleInvalidatingCache +{ + // Mark article for refreshing so its core data records will be reloaded. + // (Needs to be done on worker context as worker context changes bubble up through + // main context too - so web view controller accessing main context will see changes.) + + NSManagedObjectID *articleID = + [articleDataContext_.mainContext getArticleIDForTitle: [SessionSingleton sharedInstance].currentArticleTitle + domain: [SessionSingleton sharedInstance].currentArticleDomain]; + + if (articleID) { + [articleDataContext_.workerContext performBlockAndWait:^(){ + Article *article = (Article *)[articleDataContext_.workerContext objectWithID:articleID]; + if (article) { + article.needsRefresh = @YES; + NSError *error = nil; + [articleDataContext_.workerContext save:&error]; + NSLog(@"error = %@", error); + } + }]; + [self reloadCurrentArticle]; + } } - (void)retrieveArticleForPageTitle:(NSString *)pageTitle domain:(NSString *)domain discoveryMethod:(NSString *)discoveryMethod @@ -1130,4 +1164,126 @@ } } +#pragma mark Pull to refresh + +-(void)setupPullToRefresh +{ + self.pullToRefreshLabel = [[UILabel alloc] init]; + self.pullToRefreshLabel.translatesAutoresizingMaskIntoConstraints = NO; + self.pullToRefreshLabel.backgroundColor = [UIColor clearColor]; + self.pullToRefreshLabel.textAlignment = NSTextAlignmentCenter; + self.pullToRefreshLabel.numberOfLines = 2; + self.pullToRefreshLabel.font = [UIFont systemFontOfSize:10]; + self.pullToRefreshLabel.textColor = [UIColor darkGrayColor]; + + self.pullToRefreshView = [[UIView alloc] init]; + self.pullToRefreshView.alpha = 0.0f; + self.pullToRefreshView.backgroundColor = [UIColor clearColor]; + self.pullToRefreshView.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:self.pullToRefreshView]; + [self.pullToRefreshView addSubview:self.pullToRefreshLabel]; + + [self constrainPullToRefresh]; +} + +-(void)constrainPullToRefresh +{ + self.pullToRefreshViewBottomConstraint = + [NSLayoutConstraint constraintWithItem: self.pullToRefreshView + attribute: NSLayoutAttributeBottom + relatedBy: NSLayoutRelationEqual + toItem: self.view + attribute: NSLayoutAttributeTop + multiplier: 1.0 + constant: 0]; + + NSDictionary *viewsDictionary = @{ + @"pullToRefreshView": self.pullToRefreshView, + @"pullToRefreshLabel": self.pullToRefreshLabel, + @"selfView": self.view + }; + + NSArray *viewConstraintArrays = + @[ + [NSLayoutConstraint constraintsWithVisualFormat: @"H:|[pullToRefreshView]|" + options: 0 + metrics: nil + views: viewsDictionary], + @[self.pullToRefreshViewBottomConstraint], + [NSLayoutConstraint constraintsWithVisualFormat: @"H:|-[pullToRefreshLabel]-|" + options: 0 + metrics: nil + views: viewsDictionary], + [NSLayoutConstraint constraintsWithVisualFormat: @"V:|[pullToRefreshLabel]|" + options: 0 + metrics: nil + views: viewsDictionary], + ]; + + [self.view addConstraints:[viewConstraintArrays valueForKeyPath:@"@unionOfArrays.self"]]; +} + +- (void)updatePullToRefreshForScrollView:(UIScrollView *)scrollView +{ + CGFloat pullDistance = (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) ? 85.0f : 55.0f; + + BOOL safeToShow = + !scrollView.decelerating + && + ([QueuesSingleton sharedInstance].articleRetrievalQ.operationCount == 0) + && + !self.tocVisible + ; + + //NSLog(@"%@", NSStringFromCGPoint(scrollView.contentOffset)); + if ((scrollView.contentOffset.y < 0.0f)){ + + self.pullToRefreshViewBottomConstraint.constant = -scrollView.contentOffset.y; + //self.pullToRefreshViewBottomConstraint.constant = -(fmaxf(scrollView.contentOffset.y, -self.pullToRefreshView.frame.size.height)); + + if (safeToShow) { + self.pullToRefreshView.alpha = 1.0f; + } + + NSString *lineOneText = @""; + NSString *lineTwoText = NSLocalizedString(@"article-pull-to-refresh-prompt", nil); + + if (scrollView.contentOffset.y > -(pullDistance * 0.35)){ + lineOneText = @"▫︎ ▫︎ ▫︎ ▫︎ ▫︎"; + }else if (scrollView.contentOffset.y > -(pullDistance * 0.52)){ + lineOneText = @"▫︎ ▫︎ ▪︎ ▫︎ ▫︎"; + }else if (scrollView.contentOffset.y > -(pullDistance * 0.7)){ + lineOneText = @"▫︎ ▪︎ ▪︎ ▪︎ ▫︎"; + }else if (scrollView.contentOffset.y > -pullDistance){ + lineOneText = @"▫︎ ▪︎ ▪︎ ▪︎ ▫︎"; + }else{ + lineOneText = @"▪︎ ▪︎ ▪︎ ▪︎ ▪︎"; + lineTwoText = NSLocalizedString(@"article-pull-to-refresh-is-refreshing", nil); + } + + self.pullToRefreshLabel.text = [NSString stringWithFormat:@"%@\n%@", lineOneText, lineTwoText]; + } + + if (scrollView.contentOffset.y < -pullDistance) { + if (safeToShow) { + + //NSLog(@"REFRESH NOW!!!!!"); + + [self reloadCurrentArticleInvalidatingCache]; + + [UIView animateWithDuration: 0.3f + delay: 0.6f + options: UIViewAnimationOptionTransitionNone + animations: ^{ + self.pullToRefreshView.alpha = 0.0f; + self.pullToRefreshViewBottomConstraint.constant = 0; + [self.view layoutIfNeeded]; + scrollView.panGestureRecognizer.enabled = NO; + } completion: ^(BOOL done){ + scrollView.panGestureRecognizer.enabled = YES; + }]; + } + } +} + @end diff --git a/Wikipedia-iOS/en.lproj/Localizable.strings b/Wikipedia-iOS/en.lproj/Localizable.strings index 002e132..d4b474b 100644 --- a/Wikipedia-iOS/en.lproj/Localizable.strings +++ b/Wikipedia-iOS/en.lproj/Localizable.strings @@ -100,3 +100,6 @@ "edit-summary-field-placeholder-text" = "How did you improve the page?"; "fetching-random-article" = "Fetching random article"; + +"article-pull-to-refresh-prompt" = "Pull to refresh article"; +"article-pull-to-refresh-is-refreshing" = "Refreshing article"; diff --git a/Wikipedia-iOS/qqq.lproj/Localizable.strings b/Wikipedia-iOS/qqq.lproj/Localizable.strings index af611ff..1bc0676 100644 --- a/Wikipedia-iOS/qqq.lproj/Localizable.strings +++ b/Wikipedia-iOS/qqq.lproj/Localizable.strings @@ -95,3 +95,7 @@ "edit-summary-field-placeholder-text" = "Placeholder text which appears initially in the free-form edit summary text box"; "fetching-random-article" = "Alert text shown when fetching a random article"; + +"article-pull-to-refresh-prompt" = "Label text informing user article may be pulled down to refresh"; +"article-pull-to-refresh-is-refreshing" = "Label text shown when user pulls down on article to refresh"; + -- To view, visit https://gerrit.wikimedia.org/r/120500 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Id76ad6518cf0cdc2f2b1a05a59e09c93e7146b7a Gerrit-PatchSet: 3 Gerrit-Project: apps/ios/wikipedia Gerrit-Branch: master Gerrit-Owner: Mhurd <mh...@wikimedia.org> Gerrit-Reviewer: Brion VIBBER <br...@wikimedia.org> Gerrit-Reviewer: Dr0ptp4kt <ab...@wikimedia.org> Gerrit-Reviewer: Mhurd <mh...@wikimedia.org> Gerrit-Reviewer: Siebrand <siebr...@kitano.nl> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits