Commit 459a6e05 authored by sczs's avatar sczs Committed by Commit Bot

[ios]Creates DiscoverFeed Observer and Updates the Discover Feed

- ContentSuggestionsMediator uses DiscoverFeedDelegate to notify
its Coordinator of Discover Feed Changes.
- ContentSuggestionsCoordinator refreshes the Feed and sets a new
ViewController (Created with the refreshed model) via its mediator.
- Creates a DiscoverFeed Observer and its bridge in DiscoverFeedProvider.

Bug: 1085419
Change-Id: If5b91d1cf9c99e164f4d9a50b5071ae65816350b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2327846
Commit-Queue: Sergio Collazos <sczs@chromium.org>
Reviewed-by: default avatarGanggui Tang <gogerald@chromium.org>
Reviewed-by: default avatarGauthier Ambard <gambard@chromium.org>
Cr-Commit-Position: refs/heads/master@{#795324}
parent 1491c7b3
...@@ -20,6 +20,7 @@ source_set("content_suggestions") { ...@@ -20,6 +20,7 @@ source_set("content_suggestions") {
"content_suggestions_metrics_recorder.mm", "content_suggestions_metrics_recorder.mm",
"content_suggestions_service_bridge_observer.h", "content_suggestions_service_bridge_observer.h",
"content_suggestions_service_bridge_observer.mm", "content_suggestions_service_bridge_observer.mm",
"discover_feed_delegate.h",
"mediator_util.h", "mediator_util.h",
"mediator_util.mm", "mediator_util.mm",
"ntp_home_mediator.h", "ntp_home_mediator.h",
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_metrics_recorder.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_metrics_recorder.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller_audience.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller_audience.h"
#import "ios/chrome/browser/ui/content_suggestions/discover_feed_delegate.h"
#import "ios/chrome/browser/ui/content_suggestions/discover_feed_header_changing.h" #import "ios/chrome/browser/ui/content_suggestions/discover_feed_header_changing.h"
#import "ios/chrome/browser/ui/content_suggestions/discover_feed_menu_commands.h" #import "ios/chrome/browser/ui/content_suggestions/discover_feed_menu_commands.h"
#import "ios/chrome/browser/ui/content_suggestions/ntp_home_constant.h" #import "ios/chrome/browser/ui/content_suggestions/ntp_home_constant.h"
...@@ -71,6 +72,7 @@ ...@@ -71,6 +72,7 @@
@interface ContentSuggestionsCoordinator () < @interface ContentSuggestionsCoordinator () <
ContentSuggestionsMenuProvider, ContentSuggestionsMenuProvider,
ContentSuggestionsViewControllerAudience, ContentSuggestionsViewControllerAudience,
DiscoverFeedDelegate,
DiscoverFeedMenuCommands, DiscoverFeedMenuCommands,
OverscrollActionsControllerDelegate, OverscrollActionsControllerDelegate,
ThemeChangeDelegate, ThemeChangeDelegate,
...@@ -178,19 +180,7 @@ ...@@ -178,19 +180,7 @@
ReadingListModelFactory::GetForBrowserState( ReadingListModelFactory::GetForBrowserState(
self.browser->GetBrowserState()); self.browser->GetBrowserState());
self.discoverFeedViewController = ios::GetChromeBrowserProvider() self.discoverFeedViewController = [self discoverFeed];
->GetDiscoverFeedProvider()
->NewFeedViewController(self.browser);
// TODO(crbug.com/1085419): Once the CollectionView is cleanly exposed, remove
// this loop.
for (UIView* view in self.discoverFeedViewController.view.subviews) {
if ([view isKindOfClass:[UICollectionView class]]) {
UICollectionView* feedView = static_cast<UICollectionView*>(view);
feedView.bounces = false;
feedView.alwaysBounceVertical = false;
}
}
self.contentSuggestionsMediator = [[ContentSuggestionsMediator alloc] self.contentSuggestionsMediator = [[ContentSuggestionsMediator alloc]
initWithContentService:contentSuggestionsService initWithContentService:contentSuggestionsService
...@@ -204,6 +194,7 @@ ...@@ -204,6 +194,7 @@
self.contentSuggestionsMediator.headerProvider = self.headerController; self.contentSuggestionsMediator.headerProvider = self.headerController;
self.contentSuggestionsMediator.contentArticlesExpanded = self.contentSuggestionsMediator.contentArticlesExpanded =
self.contentSuggestionsVisible; self.contentSuggestionsVisible;
self.contentSuggestionsMediator.discoverFeedDelegate = self;
self.headerController.promoCanShow = self.headerController.promoCanShow =
[self.contentSuggestionsMediator notificationPromo]->CanShow(); [self.contentSuggestionsMediator notificationPromo]->CanShow();
...@@ -429,6 +420,17 @@ ...@@ -429,6 +420,17 @@
[self.alertCoordinator start]; [self.alertCoordinator start];
} }
#pragma mark - DiscoverFeedDelegate
- (void)recreateDiscoverFeedViewController {
DCHECK(IsDiscoverFeedEnabled());
// Create and set a new DiscoverFeed since that its model has changed.
self.discoverFeedViewController = [self discoverFeed];
self.contentSuggestionsMediator.discoverFeed =
self.discoverFeedViewController;
}
#pragma mark - Public methods #pragma mark - Public methods
- (UIView*)view { - (UIView*)view {
...@@ -499,4 +501,27 @@ ...@@ -499,4 +501,27 @@
actionProvider:actionProvider]; actionProvider:actionProvider];
} }
#pragma mark - Helpers
// Creates, configures and returns a DiscoverFeed ViewController.
- (UIViewController*)discoverFeed {
if (!IsDiscoverFeedEnabled())
return nil;
UIViewController* discoverFeed = ios::GetChromeBrowserProvider()
->GetDiscoverFeedProvider()
->NewFeedViewController(self.browser);
// TODO(crbug.com/1085419): Once the CollectionView is cleanly exposed, remove
// this loop.
for (UIView* view in discoverFeed.view.subviews) {
if ([view isKindOfClass:[UICollectionView class]]) {
UICollectionView* feedView = static_cast<UICollectionView*>(view);
feedView.bounces = NO;
feedView.alwaysBounceVertical = NO;
feedView.scrollEnabled = NO;
}
}
return discoverFeed;
}
@end @end
...@@ -31,6 +31,7 @@ class MostVisitedSites; ...@@ -31,6 +31,7 @@ class MostVisitedSites;
@protocol ContentSuggestionsGestureCommands; @protocol ContentSuggestionsGestureCommands;
@protocol ContentSuggestionsHeaderProvider; @protocol ContentSuggestionsHeaderProvider;
@class ContentSuggestionIdentifier; @class ContentSuggestionIdentifier;
@protocol DiscoverFeedDelegate;
class GURL; class GURL;
class LargeIconCache; class LargeIconCache;
class NotificationPromoWhatsNew; class NotificationPromoWhatsNew;
...@@ -73,7 +74,10 @@ class ReadingListModel; ...@@ -73,7 +74,10 @@ class ReadingListModel;
@property(nonatomic, assign) BOOL readingListNeedsReload; @property(nonatomic, assign) BOOL readingListNeedsReload;
// ViewController created by the Discover provider containing the Discover feed. // ViewController created by the Discover provider containing the Discover feed.
@property(nonatomic, strong) UIViewController* discoverFeed; @property(nonatomic, weak) UIViewController* discoverFeed;
// Delegate used to communicate to communicate events to the DiscoverFeed.
@property(nonatomic, weak) id<DiscoverFeedDelegate> discoverFeedDelegate;
// Disconnects the mediator. // Disconnects the mediator.
- (void)disconnect; - (void)disconnect;
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_feature.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_feature.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_header_provider.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_header_provider.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_service_bridge_observer.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_service_bridge_observer.h"
#import "ios/chrome/browser/ui/content_suggestions/discover_feed_delegate.h"
#import "ios/chrome/browser/ui/content_suggestions/identifier/content_suggestion_identifier.h" #import "ios/chrome/browser/ui/content_suggestions/identifier/content_suggestion_identifier.h"
#import "ios/chrome/browser/ui/content_suggestions/identifier/content_suggestions_section_information.h" #import "ios/chrome/browser/ui/content_suggestions/identifier/content_suggestions_section_information.h"
#import "ios/chrome/browser/ui/content_suggestions/mediator_util.h" #import "ios/chrome/browser/ui/content_suggestions/mediator_util.h"
...@@ -43,6 +44,7 @@ ...@@ -43,6 +44,7 @@
#include "ios/chrome/browser/ui/util/ui_util.h" #include "ios/chrome/browser/ui/util/ui_util.h"
#include "ios/chrome/common/app_group/app_group_constants.h" #include "ios/chrome/common/app_group/app_group_constants.h"
#include "ios/public/provider/chrome/browser/chrome_browser_provider.h" #include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
#import "ios/public/provider/chrome/browser/discover_feed/discover_feed_observer_bridge.h"
#include "ios/public/provider/chrome/browser/images/branded_image_provider.h" #include "ios/public/provider/chrome/browser/images/branded_image_provider.h"
#if !defined(__has_feature) || !__has_feature(objc_arc) #if !defined(__has_feature) || !__has_feature(objc_arc)
...@@ -59,6 +61,7 @@ const NSInteger kMaxNumMostVisitedTiles = 4; ...@@ -59,6 +61,7 @@ const NSInteger kMaxNumMostVisitedTiles = 4;
} // namespace } // namespace
@interface ContentSuggestionsMediator () <BooleanObserver, @interface ContentSuggestionsMediator () <BooleanObserver,
DiscoverFeedObserverBridgeDelegate,
ContentSuggestionsItemDelegate, ContentSuggestionsItemDelegate,
ContentSuggestionsServiceObserver, ContentSuggestionsServiceObserver,
MostVisitedSitesObserving, MostVisitedSitesObserving,
...@@ -74,6 +77,9 @@ const NSInteger kMaxNumMostVisitedTiles = 4; ...@@ -74,6 +77,9 @@ const NSInteger kMaxNumMostVisitedTiles = 4;
std::unique_ptr<PrefObserverBridge> _prefObserverBridge; std::unique_ptr<PrefObserverBridge> _prefObserverBridge;
// Registrar for pref changes notifications. // Registrar for pref changes notifications.
std::unique_ptr<PrefChangeRegistrar> _prefChangeRegistrar; std::unique_ptr<PrefChangeRegistrar> _prefChangeRegistrar;
// Observes changes in the DiscoverFeed.
std::unique_ptr<DiscoverFeedObserverBridge>
_discoverFeedProviderObserverBridge;
} }
// Whether the contents section should be hidden completely. // Whether the contents section should be hidden completely.
...@@ -168,9 +174,10 @@ const NSInteger kMaxNumMostVisitedTiles = 4; ...@@ -168,9 +174,10 @@ const NSInteger kMaxNumMostVisitedTiles = 4;
_learnMoreItem = [[ContentSuggestionsLearnMoreItem alloc] init]; _learnMoreItem = [[ContentSuggestionsLearnMoreItem alloc] init];
_discoverFeed = discoverFeed;
_discoverSectionInfo = DiscoverSectionInformation(); _discoverSectionInfo = DiscoverSectionInformation();
_discoverItem = [[ContentSuggestionsDiscoverItem alloc] init]; _discoverItem = [[ContentSuggestionsDiscoverItem alloc] init];
_discoverItem.discoverFeed = discoverFeed; _discoverItem.discoverFeed = _discoverFeed;
_notificationPromo = std::make_unique<NotificationPromoWhatsNew>( _notificationPromo = std::make_unique<NotificationPromoWhatsNew>(
GetApplicationContext()->GetLocalState()); GetApplicationContext()->GetLocalState());
...@@ -190,6 +197,11 @@ const NSInteger kMaxNumMostVisitedTiles = 4; ...@@ -190,6 +197,11 @@ const NSInteger kMaxNumMostVisitedTiles = 4;
_readingListModelBridge = _readingListModelBridge =
std::make_unique<ReadingListModelBridge>(self, readingListModel); std::make_unique<ReadingListModelBridge>(self, readingListModel);
if (IsDiscoverFeedEnabled()) {
_discoverFeedProviderObserverBridge =
std::make_unique<DiscoverFeedObserverBridge>(self);
}
} }
return self; return self;
} }
...@@ -197,6 +209,7 @@ const NSInteger kMaxNumMostVisitedTiles = 4; ...@@ -197,6 +209,7 @@ const NSInteger kMaxNumMostVisitedTiles = 4;
- (void)disconnect { - (void)disconnect {
_prefChangeRegistrar.reset(); _prefChangeRegistrar.reset();
_prefObserverBridge.reset(); _prefObserverBridge.reset();
_discoverFeedProviderObserverBridge.reset();
} }
- (void)reloadAllData { - (void)reloadAllData {
...@@ -747,6 +760,13 @@ const NSInteger kMaxNumMostVisitedTiles = 4; ...@@ -747,6 +760,13 @@ const NSInteger kMaxNumMostVisitedTiles = 4;
[contentArticlesExpanded setObserver:self]; [contentArticlesExpanded setObserver:self];
} }
- (void)setDiscoverFeed:(UIViewController*)discoverFeed {
DCHECK(_discoverFeed != discoverFeed);
_discoverFeed = discoverFeed;
_discoverItem.discoverFeed = _discoverFeed;
[self.dataSink reloadAllData];
}
#pragma mark - PrefObserverDelegate #pragma mark - PrefObserverDelegate
- (void)onPreferenceChanged:(const std::string&)preferenceName { - (void)onPreferenceChanged:(const std::string&)preferenceName {
...@@ -769,4 +789,10 @@ const NSInteger kMaxNumMostVisitedTiles = 4; ...@@ -769,4 +789,10 @@ const NSInteger kMaxNumMostVisitedTiles = 4;
} }
} }
#pragma mark - DiscoverFeedObserverBridge
- (void)onDiscoverFeedModelRecreated {
[self.discoverFeedDelegate recreateDiscoverFeedViewController];
}
@end @end
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_DISCOVER_FEED_DELEGATE_H_
#define IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_DISCOVER_FEED_DELEGATE_H_
// Protocol for events related to the Discover Feed.
@protocol DiscoverFeedDelegate
// Informs the DiscoverFeedDelegate that the FeedViewController needs to be
// re-created.
- (void)recreateDiscoverFeedViewController;
@end
#endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_DISCOVER_FEED_DELEGATE_H_
...@@ -5,8 +5,13 @@ ...@@ -5,8 +5,13 @@
source_set("discover_feed") { source_set("discover_feed") {
configs += [ "//build/config/compiler:enable_arc" ] configs += [ "//build/config/compiler:enable_arc" ]
sources = [ sources = [
"discover_feed_observer_bridge.h",
"discover_feed_observer_bridge.mm",
"discover_feed_provider.h", "discover_feed_provider.h",
"discover_feed_provider.mm", "discover_feed_provider.mm",
] ]
deps = [ "//base" ] deps = [
"//base",
"//ios/public/provider/chrome/browser",
]
} }
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_PUBLIC_PROVIDER_CHROME_BROWSER_DISCOVER_FEED_DISCOVER_FEED_OBSERVER_BRIDGE_H_
#define IOS_PUBLIC_PROVIDER_CHROME_BROWSER_DISCOVER_FEED_DISCOVER_FEED_OBSERVER_BRIDGE_H_
#import <Foundation/Foundation.h>
#import "ios/public/provider/chrome/browser/discover_feed/discover_feed_provider.h"
#include "base/scoped_observer.h"
// Implement this protocol and pass your implementation into an
// DiscoveFeedObserverBridge object to receive DiscoverFeed observer
// callbacks in Objective-C.
@protocol DiscoverFeedObserverBridgeDelegate <NSObject>
@optional
// These callbacks follow the semantics of the corresponding
// DiscoverFeedProviderImpl::Observer callbacks. See the comments on
// DiscoverFeedProviderImpl::Observer in discover_feed_provider_impl.h for the
// specification of these semantics.
- (void)onDiscoverFeedModelRecreated;
@end
// Bridge class that listens for |DiscoverFeedProvider| notifications and
// passes them to its Objective-C delegate.
class DiscoverFeedObserverBridge : public DiscoverFeedProvider::Observer {
public:
explicit DiscoverFeedObserverBridge(
id<DiscoverFeedObserverBridgeDelegate> observer);
~DiscoverFeedObserverBridge() override;
DiscoverFeedObserverBridge(const DiscoverFeedObserverBridge&) = delete;
DiscoverFeedObserverBridge& operator=(const DiscoverFeedObserverBridge&) =
delete;
private:
// DiscoverFeedProvider::Observer implementation.
void OnDiscoverFeedModelRecreated() override;
__weak id<DiscoverFeedObserverBridgeDelegate> observer_;
ScopedObserver<DiscoverFeedProvider, DiscoverFeedProvider::Observer>
scoped_observer_{this};
};
#endif // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_DISCOVER_FEED_DISCOVER_FEED_OBSERVER_BRIDGE_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/public/provider/chrome/browser/discover_feed/discover_feed_observer_bridge.h"
#import "ios/public/provider/chrome/browser/chrome_browser_provider.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
DiscoverFeedObserverBridge::DiscoverFeedObserverBridge(
id<DiscoverFeedObserverBridgeDelegate> observer)
: observer_(observer) {
scoped_observer_.Add(
ios::GetChromeBrowserProvider()->GetDiscoverFeedProvider());
}
DiscoverFeedObserverBridge::~DiscoverFeedObserverBridge() {}
void DiscoverFeedObserverBridge::OnDiscoverFeedModelRecreated() {
if ([observer_ respondsToSelector:@selector(onDiscoverFeedModelRecreated)])
[observer_ onDiscoverFeedModelRecreated];
}
...@@ -16,6 +16,19 @@ class Browser; ...@@ -16,6 +16,19 @@ class Browser;
// Feed. // Feed.
class DiscoverFeedProvider { class DiscoverFeedProvider {
public: public:
// Observer class for discover feed events.
class Observer {
public:
Observer() {}
virtual ~Observer() {}
Observer(const Observer&) = delete;
Observer& operator=(const Observer&) = delete;
// Called whenever the FeedProvider Model has changed. At this point all
// existing Feed ViewControllers are stale and need to be refreshed.
virtual void OnDiscoverFeedModelRecreated() = 0;
};
DiscoverFeedProvider() = default; DiscoverFeedProvider() = default;
virtual ~DiscoverFeedProvider() = default; virtual ~DiscoverFeedProvider() = default;
...@@ -25,18 +38,15 @@ class DiscoverFeedProvider { ...@@ -25,18 +38,15 @@ class DiscoverFeedProvider {
// Returns true if the Discover Feed is enabled. // Returns true if the Discover Feed is enabled.
virtual bool IsDiscoverFeedEnabled(); virtual bool IsDiscoverFeedEnabled();
// Returns the Discover Feed ViewController. // Returns the Discover Feed ViewController.
// Deprecated - use the below NewFeedViewController(Browser* browser) instead.
// TODO(crbug.com/1085419): Remove this interface after rolling the downstream
// change.
virtual UIViewController* NewFeedViewController(
id<ApplicationCommands> handler) NS_RETURNS_RETAINED;
// Returns the Discover Feed ViewController.
virtual UIViewController* NewFeedViewController(Browser* browser) virtual UIViewController* NewFeedViewController(Browser* browser)
NS_RETURNS_RETAINED; NS_RETURNS_RETAINED;
// Updates the feed's theme to match the user's theme (light/dark). // Updates the feed's theme to match the user's theme (light/dark).
virtual void UpdateTheme(); virtual void UpdateTheme();
// Refreshes the Discover Feed with completion. // Refreshes the Discover Feed with completion.
virtual void RefreshFeedWithCompletion(ProceduralBlock completion); virtual void RefreshFeedWithCompletion(ProceduralBlock completion);
// Methods to register or remove observers.
virtual void AddObserver(Observer* observer);
virtual void RemoveObserver(Observer* observer);
}; };
#endif // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_DISCOVER_FEED_DISCOVER_FEED_PROVIDER_H_ #endif // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_DISCOVER_FEED_DISCOVER_FEED_PROVIDER_H_
...@@ -12,11 +12,6 @@ bool DiscoverFeedProvider::IsDiscoverFeedEnabled() { ...@@ -12,11 +12,6 @@ bool DiscoverFeedProvider::IsDiscoverFeedEnabled() {
return false; return false;
} }
UIViewController* DiscoverFeedProvider::NewFeedViewController(
id<ApplicationCommands> handler) {
return nil;
}
UIViewController* DiscoverFeedProvider::NewFeedViewController( UIViewController* DiscoverFeedProvider::NewFeedViewController(
Browser* browser) { Browser* browser) {
return nil; return nil;
...@@ -26,3 +21,6 @@ void DiscoverFeedProvider::UpdateTheme() {} ...@@ -26,3 +21,6 @@ void DiscoverFeedProvider::UpdateTheme() {}
void DiscoverFeedProvider::RefreshFeedWithCompletion( void DiscoverFeedProvider::RefreshFeedWithCompletion(
ProceduralBlock completion) {} ProceduralBlock completion) {}
void DiscoverFeedProvider::AddObserver(Observer* observer) {}
void DiscoverFeedProvider::RemoveObserver(Observer* observer) {}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment