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

Reply via email to