Mhurd has submitted this change and it was merged. Change subject: Removes spinner and adds progress bar ......................................................................
Removes spinner and adds progress bar Add progress bar to Web VC Remove spinner (and trash files) Add progress reporting to article fetcher Calculates first 75% of progress from article fetcher, the last 25% is "faked" around the DOM loading notification Fix warning about subclass delegate property not synthesized (add "dynamic") Make logic for displaying progress internal to web VC (removed argument from method) Bug T97781 Change-Id: I89326831f795cdc03c12ed054b00489f255b5f0e --- M Wikipedia.xcodeproj/project.pbxproj D Wikipedia/Custom Views/WMFLoadingIndicatorOverlay.h D Wikipedia/Custom Views/WMFLoadingIndicatorOverlay.m M Wikipedia/Custom Views/WMFProgressLineView.m M Wikipedia/Networking/Fetchers/ArticleFetcher.h M Wikipedia/Networking/Fetchers/ArticleFetcher.m M Wikipedia/Networking/Fetchers/SavedArticlesFetcher.h M Wikipedia/Networking/Fetchers/SavedArticlesFetcher.m M Wikipedia/View Controllers/Navigation/Bottom/BottomMenuViewController.m M Wikipedia/View Controllers/Navigation/Center/CenterNavController.m M Wikipedia/View Controllers/References/ReferenceVC.m M Wikipedia/View Controllers/WebView/WebViewController.h M Wikipedia/View Controllers/WebView/WebViewController.m M Wikipedia/View Controllers/WebView/WebViewController_Private.h 14 files changed, 229 insertions(+), 289 deletions(-) Approvals: Mhurd: Looks good to me, approved jenkins-bot: Verified diff --git a/Wikipedia.xcodeproj/project.pbxproj b/Wikipedia.xcodeproj/project.pbxproj index 6570016..95873e5 100644 --- a/Wikipedia.xcodeproj/project.pbxproj +++ b/Wikipedia.xcodeproj/project.pbxproj @@ -74,8 +74,6 @@ 0462A6D11A1FE016009412D4 /* SearchResultAttributedString.m in Sources */ = {isa = PBXBuildFile; fileRef = 0462A6D01A1FE016009412D4 /* SearchResultAttributedString.m */; }; 0463639818A844570049EE4F /* KeychainCredentials.m in Sources */ = {isa = PBXBuildFile; fileRef = 0463639718A844570049EE4F /* KeychainCredentials.m */; }; 0472BC18193AD88C00C40BDA /* MWKSection+DisplayHtml.m in Sources */ = {isa = PBXBuildFile; fileRef = 0472BC17193AD88C00C40BDA /* MWKSection+DisplayHtml.m */; }; - 04733A041AC6123400E365E5 /* WMFLoadingIndicatorOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = 04733A031AC6123400E365E5 /* WMFLoadingIndicatorOverlay.m */; }; - 04733A051AC6123400E365E5 /* WMFLoadingIndicatorOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = 04733A031AC6123400E365E5 /* WMFLoadingIndicatorOverlay.m */; }; 047801BE18AE987900DBB747 /* UIButton+ColorMask.m in Sources */ = {isa = PBXBuildFile; fileRef = 047801BD18AE987900DBB747 /* UIButton+ColorMask.m */; }; 047E74141860509000916964 /* SavedPagesResultPrototypeView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 047E74131860509000916964 /* SavedPagesResultPrototypeView.xib */; }; 047E95511996DD030046A122 /* NearbyViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 047E954E1996DD030046A122 /* NearbyViewController.m */; }; @@ -519,8 +517,6 @@ 04649CA619F72B360071E8FA /* libPods.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libPods.a; path = "Pods/build/Debug-iphoneos/libPods.a"; sourceTree = "<group>"; }; 0472BC16193AD88C00C40BDA /* MWKSection+DisplayHtml.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MWKSection+DisplayHtml.h"; sourceTree = "<group>"; }; 0472BC17193AD88C00C40BDA /* MWKSection+DisplayHtml.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MWKSection+DisplayHtml.m"; sourceTree = "<group>"; }; - 04733A021AC6123400E365E5 /* WMFLoadingIndicatorOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WMFLoadingIndicatorOverlay.h; sourceTree = "<group>"; }; - 04733A031AC6123400E365E5 /* WMFLoadingIndicatorOverlay.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WMFLoadingIndicatorOverlay.m; sourceTree = "<group>"; }; 047528A3190F0C2900F2CDA8 /* WikiGlyph_Chars.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WikiGlyph_Chars.h; sourceTree = "<group>"; }; 047801BC18AE987900DBB747 /* UIButton+ColorMask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIButton+ColorMask.h"; sourceTree = "<group>"; }; 047801BD18AE987900DBB747 /* UIButton+ColorMask.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIButton+ColorMask.m"; sourceTree = "<group>"; }; @@ -2314,8 +2310,6 @@ 0480AE9F1AA4F4DA00A9950C /* WMFIntrinsicContentSizeAwareTableView.m */, BCA96E711AAA354D009A61FA /* WMFGradientView.h */, BCA96E721AAA354D009A61FA /* WMFGradientView.m */, - 04733A021AC6123400E365E5 /* WMFLoadingIndicatorOverlay.h */, - 04733A031AC6123400E365E5 /* WMFLoadingIndicatorOverlay.m */, ); path = "Custom Views"; sourceTree = "<group>"; @@ -2914,7 +2908,6 @@ BC0FED641AAA0263002488D7 /* MWKArticleStoreTestCase.m in Sources */, BCA676561AC05FE200A16160 /* NSBundle+TestAssets.m in Sources */, BCB8487B1AAAADF90077EC24 /* WMFRoundingUtilitiesTests.m in Sources */, - 04733A051AC6123400E365E5 /* WMFLoadingIndicatorOverlay.m in Sources */, BC0FED6F1AAA0268002488D7 /* MWKImageInfo+MWKImageComparisonTests.m in Sources */, BC0FED621AAA0263002488D7 /* WMFCodingStyle.m in Sources */, BC0FED741AAA026C002488D7 /* CircularBitwiseRotationTests.m in Sources */, @@ -3105,7 +3098,6 @@ BCB669B71A83F6C400C7B1FE /* MWKSectionList.m in Sources */, 0EE768811AFD25CC00A5D046 /* WMFSearchFunnel.m in Sources */, BCB66A0C1A85183000C7B1FE /* NSString+WMFHTMLParsing.m in Sources */, - 04733A041AC6123400E365E5 /* WMFLoadingIndicatorOverlay.m in Sources */, BCB669AF1A83F6C400C7B1FE /* MWKHistoryList.m in Sources */, BC50C37F1A83C784006DC7AF /* WMFNetworkUtilities.m in Sources */, BCB58F441A890D9700465627 /* MWKImageInfo+MWKImageComparison.m in Sources */, diff --git a/Wikipedia/Custom Views/WMFLoadingIndicatorOverlay.h b/Wikipedia/Custom Views/WMFLoadingIndicatorOverlay.h deleted file mode 100644 index 339a975..0000000 --- a/Wikipedia/Custom Views/WMFLoadingIndicatorOverlay.h +++ /dev/null @@ -1,29 +0,0 @@ -// Created by Monte Hurd on 3/27/15. -// Copyright (c) 2015 Wikimedia Foundation. Provided under MIT-style license; please copy and modify! - -#import <UIKit/UIKit.h> - -/** - * Overlay view to indicate loading. Can display optional spinner. - */ -@interface WMFLoadingIndicatorOverlay : UIView - -/** - * Shows/hides the overlay view. A fade animation is used if animated parameter is YES. - * - * @param isVisible controls visibility - * @param animated controls whether fade animation is used or visibility change happens instantly. - */ -- (void)setVisible:(BOOL)isVisible animated:(BOOL)animated; - -/** - * Control whether a centered "spinner" loading indicator is shown. - */ -@property (nonatomic) BOOL showSpinner; - -/** - * Check whether this view is presently visible. - */ -@property (nonatomic, readonly) BOOL isVisible; - -@end diff --git a/Wikipedia/Custom Views/WMFLoadingIndicatorOverlay.m b/Wikipedia/Custom Views/WMFLoadingIndicatorOverlay.m deleted file mode 100644 index 60f6501..0000000 --- a/Wikipedia/Custom Views/WMFLoadingIndicatorOverlay.m +++ /dev/null @@ -1,104 +0,0 @@ -// Created by Monte Hurd on 3/27/15. -// Copyright (c) 2015 Wikimedia Foundation. Provided under MIT-style license; please copy and modify! - -#import "WMFLoadingIndicatorOverlay.h" -#import "UIColor+WMFHexColor.h" -#import <Masonry/Masonry.h> - -static CGFloat const kActivityIndicatorWidth = 100.0f; -static CGFloat const kActivityIndicatorCornerRadius = 10.0f; -static NSInteger const kActivityIndicatorBackgroundColor = 0x000000; - -static CGFloat const kFadeAnimationDuration = 0.33f; - -@interface WMFLoadingIndicatorOverlay () - -@property (nonatomic, strong) UIActivityIndicatorView* activityIndicator; -@property (nonatomic) CGFloat lastNonZeroAlpha; -@property (nonatomic) BOOL isVisible; - -@end - -@implementation WMFLoadingIndicatorOverlay - -- (instancetype)init { - self = [super init]; - if (self) { - self.isVisible = !self.hidden; - self.userInteractionEnabled = YES; - [self addSubview:self.activityIndicator]; - [self.activityIndicator mas_makeConstraints:^(MASConstraintMaker* make) { - make.center.equalTo(self.activityIndicator.superview); - make.size.mas_equalTo(CGSizeMake(kActivityIndicatorWidth, kActivityIndicatorWidth)); - }]; - } - return self; -} - -- (UIActivityIndicatorView*)activityIndicator { - if (!_activityIndicator) { - _activityIndicator = - [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; - self.activityIndicator.color = [UIColor whiteColor]; - self.activityIndicator.hidesWhenStopped = YES; - self.activityIndicator.backgroundColor = [UIColor wmf_colorWithHex:kActivityIndicatorBackgroundColor alpha:1.0f]; - self.activityIndicator.layer.cornerRadius = kActivityIndicatorCornerRadius; - } - return _activityIndicator; -} - -- (void)setVisible:(BOOL)isVisible animated:(BOOL)animated { - CGFloat durationToUse = animated ? kFadeAnimationDuration : 0.0f; - if (isVisible) { - self.isVisible = YES; - if (self.showSpinner) { - [self.activityIndicator startAnimating]; - } - - [self performAnimations:^{ - self.alpha = self.lastNonZeroAlpha; - } duration:durationToUse completion:nil]; - } else { - [self performAnimations:^{ - self.alpha = 0.0; - } duration:durationToUse completion:^{ - [self.activityIndicator stopAnimating]; - self.isVisible = NO; - }]; - } -} - -- (void)performAnimations:(dispatch_block_t)animationsBlock - duration:(NSTimeInterval)duration - completion:(dispatch_block_t)completionBlock { - if (duration == 0) { - if (animationsBlock) { - animationsBlock(); - } - if (completionBlock) { - completionBlock(); - } - } else { - [UIView animateWithDuration:duration - delay:0.0 - options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseInOut - animations:^{ - if (animationsBlock) { - animationsBlock(); - } - } completion:^(BOOL finished) { - if (completionBlock) { - completionBlock(); - } - }]; - } -} - -- (void)setAlpha:(CGFloat)alpha { - if (self.alpha != 0.0f) { - self.lastNonZeroAlpha = self.alpha; - } - [super setAlpha:alpha]; -} - -@end diff --git a/Wikipedia/Custom Views/WMFProgressLineView.m b/Wikipedia/Custom Views/WMFProgressLineView.m index 2ac1f75..4757658 100644 --- a/Wikipedia/Custom Views/WMFProgressLineView.m +++ b/Wikipedia/Custom Views/WMFProgressLineView.m @@ -71,7 +71,9 @@ [CATransaction begin]; - [CATransaction setCompletionBlock:completion]; + if (completion) { + [CATransaction setCompletionBlock:completion]; + } if (!CGRectEqualToRect(self.progressBar.frame, slice)) { if (animated) { diff --git a/Wikipedia/Networking/Fetchers/ArticleFetcher.h b/Wikipedia/Networking/Fetchers/ArticleFetcher.h index 118416c..43d75f0 100644 --- a/Wikipedia/Networking/Fetchers/ArticleFetcher.h +++ b/Wikipedia/Networking/Fetchers/ArticleFetcher.h @@ -4,7 +4,16 @@ #import <Foundation/Foundation.h> #import "FetcherBase.h" -@class Article, AFHTTPRequestOperationManager; +@class Article, AFHTTPRequestOperationManager, ArticleFetcher; + +@protocol ArticleFetcherDelegate <FetchFinishedDelegate> + +@optional +- (void)articleFetcher:(ArticleFetcher*)savedArticlesFetcher + didUpdateProgress:(CGFloat)progress; + +@end + @interface ArticleFetcher : FetcherBase @@ -13,7 +22,8 @@ // Kick-off method. Results are reported to "delegate" via the FetchFinishedDelegate protocol method. - (instancetype)initAndFetchSectionsForArticle:(MWKArticle*)articleStore withManager:(AFHTTPRequestOperationManager*)manager - thenNotifyDelegate:(id <FetchFinishedDelegate>)delegate; + thenNotifyDelegate:(id<ArticleFetcherDelegate>)delegate; +@property (nonatomic, weak) id<ArticleFetcherDelegate> fetchFinishedDelegate; @end diff --git a/Wikipedia/Networking/Fetchers/ArticleFetcher.m b/Wikipedia/Networking/Fetchers/ArticleFetcher.m index 3233faf..9de9134 100644 --- a/Wikipedia/Networking/Fetchers/ArticleFetcher.m +++ b/Wikipedia/Networking/Fetchers/ArticleFetcher.m @@ -26,9 +26,11 @@ @implementation ArticleFetcher +@dynamic fetchFinishedDelegate; + - (instancetype)initAndFetchSectionsForArticle:(MWKArticle*)article withManager:(AFHTTPRequestOperationManager*)manager - thenNotifyDelegate:(id <FetchFinishedDelegate> )delegate { + thenNotifyDelegate:(id<ArticleFetcherDelegate> )delegate { self = [super init]; assert(article != nil); assert(manager != nil); @@ -73,7 +75,7 @@ // Conditionally add an MCCMNC header. [self addMCCMNCHeaderToRequestSerializer:manager.requestSerializer ifAppropriateForURL:url]; - [manager GET:url.absoluteString parameters:params success:^(AFHTTPRequestOperation* operation, id responseObject) { + AFHTTPRequestOperation* operation = [manager GET:url.absoluteString parameters:params success:^(AFHTTPRequestOperation* operation, id responseObject) { __block NSData* localResponseObject = responseObject; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ @@ -128,6 +130,20 @@ [self finishWithError:error fetchedData:nil]; }]; + + __block CGFloat progress = 0.0; + + [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) { + if (totalBytesExpectedToRead > 0) { + progress = (CGFloat)(totalBytesRead / totalBytesExpectedToRead); + } else { + progress += 0.05; + } + + if ([self.fetchFinishedDelegate respondsToSelector:@selector(articleFetcher:didUpdateProgress:)]) { + [self.fetchFinishedDelegate articleFetcher:self didUpdateProgress:progress]; + } + }]; } - (NSDictionary*)getParamsForTitle:(NSString*)title { diff --git a/Wikipedia/Networking/Fetchers/SavedArticlesFetcher.h b/Wikipedia/Networking/Fetchers/SavedArticlesFetcher.h index ba67495..1856568 100644 --- a/Wikipedia/Networking/Fetchers/SavedArticlesFetcher.h +++ b/Wikipedia/Networking/Fetchers/SavedArticlesFetcher.h @@ -26,7 +26,7 @@ - (void)getProgress:(WMFSavedArticlesFetcherProgress)progressBlock; -@property (nonatomic, weak) id <SavedArticlesFetcherDelegate> fetchFinishedDelegate; +@property (nonatomic, weak) id<SavedArticlesFetcherDelegate> fetchFinishedDelegate; - (instancetype)initAndFetchArticlesForSavedPageList:(MWKSavedPageList*)savedPageList inDataStore:(MWKDataStore*)dataStore diff --git a/Wikipedia/Networking/Fetchers/SavedArticlesFetcher.m b/Wikipedia/Networking/Fetchers/SavedArticlesFetcher.m index 14ff4ad..ea6f3b4 100644 --- a/Wikipedia/Networking/Fetchers/SavedArticlesFetcher.m +++ b/Wikipedia/Networking/Fetchers/SavedArticlesFetcher.m @@ -4,7 +4,7 @@ #import "AFHTTPRequestOperationManager.h" #import <BlocksKit/BlocksKit.h> -@interface SavedArticlesFetcher ()<FetchFinishedDelegate> +@interface SavedArticlesFetcher ()<ArticleFetcherDelegate> @property (nonatomic, strong, readwrite) MWKSavedPageList* savedPageList; @property (nonatomic, strong, readwrite) MWKDataStore* dataStore; @@ -20,9 +20,11 @@ @implementation SavedArticlesFetcher +@dynamic fetchFinishedDelegate; + #pragma mark - Shared Access -static SavedArticlesFetcher * _fetcher = nil; +static SavedArticlesFetcher* _fetcher = nil; + (SavedArticlesFetcher*)sharedInstance { return _fetcher; diff --git a/Wikipedia/View Controllers/Navigation/Bottom/BottomMenuViewController.m b/Wikipedia/View Controllers/Navigation/Bottom/BottomMenuViewController.m index 04a64e7..a5406f8 100644 --- a/Wikipedia/View Controllers/Navigation/Bottom/BottomMenuViewController.m +++ b/Wikipedia/View Controllers/Navigation/Bottom/BottomMenuViewController.m @@ -318,8 +318,7 @@ [webVC showAlert:historyEntry.title.prefixedText type:ALERT_TYPE_BOTTOM duration:0.8]; [webVC navigateToPage:historyEntry.title - discoveryMethod:MWKHistoryDiscoveryMethodBackForward - showLoadingIndicator:YES]; + discoveryMethod:MWKHistoryDiscoveryMethodBackForward]; } } @@ -331,8 +330,7 @@ [webVC showAlert:historyEntry.title.prefixedText type:ALERT_TYPE_BOTTOM duration:0.8]; [webVC navigateToPage:historyEntry.title - discoveryMethod:MWKHistoryDiscoveryMethodBackForward - showLoadingIndicator:YES]; + discoveryMethod:MWKHistoryDiscoveryMethodBackForward]; } } diff --git a/Wikipedia/View Controllers/Navigation/Center/CenterNavController.m b/Wikipedia/View Controllers/Navigation/Center/CenterNavController.m index fb4c421..402180d 100644 --- a/Wikipedia/View Controllers/Navigation/Center/CenterNavController.m +++ b/Wikipedia/View Controllers/Navigation/Center/CenterNavController.m @@ -78,8 +78,7 @@ [SessionSingleton sharedInstance].currentArticle = article; [webVC navigateToPage:title - discoveryMethod:discoveryMethod - showLoadingIndicator:YES]; + discoveryMethod:discoveryMethod]; if (popToWebVC) { [ROOT popToViewController:webVC animated:animated]; } diff --git a/Wikipedia/View Controllers/References/ReferenceVC.m b/Wikipedia/View Controllers/References/ReferenceVC.m index 599b064..7e788ae 100644 --- a/Wikipedia/View Controllers/References/ReferenceVC.m +++ b/Wikipedia/View Controllers/References/ReferenceVC.m @@ -62,8 +62,7 @@ NSString* title = [encodedTitle stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; MWKTitle* pageTitle = [[SessionSingleton sharedInstance].currentArticleSite titleWithString:title]; [self.webVC navigateToPage:pageTitle - discoveryMethod:MWKHistoryDiscoveryMethodLink - showLoadingIndicator:YES]; + discoveryMethod:MWKHistoryDiscoveryMethodLink]; [self.webVC referencesHide]; return NO; } diff --git a/Wikipedia/View Controllers/WebView/WebViewController.h b/Wikipedia/View Controllers/WebView/WebViewController.h index 97c7d8f..6049c91 100644 --- a/Wikipedia/View Controllers/WebView/WebViewController.h +++ b/Wikipedia/View Controllers/WebView/WebViewController.h @@ -14,7 +14,7 @@ @class BottomMenuViewController, CommunicationBridge; -@interface WebViewController : PullToRefreshViewController <UIWebViewDelegate, UIScrollViewDelegate, UIGestureRecognizerDelegate, UIAlertViewDelegate, FetchFinishedDelegate> +@interface WebViewController : PullToRefreshViewController <UIWebViewDelegate, UIScrollViewDelegate, UIGestureRecognizerDelegate, UIAlertViewDelegate, ArticleFetcherDelegate> @property (weak, nonatomic) IBOutlet UIWebView* webView; @property (nonatomic) BOOL bottomMenuHidden; @@ -34,9 +34,8 @@ - (void)reloadCurrentArticle; -- (void) navigateToPage:(MWKTitle*)title - discoveryMethod:(MWKHistoryDiscoveryMethod)discoveryMethod - showLoadingIndicator:(BOOL)showLoadingIndicator; +- (void)navigateToPage:(MWKTitle*)title + discoveryMethod:(MWKHistoryDiscoveryMethod)discoveryMethod; - (void)tocScrollWebViewToSectionWithElementId:(NSString*)elementId duration:(CGFloat)duration diff --git a/Wikipedia/View Controllers/WebView/WebViewController.m b/Wikipedia/View Controllers/WebView/WebViewController.m index 636064b..3e9e0cb 100644 --- a/Wikipedia/View Controllers/WebView/WebViewController.m +++ b/Wikipedia/View Controllers/WebView/WebViewController.m @@ -76,8 +76,12 @@ [self.bridge addListener:@"DOMContentLoaded" withBlock:^(NSString* type, NSDictionary* payload) { [weakSelf jumpToFragmentIfNecessary]; [weakSelf autoScrollToLastScrollOffsetIfNecessary]; - [weakSelf.loadingIndicatorOverlay setVisible:NO animated:YES]; + [weakSelf updateProgress:1.0 animated:YES completion:^{ + [weakSelf hideProgressViewAnimated:YES]; + }]; + + //dispatching because the toc is expensive to create so we are waiting to update it after the web view renders. dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf.tocVC updateTocForArticle:[SessionSingleton sharedInstance].currentArticle]; [weakSelf updateTOCScrollPositionWithoutAnimationIfHidden]; @@ -162,8 +166,6 @@ self.webView.scrollView.layer.anchorPoint = CGPointMake((isRTL ? 1.0 : 0.0), 0.0); [self tocUpdateViewLayout]; - - [self loadingIndicatorAdd]; } - (void)jumpToFragmentIfNecessary { @@ -562,7 +564,7 @@ } // Prevent toc reveal if loading article. - if (self.loadingIndicatorOverlay.isVisible) { + if (self.isFetchingArticle) { return; } @@ -833,8 +835,7 @@ MWKTitle* pageTitle = [[SessionSingleton sharedInstance].currentArticleSite titleWithInternalLink:href]; [strSelf navigateToPage:pageTitle - discoveryMethod:MWKHistoryDiscoveryMethodLink - showLoadingIndicator:YES]; + discoveryMethod:MWKHistoryDiscoveryMethodLink]; } else if ([href hasPrefix:@"http:"] || [href hasPrefix:@"https:"] || [href hasPrefix:@"//"]) { // A standard external link, either explicitly http(s) or left protocol-relative on web meaning http(s) if ([href hasPrefix:@"//"]) { @@ -1328,11 +1329,10 @@ } } -#pragma mark Article loading +#pragma mark - Article loading -- (void) navigateToPage:(MWKTitle*)title - discoveryMethod:(MWKHistoryDiscoveryMethod)discoveryMethod - showLoadingIndicator:(BOOL)showLoadingIndicator { +- (void)navigateToPage:(MWKTitle*)title + discoveryMethod:(MWKHistoryDiscoveryMethod)discoveryMethod { NSString* cleanTitle = title.prefixedText; // Don't try to load nothing. Core data takes exception with such nonsense. @@ -1344,11 +1344,6 @@ } [self hideKeyboard]; - - if (showLoadingIndicator) { - self.loadingIndicatorOverlay.showSpinner = discoveryMethod != MWKHistoryDiscoveryMethodBackForward; - [self.loadingIndicatorOverlay setVisible:YES animated:YES]; - } // Show loading message //[self showAlert:MWLocalizedString(@"search-loading-section-zero", nil) type:ALERT_TYPE_TOP duration:-1]; @@ -1373,94 +1368,7 @@ - (void)reloadCurrentArticle { [self navigateToPage:session.currentArticle.title - discoveryMethod:MWKHistoryDiscoveryMethodReload - showLoadingIndicator:YES]; -} - -- (void)fetchFinished:(id)sender - fetchedData:(id)fetchedData - status:(FetchFinalStatus)status - error:(NSError*)error { - if ([sender isKindOfClass:[ArticleFetcher class]]) { - MWKArticle* article = session.currentArticle; - - switch (status) { - case FETCH_FINAL_STATUS_SUCCEEDED: - { - // Redirect if necessary. - MWKTitle* redirectedTitle = article.redirected; - if (redirectedTitle) { - // Get discovery method for call to "retrieveArticleForPageTitle:". - // There should only be a single history item (at most). - MWKHistoryEntry* history = [session.userDataStore.historyList entryForTitle:article.title]; - // Get the article's discovery method. - MWKHistoryDiscoveryMethod discoveryMethod = - (history) ? history.discoveryMethod : MWKHistoryDiscoveryMethodSearch; - - // Redirect! - [self retrieveArticleForPageTitle:redirectedTitle - discoveryMethod:discoveryMethod]; - return; - } - - // Update the toc and web view. - [self displayArticle:article.title]; - - [self hideAlert]; - } - break; - - case FETCH_FINAL_STATUS_FAILED: - { - [self displayArticle:article.title]; - - NSString* errorMsg = error.localizedDescription; - [self showAlert:errorMsg type:ALERT_TYPE_TOP duration:-1]; - - [self.loadingIndicatorOverlay setVisible:NO animated:YES]; - } - break; - - case FETCH_FINAL_STATUS_CANCELLED: - { - } - break; - - default: - break; - } - } else if ([sender isKindOfClass:[WikipediaZeroMessageFetcher class]]) { - switch (status) { - case FETCH_FINAL_STATUS_SUCCEEDED: - { - NSDictionary* banner = (NSDictionary*)fetchedData; - if (banner) { - TopMenuTextFieldContainer* textFieldContainer = [ROOT.topMenuViewController getNavBarItem:NAVBAR_TEXT_FIELD]; - textFieldContainer.textField.placeholder = MWLocalizedString(@"search-field-placeholder-text-zero", nil); - - //[self showAlert:title type:ALERT_TYPE_TOP duration:2]; - NSString* title = banner[@"message"]; - self.zeroStatusLabel.text = title; - self.zeroStatusLabel.padding = UIEdgeInsetsMake(3, 10, 3, 10); - self.zeroStatusLabel.textColor = banner[@"foreground"]; - self.zeroStatusLabel.backgroundColor = banner[@"background"]; - - [NAV promptFirstTimeZeroOnWithTitleIfAppropriate:title]; - } - } - break; - - case FETCH_FINAL_STATUS_FAILED: - { - } - break; - - case FETCH_FINAL_STATUS_CANCELLED: - { - } - break; - } - } + discoveryMethod:MWKHistoryDiscoveryMethodReload]; } - (void)cancelArticleLoading { @@ -1502,12 +1410,15 @@ break; } - // If article with sections just show them (unless needsRefresh is YES) - if ([article.sections count] > 0 && !article.needsRefresh) { + // If article is cached + if ([article isCached] && !article.needsRefresh) { [self displayArticle:session.currentArticle.title]; //[self showAlert:MWLocalizedString(@"search-loading-article-loaded", nil) type:ALERT_TYPE_TOP duration:-1]; [self fadeAlert]; } else { + [self showProgressViewAnimated:YES]; + self.isFetchingArticle = YES; + // "fetchFinished:" above will be notified when articleFetcher has actually retrieved some data. // Note: cast to void to avoid compiler warning: http://stackoverflow.com/a/7915839 (void)[[ArticleFetcher alloc] initAndFetchSectionsForArticle:session.currentArticle @@ -1516,7 +1427,103 @@ } } -#pragma mark Lead image +#pragma mark - ArticleFetcherDelegate + +- (void)articleFetcher:(ArticleFetcher*)savedArticlesFetcher + didUpdateProgress:(CGFloat)progress { + [self updateProgress:[self totalProgressWithArticleFetcherProgress:progress] animated:YES completion:NULL]; +} + +- (void)fetchFinished:(id)sender + fetchedData:(id)fetchedData + status:(FetchFinalStatus)status + error:(NSError*)error { + if ([sender isKindOfClass:[ArticleFetcher class]]) { + MWKArticle* article = session.currentArticle; + + switch (status) { + case FETCH_FINAL_STATUS_SUCCEEDED: + { + // Redirect if necessary. + MWKTitle* redirectedTitle = article.redirected; + if (redirectedTitle) { + // Get discovery method for call to "retrieveArticleForPageTitle:". + // There should only be a single history item (at most). + MWKHistoryEntry* history = [session.userDataStore.historyList entryForTitle:article.title]; + // Get the article's discovery method. + MWKHistoryDiscoveryMethod discoveryMethod = + (history) ? history.discoveryMethod : MWKHistoryDiscoveryMethodSearch; + + // Redirect! + [self retrieveArticleForPageTitle:redirectedTitle + discoveryMethod:discoveryMethod]; + return; + } + + self.isFetchingArticle = NO; + + // Update the toc and web view. + [self displayArticle:article.title]; + + [self hideAlert]; + } + break; + + case FETCH_FINAL_STATUS_FAILED: + { + self.isFetchingArticle = NO; + + [self displayArticle:article.title]; + + NSString* errorMsg = error.localizedDescription; + [self showAlert:errorMsg type:ALERT_TYPE_TOP duration:-1]; + } + break; + + case FETCH_FINAL_STATUS_CANCELLED: + { + self.isFetchingArticle = NO; + } + break; + + default: + break; + } + } else if ([sender isKindOfClass:[WikipediaZeroMessageFetcher class]]) { + switch (status) { + case FETCH_FINAL_STATUS_SUCCEEDED: + { + NSDictionary* banner = (NSDictionary*)fetchedData; + if (banner) { + TopMenuTextFieldContainer* textFieldContainer = [ROOT.topMenuViewController getNavBarItem:NAVBAR_TEXT_FIELD]; + textFieldContainer.textField.placeholder = MWLocalizedString(@"search-field-placeholder-text-zero", nil); + + //[self showAlert:title type:ALERT_TYPE_TOP duration:2]; + NSString* title = banner[@"message"]; + self.zeroStatusLabel.text = title; + self.zeroStatusLabel.padding = UIEdgeInsetsMake(3, 10, 3, 10); + self.zeroStatusLabel.textColor = banner[@"foreground"]; + self.zeroStatusLabel.backgroundColor = banner[@"background"]; + + [NAV promptFirstTimeZeroOnWithTitleIfAppropriate:title]; + } + } + break; + + case FETCH_FINAL_STATUS_FAILED: + { + } + break; + + case FETCH_FINAL_STATUS_CANCELLED: + { + } + break; + } + } +} + +#pragma mark - Lead image - (NSString*)leadImageGetHtml { // Get lead image html structured such that no JS bridge messages are needed for lead image presentation. @@ -1653,6 +1660,7 @@ session.currentArticle = article; if (![article isCached]) { + [self hideProgressViewAnimated:YES]; return; } @@ -1706,14 +1714,6 @@ NSString* sectionHTMLWithID = [section displayHTML:html]; [sectionTextArray addObject:sectionHTMLWithID]; } - - // If article has no thumbnailImage, use the first section image instead. - // Actually sets article.thumbnailImage to point to the image record of the first section - // image. That way, if the housekeeping code removes all section images, it won't remove this - // particular one because it checks to see if an article is referencing an image before it - // removes them. - //[article ifNoThumbnailUseFirstSectionImageAsThumbnailUsingContext:articleDataContext_.mainContext]; - if (session.currentArticleDiscoveryMethod == MWKHistoryDiscoveryMethodSaved || session.currentArticleDiscoveryMethod == MWKHistoryDiscoveryMethodBackForward || @@ -1782,6 +1782,10 @@ if ([self tocDrawerIsOpen]) { [self tocHide]; } + + dispatch_async(dispatch_get_main_queue(), ^{ + [self updateProgress:0.85 animated:YES completion:NULL]; + }); } #pragma mark Scroll to last section after rotate @@ -2077,20 +2081,70 @@ }]; } -#pragma mark Loading Indicator +#pragma mark - Progress -- (void)loadingIndicatorAdd { - self.loadingIndicatorOverlay = [[WMFLoadingIndicatorOverlay alloc] init]; - self.loadingIndicatorOverlay.backgroundColor = [UIColor whiteColor]; - self.loadingIndicatorOverlay.alpha = 0.8f; +- (WMFProgressLineView*)progressView { + if (!_progressView) { + WMFProgressLineView* progress = [[WMFProgressLineView alloc] initWithFrame:CGRectZero]; + _progressView = progress; + } - [self.view insertSubview:self.loadingIndicatorOverlay belowSubview:self.bottomBarView]; - [self.loadingIndicatorOverlay mas_makeConstraints:^(MASConstraintMaker* make) { - make.edges.equalTo(self.loadingIndicatorOverlay.superview); + return _progressView; +} + +- (void)showProgressViewAnimated:(BOOL)animated { + self.progressView.progress = 0.0; + + if (!animated) { + [self _showProgressView]; + return; + } + + [UIView animateWithDuration:0.25 animations:^{ + [self _showProgressView]; + } completion:^(BOOL finished) { }]; } -#pragma mark Sharing +- (void)_showProgressView { + self.progressView.alpha = 1.0; + + if (!self.progressView.superview) { + [ROOT.topMenuViewController.view addSubview:self.progressView]; + [self.progressView mas_makeConstraints:^(MASConstraintMaker* make) { + make.top.equalTo(ROOT.topMenuViewController.view.mas_bottom).with.offset(-2); + make.left.equalTo(ROOT.topMenuViewController.view.mas_left); + make.right.equalTo(ROOT.topMenuViewController.view.mas_right); + make.height.equalTo(@2.0); + }]; + } +} + +- (void)hideProgressViewAnimated:(BOOL)animated { + if (!animated) { + [self _hideProgressView]; + return; + } + + [UIView animateWithDuration:0.25 animations:^{ + [self _hideProgressView]; + } completion:^(BOOL finished) { + }]; +} + +- (void)_hideProgressView { + self.progressView.alpha = 0.0; +} + +- (void)updateProgress:(CGFloat)progress animated:(BOOL)animated completion:(dispatch_block_t)completion { + [self.progressView setProgress:progress animated:animated completion:completion]; +} + +- (CGFloat)totalProgressWithArticleFetcherProgress:(CGFloat)progress { + return 0.75 * progress; +} + +#pragma mark - Sharing - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { if (action == @selector(shareSnippet:)) { @@ -2119,7 +2173,7 @@ return selectedText.length < kMinimumTextSelectionLength ? @"" : selectedText; } -#pragma mark Tracking Footer +#pragma mark - Tracking Footer - (void)setupTrackingFooter { if (!self.footerContainer) { diff --git a/Wikipedia/View Controllers/WebView/WebViewController_Private.h b/Wikipedia/View Controllers/WebView/WebViewController_Private.h index c7fe503..dcfa4b7 100644 --- a/Wikipedia/View Controllers/WebView/WebViewController_Private.h +++ b/Wikipedia/View Controllers/WebView/WebViewController_Private.h @@ -67,9 +67,9 @@ #import "UIScrollView+WMFScrollsToTop.h" #import "UIColor+WMFHexColor.h" -#import "WMFLoadingIndicatorOverlay.h" - #import "URLCache.h" + +#import "WMFProgressLineView.h" //#import "UIView+Debugging.h" @@ -148,8 +148,6 @@ @property (weak, nonatomic) IBOutlet NSLayoutConstraint* bottomNavHeightConstraint; -@property (strong, nonatomic) WMFLoadingIndicatorOverlay* loadingIndicatorOverlay; - @property (strong, nonatomic) WMFWebViewFooterContainerView* footerContainer; @property (strong, nonatomic) WMFWebViewFooterViewController* footerViewController; @@ -159,6 +157,10 @@ @property (nonatomic) BOOL keyboardIsVisible; +@property (strong, nonatomic) WMFProgressLineView* progressView; + +@property (assign, nonatomic) BOOL isFetchingArticle; + /** * Designated initializer. * @param session The current session, defaults to `+[SessionSingleton sharedInstance]`. -- To view, visit https://gerrit.wikimedia.org/r/210411 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I89326831f795cdc03c12ed054b00489f255b5f0e Gerrit-PatchSet: 6 Gerrit-Project: apps/ios/wikipedia Gerrit-Branch: master Gerrit-Owner: Fjalapeno <cfl...@wikimedia.org> Gerrit-Reviewer: Bgerstle <bgers...@wikimedia.org> Gerrit-Reviewer: Fjalapeno <cfl...@wikimedia.org> Gerrit-Reviewer: Mhurd <mh...@wikimedia.org> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits