Index: ios/chrome/browser/ui/bookmarks/bookmark_collection_view.mm |
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_collection_view.mm b/ios/chrome/browser/ui/bookmarks/bookmark_collection_view.mm |
index 9e4992cce7fa8d4274c0400b0fe265e444b11ab1..11bdc7924bd3907355dff07cf9d5aa2186fb466a 100644 |
--- a/ios/chrome/browser/ui/bookmarks/bookmark_collection_view.mm |
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_collection_view.mm |
@@ -21,20 +21,26 @@ |
#include "components/favicon_base/fallback_icon_style.h" |
#include "components/favicon_base/favicon_types.h" |
#include "components/pref_registry/pref_registry_syncable.h" |
+#include "components/signin/core/browser/signin_manager.h" |
#include "ios/chrome/browser/bookmarks/bookmark_model_factory.h" |
#include "ios/chrome/browser/bookmarks/bookmarks_utils.h" |
#include "ios/chrome/browser/experimental_flags.h" |
#include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h" |
#include "ios/chrome/browser/pref_names.h" |
+#include "ios/chrome/browser/signin/signin_manager_factory.h" |
+#include "ios/chrome/browser/sync/sync_setup_service.h" |
+#include "ios/chrome/browser/sync/sync_setup_service_factory.h" |
#import "ios/chrome/browser/ui/authentication/signin_promo_view.h" |
#import "ios/chrome/browser/ui/authentication/signin_promo_view_configurator.h" |
#import "ios/chrome/browser/ui/authentication/signin_promo_view_consumer.h" |
#import "ios/chrome/browser/ui/authentication/signin_promo_view_mediator.h" |
#import "ios/chrome/browser/ui/bookmarks/bookmark_collection_cells.h" |
#import "ios/chrome/browser/ui/bookmarks/bookmark_collection_view_background.h" |
+#import "ios/chrome/browser/ui/bookmarks/bookmark_home_waiting_view.h" |
#import "ios/chrome/browser/ui/bookmarks/bookmark_promo_cell.h" |
#import "ios/chrome/browser/ui/bookmarks/bookmark_signin_promo_cell.h" |
#import "ios/chrome/browser/ui/bookmarks/bookmark_utils_ios.h" |
+#import "ios/chrome/browser/ui/sync/synced_sessions_bridge.h" |
#include "ios/chrome/browser/ui/ui_util.h" |
#import "ios/chrome/browser/ui/uikit_ui_util.h" |
#include "ios/chrome/grit/ios_strings.h" |
@@ -74,15 +80,10 @@ CGFloat rowMarginTablet = 24.0; |
CGFloat rowHeight = 48.0; |
// Minimal acceptable favicon size, in points. |
CGFloat minFaviconSizePt = 16; |
- |
-// Delay in seconds to which the empty background view will be shown when the |
-// collection view is empty. |
-// This delay should not be too small to let enough time to load bookmarks |
-// from network. |
-const NSTimeInterval kShowEmptyBookmarksBackgroundRefreshDelay = 1.0; |
} |
@interface BookmarkCollectionView ()<BookmarkPromoCellDelegate, |
+ SyncedSessionsObserver, |
SigninPromoViewConsumer, |
UICollectionViewDataSource, |
UICollectionViewDelegateFlowLayout, |
@@ -107,6 +108,9 @@ const NSTimeInterval kShowEmptyBookmarksBackgroundRefreshDelay = 1.0; |
std::map<IntegerPair, base::CancelableTaskTracker::TaskId> _faviconLoadTasks; |
// Task tracker used for async favicon loads. |
base::CancelableTaskTracker _faviconTaskTracker; |
+ |
+ std::unique_ptr<synced_sessions::SyncedSessionsObserverBridge> |
+ _syncedSessionsObserver; |
} |
// Redefined to be readwrite. |
@@ -120,6 +124,9 @@ const NSTimeInterval kShowEmptyBookmarksBackgroundRefreshDelay = 1.0; |
// Background view of the collection view shown when there is no items. |
@property(nonatomic, strong) |
BookmarkCollectionViewBackground* emptyCollectionBackgroundView; |
+// Background view showing a loading spinner. |
+@property(nonatomic, strong) |
+ BookmarkHomeWaitingView* loadingSpinnerBackgroundView; |
// Shadow to display over the content. |
@property(nonatomic, strong) UIView* shadow; |
@@ -140,6 +147,7 @@ const NSTimeInterval kShowEmptyBookmarksBackgroundRefreshDelay = 1.0; |
@synthesize collectionView = _collectionView; |
@synthesize editing = _editing; |
@synthesize emptyCollectionBackgroundView = _emptyCollectionBackgroundView; |
+@synthesize loadingSpinnerBackgroundView = _loadingSpinnerBackgroundView; |
@synthesize loader = _loader; |
@synthesize longPressRecognizer = _longPressRecognizer; |
@synthesize browserState = _browserState; |
@@ -222,6 +230,7 @@ const NSTimeInterval kShowEmptyBookmarksBackgroundRefreshDelay = 1.0; |
[self setupViews]; |
[self updateCollectionView]; |
+ [self initObserver]; |
} |
return self; |
} |
@@ -241,6 +250,7 @@ const NSTimeInterval kShowEmptyBookmarksBackgroundRefreshDelay = 1.0; |
[moi self]; |
}); |
_faviconTaskTracker.TryCancelAll(); |
+ [self deallocObserver]; |
} |
#pragma mark - BookmarkHomePrimaryView |
@@ -639,6 +649,17 @@ const NSTimeInterval kShowEmptyBookmarksBackgroundRefreshDelay = 1.0; |
[self.collectionView reloadData]; |
} |
+- (void)initObserver { |
+ if (!_syncedSessionsObserver) { |
+ _syncedSessionsObserver.reset( |
+ new synced_sessions::SyncedSessionsObserverBridge(self, _browserState)); |
+ } |
+} |
+ |
+- (void)deallocObserver { |
+ _syncedSessionsObserver.reset(); |
+} |
+ |
// Returns the bookmark node associated with |indexPath|. |
- (const BookmarkNode*)nodeAtIndexPath:(NSIndexPath*)indexPath { |
if (indexPath.section == self.folderSection) |
@@ -896,21 +917,6 @@ const NSTimeInterval kShowEmptyBookmarksBackgroundRefreshDelay = 1.0; |
#pragma mark - empty background |
-// Schedules showing or hiding the empty bookmarks background view if the |
-// collection view is empty by calling showEmptyBackgroundIfNeeded after |
-// kShowEmptyBookmarksBackgroundRefreshDelay. |
-// Multiple call to this method will cancel previous scheduled call to |
-// showEmptyBackgroundIfNeeded before scheduling a new one. |
-- (void)scheduleEmptyBackgroundVisibilityUpdate { |
- [NSObject cancelPreviousPerformRequestsWithTarget:self |
- selector:@selector |
- (updateEmptyBackgroundVisibility) |
- object:nil]; |
- [self performSelector:@selector(updateEmptyBackgroundVisibility) |
- withObject:nil |
- afterDelay:kShowEmptyBookmarksBackgroundRefreshDelay]; |
-} |
- |
- (BOOL)isCollectionViewEmpty { |
BOOL collectionViewIsEmpty = YES; |
const NSInteger numberOfSections = [self numberOfSections]; |
@@ -923,13 +929,6 @@ const NSTimeInterval kShowEmptyBookmarksBackgroundRefreshDelay = 1.0; |
return collectionViewIsEmpty; |
} |
-// Shows/hides empty bookmarks background view if the collections view is empty. |
-- (void)updateEmptyBackgroundVisibility { |
- const BOOL showEmptyBackground = |
- [self isCollectionViewEmpty] && ![self shouldShowPromoCell]; |
- [self setEmptyBackgroundVisible:showEmptyBackground]; |
-} |
- |
// Shows/hides empty bookmarks background view with an animation. |
- (void)setEmptyBackgroundVisible:(BOOL)emptyBackgroundVisible { |
[UIView beginAnimations:@"alpha" context:NULL]; |
@@ -937,6 +936,59 @@ const NSTimeInterval kShowEmptyBookmarksBackgroundRefreshDelay = 1.0; |
[UIView commitAnimations]; |
} |
+// If the collection view is not empty, hide the empty bookmarks and loading |
+// spinner background. If the collection view is empty, shows the loading |
+// spinner background (if syncing) or the empty bookmarks background (if not |
+// syncing). |
+- (void)showEmptyOrLoadingSpinnerBackgroundIfNeeded { |
+ const BOOL isEmpty = |
+ [self isCollectionViewEmpty] && ![self shouldShowPromoCell]; |
+ if (!isEmpty) { |
+ [self hideLoadingSpinnerBackground]; |
+ [self hideEmptyBackground]; |
+ return; |
+ } |
+ if ([self isSyncing]) { |
+ [self showLoadingSpinnerBackground]; |
+ return; |
+ } |
+ [self showEmptyBackground]; |
+} |
+ |
+// Shows loading spinner background view |
+- (void)showLoadingSpinnerBackground { |
+ if (!self.loadingSpinnerBackgroundView) { |
+ BookmarkHomeWaitingView* loadingSpinnerBackgroundView = |
+ [[BookmarkHomeWaitingView alloc] initWithFrame:CGRectZero]; |
+ self.loadingSpinnerBackgroundView = loadingSpinnerBackgroundView; |
+ [self.loadingSpinnerBackgroundView startWaiting]; |
+ self.loadingSpinnerBackgroundView.autoresizingMask = |
+ UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; |
+ self.loadingSpinnerBackgroundView.alpha = 1; |
+ self.loadingSpinnerBackgroundView.frame = self.collectionView.bounds; |
+ } |
+ self.collectionView.backgroundView = self.loadingSpinnerBackgroundView; |
+ [self setEmptyBackgroundVisible:NO]; |
+} |
+ |
+// Hides loading spinner background view |
+- (void)hideLoadingSpinnerBackground { |
+ if (self.loadingSpinnerBackgroundView) { |
+ self.collectionView.backgroundView = self.emptyCollectionBackgroundView; |
+ self.loadingSpinnerBackgroundView = nil; |
+ } |
+} |
+ |
+- (void)showEmptyBackground { |
+ [self hideLoadingSpinnerBackground]; |
+ [self setEmptyBackgroundVisible:YES]; |
+ self.collectionView.backgroundView = self.emptyCollectionBackgroundView; |
+} |
+ |
+- (void)hideEmptyBackground { |
+ [self setEmptyBackgroundVisible:NO]; |
+} |
+ |
#pragma mark - UICollectionViewDataSource |
- (NSInteger)collectionView:(UICollectionView*)collectionView |
@@ -945,12 +997,7 @@ const NSTimeInterval kShowEmptyBookmarksBackgroundRefreshDelay = 1.0; |
[self numberOfItemsInSection:section]; |
const BOOL isCollectionViewEmpty = [self isCollectionViewEmpty]; |
self.collectionView.scrollEnabled = !isCollectionViewEmpty; |
- if (isCollectionViewEmpty) { |
- [self scheduleEmptyBackgroundVisibilityUpdate]; |
- } else { |
- // Hide empty bookmarks now. |
- [self setEmptyBackgroundVisible:NO]; |
- } |
+ [self showEmptyOrLoadingSpinnerBackgroundIfNeeded]; |
return numberOfItemsInSection; |
} |
@@ -959,12 +1006,7 @@ const NSTimeInterval kShowEmptyBookmarksBackgroundRefreshDelay = 1.0; |
const NSInteger numberOfSections = [self numberOfSections]; |
const BOOL collectionViewIsEmpty = 0 == numberOfSections; |
self.collectionView.scrollEnabled = !collectionViewIsEmpty; |
- if (collectionViewIsEmpty) { |
- [self scheduleEmptyBackgroundVisibilityUpdate]; |
- } else { |
- // Hide empty bookmarks now. |
- [self setEmptyBackgroundVisible:NO]; |
- } |
+ [self showEmptyOrLoadingSpinnerBackgroundIfNeeded]; |
return numberOfSections; |
} |
@@ -1281,4 +1323,36 @@ const NSTimeInterval kShowEmptyBookmarksBackgroundRefreshDelay = 1.0; |
return NO; |
} |
+#pragma mark - Signin and syncing status |
+ |
+- (BOOL)isSignedIn { |
+ SigninManager* signin_manager = |
+ ios::SigninManagerFactory::GetForBrowserState(_browserState); |
+ return signin_manager->IsAuthenticated(); |
+} |
+ |
+- (BOOL)isSyncing { |
+ if (![self isSignedIn]) |
+ return false; |
+ |
+ SyncSetupService* syncSetupService = |
+ SyncSetupServiceFactory::GetForBrowserState(_browserState); |
+ |
+ BOOL syncEnabled = syncSetupService->IsSyncEnabled(); |
+ BOOL noSyncError = (syncSetupService->GetSyncServiceState() == |
+ SyncSetupService::kNoSyncServiceError); |
+ |
+ return syncEnabled && noSyncError && |
+ !_syncedSessionsObserver->IsFirstSyncCycleCompleted(); |
+} |
+ |
+#pragma mark - Exposed to the SyncedSessionsObserver |
+ |
+- (void)reloadSessions { |
+} |
+ |
+- (void)onSyncStateChanged { |
+ [self showEmptyOrLoadingSpinnerBackgroundIfNeeded]; |
+} |
+ |
@end |