Commit ecb8fb27 authored by sczs's avatar sczs Committed by Chromium LUCI CQ

[ios] Adds Discover Feed on/off support for refactored NTP.

- If the Discover Feed is OFF then the non refactored version (which
uses ContentSuggestionsVC as the main NTP VC) will be used, for this
container VC is created on NTPCoordinator which is returned to BVC.
The contained VC will change (between NTPVC and ContentSuggestionsVC)
depending on the Feed being ON or OFF.
- Adds an extra check on most IsRefactoredNTP calls, so the refactored
NTP is only used when the Discover Feed is on.
- Moves the NTPHomeMediator creation to NTPCoordinator.

Bug: 1114792
Change-Id: I64b82462825da7bd66f1004e89f55c64313f1dbb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2625508
Commit-Queue: Sergio Collazos <sczs@chromium.org>
Reviewed-by: default avatarAdam Trudeau-Arcaro <adamta@google.com>
Cr-Commit-Position: refs/heads/master@{#843197}
parent 1ff4677b
......@@ -12,7 +12,9 @@ class WebState;
}
@class ContentSuggestionsHeaderViewController;
@protocol NewTabPageCommands;
@protocol NewTabPageControllerDelegate;
@class NTPHomeMediator;
@class ViewRevealingVerticalPanHandler;
// Coordinator to manage the Suggestions UI via a
......@@ -36,6 +38,15 @@ class WebState;
// The pan gesture handler for the view controller.
@property(nonatomic, weak) ViewRevealingVerticalPanHandler* panGestureHandler;
// NTP Mediator used by this Coordinator.
// TODO(crbug.com/1114792): Move all usage of this mediator to NTPCoordinator.
// It might also be necessary to split it and create a ContentSuggestions
// mediator for non NTP logic.
@property(nonatomic, strong) NTPHomeMediator* ntpMediator;
// Command handler for NTP related commands.
@property(nonatomic, weak) id<NewTabPageCommands> ntpCommandHandler;
// Dismisses all modals owned by the NTP mediator.
- (void)dismissModals;
......@@ -61,6 +72,9 @@ class WebState;
// Constrains the named layout guide for the Discover header menu button.
- (void)constrainDiscoverHeaderMenuButtonNamedGuide;
// YES if the Discover feed is currently visible.
- (BOOL)isDiscoverFeedVisible;
@end
#endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_COORDINATOR_H_
......@@ -29,8 +29,8 @@
// Creates layout with |offset| as additional height. Allows the view's height
// to be increased enough to maintain the scroll position. Only needed if
// Discover feed is enabled.
- (instancetype)initWithOffset:(CGFloat)offset;
// Discover feed is visible.
- (instancetype)initWithOffset:(CGFloat)offset feedVisible:(BOOL)visible;
@end
......
......@@ -15,22 +15,29 @@
#error "This file requires ARC support."
#endif
@interface ContentSuggestionsLayout ()
// YES if the Discover Feed is currently visible.
@property(nonatomic, assign, getter=isFeedVisible) BOOL feedVisible;
@end
@implementation ContentSuggestionsLayout
- (instancetype)initWithOffset:(CGFloat)offset {
- (instancetype)initWithOffset:(CGFloat)offset feedVisible:(BOOL)visible {
if (self = [super init]) {
_feedVisible = visible;
_offset = offset;
}
return self;
}
- (CGSize)collectionViewContentSize {
if (IsRefactoredNTP()) {
// In the refactored NTP, we don't want to extend the view height beyond its
// content.
if (IsRefactoredNTP() && [self isFeedVisible]) {
// In the refactored NTP and when the Feed is visible, we don't want to
// extend the view height beyond its content.
return [super collectionViewContentSize];
}
DCHECK(!IsRefactoredNTP());
CGFloat collectionViewHeight = self.collectionView.bounds.size.height;
CGFloat headerHeight = [self firstHeaderHeight];
......@@ -116,7 +123,7 @@ layoutAttributesForSupplementaryViewOfKind:(NSString*)kind
if ([kind isEqualToString:UICollectionElementKindSectionHeader] &&
indexPath.section == 0) {
CGFloat contentOffset;
if (IsRefactoredNTP()) {
if (IsRefactoredNTP() && [self isFeedVisible]) {
contentOffset = self.parentCollectionView.contentOffset.y +
self.collectionView.contentSize.height;
} else {
......@@ -136,8 +143,11 @@ layoutAttributesForSupplementaryViewOfKind:(NSString*)kind
ToolbarExpandedHeight(
[UIApplication sharedApplication].preferredContentSizeCategory) -
topSafeArea;
if (contentOffset > minY &&
(!IsRefactoredNTP() || !self.isScrolledIntoFeed)) {
// TODO(crbug.com/1114792): Remove mentioned of "refactored" from the
// variable name once this launches.
BOOL hasScrolledIntoRefactoredDiscoverFeed =
[self isFeedVisible] && self.isScrolledIntoFeed && IsRefactoredNTP();
if (contentOffset > minY && !hasScrolledIntoRefactoredDiscoverFeed) {
origin.y = contentOffset - minY;
}
attributes.frame = {origin, attributes.frame.size};
......
......@@ -38,9 +38,10 @@ extern NSString* const
ContentSuggestionsConsumer>
// Inits view controller with |offset| to maintain scroll position if needed.
// Offset is only required if Discover feed is enabled.
// Offset is only required if Discover feed is visible.
- (instancetype)initWithStyle:(CollectionViewControllerStyle)style
offset:(CGFloat)offset NS_DESIGNATED_INITIALIZER;
offset:(CGFloat)offset
feedVisible:(BOOL)visible NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithLayout:(UICollectionViewLayout*)layout
style:(CollectionViewControllerStyle)style
......
......@@ -116,9 +116,11 @@ NSString* const kContentSuggestionsMostVisitedAccessibilityIdentifierPrefix =
#pragma mark - Lifecycle
- (instancetype)initWithStyle:(CollectionViewControllerStyle)style
offset:(CGFloat)offset {
offset:(CGFloat)offset
feedVisible:(BOOL)visible {
_offset = offset;
_layout = [[ContentSuggestionsLayout alloc] initWithOffset:offset];
_layout = [[ContentSuggestionsLayout alloc] initWithOffset:offset
feedVisible:visible];
self = [super initWithLayout:_layout style:style];
if (self) {
_collectionUpdater = [[ContentSuggestionsCollectionUpdater alloc] init];
......
......@@ -4,6 +4,7 @@
source_set("ntp") {
sources = [
"new_tab_page_commands.h",
"new_tab_page_content_delegate.h",
"new_tab_page_controller_delegate.h",
"new_tab_page_header_constants.h",
......@@ -26,6 +27,8 @@ source_set("coordinator") {
":ntp_internal",
"//ios/chrome/browser/browser_state",
"//ios/chrome/browser/main:public",
"//ios/chrome/browser/search_engines",
"//ios/chrome/browser/signin",
"//ios/chrome/browser/ui/commands",
"//ios/chrome/browser/ui/content_suggestions",
"//ios/chrome/browser/ui/content_suggestions:content_suggestions_ui",
......@@ -34,7 +37,9 @@ source_set("coordinator") {
"//ios/chrome/browser/ui/main:scene_state_observer",
"//ios/chrome/browser/ui/overscroll_actions",
"//ios/chrome/browser/url_loading",
"//ios/chrome/browser/voice",
"//ios/chrome/browser/web_state_list",
"//ios/chrome/common/ui/util",
"//ios/public/provider/chrome/browser",
"//ios/public/provider/chrome/browser/discover_feed",
"//ios/public/provider/chrome/browser/voice",
......
// Copyright 2021 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_NTP_NEW_TAB_PAGE_COMMANDS_H_
#define IOS_CHROME_BROWSER_UI_NTP_NEW_TAB_PAGE_COMMANDS_H_
// Commands to communicate back to the NewTabPageCoordinator
@protocol NewTabPageCommands
// Called when the Discover Feed changes it visibility.
- (void)setDiscoverFeedVisible:(BOOL)visible;
@end
#endif // IOS_CHROME_BROWSER_UI_NTP_NEW_TAB_PAGE_COMMANDS_H_
......@@ -9,6 +9,9 @@
#include "base/metrics/user_metrics_action.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#import "ios/chrome/browser/main/browser.h"
#import "ios/chrome/browser/search_engines/template_url_service_factory.h"
#import "ios/chrome/browser/signin/authentication_service_factory.h"
#import "ios/chrome/browser/signin/identity_manager_factory.h"
#import "ios/chrome/browser/ui/commands/application_commands.h"
#import "ios/chrome/browser/ui/commands/browser_commands.h"
#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
......@@ -17,16 +20,20 @@
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.h"
#import "ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.h"
#import "ios/chrome/browser/ui/main/scene_state.h"
#import "ios/chrome/browser/ui/main/scene_state_browser_agent.h"
#import "ios/chrome/browser/ui/main/scene_state_observer.h"
#import "ios/chrome/browser/ui/ntp/discover_feed_wrapper_view_controller.h"
#import "ios/chrome/browser/ui/ntp/incognito_view_controller.h"
#import "ios/chrome/browser/ui/ntp/new_tab_page_commands.h"
#import "ios/chrome/browser/ui/ntp/new_tab_page_content_delegate.h"
#import "ios/chrome/browser/ui/ntp/new_tab_page_feature.h"
#import "ios/chrome/browser/ui/ntp/new_tab_page_view_controller.h"
#import "ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h"
#import "ios/chrome/browser/url_loading/url_loading_browser_agent.h"
#import "ios/chrome/browser/voice/voice_search_availability.h"
#import "ios/chrome/common/ui/util/constraints_ui_util.h"
#import "ios/public/provider/chrome/browser/chrome_browser_provider.h"
#import "ios/public/provider/chrome/browser/discover_feed/discover_feed_provider.h"
#import "ios/web/public/navigation/navigation_context.h"
......@@ -38,9 +45,13 @@
#error "This file requires ARC support."
#endif
@interface NewTabPageCoordinator () <NewTabPageContentDelegate,
@interface NewTabPageCoordinator () <NewTabPageCommands,
NewTabPageContentDelegate,
OverscrollActionsControllerDelegate,
SceneStateObserver>
SceneStateObserver> {
// Helper object managing the availability of the voice search feature.
VoiceSearchAvailability _voiceSearchAvailability;
}
// Coordinator for the ContentSuggestions.
@property(nonatomic, strong)
......@@ -49,6 +60,12 @@
// View controller for the regular NTP.
@property(nonatomic, strong) NewTabPageViewController* ntpViewController;
// Mediator owned by this Coordinator.
@property(nonatomic, strong) NTPHomeMediator* NTPMediator;
// Authentication Service for the user's signed-in state.
@property(nonatomic, assign) AuthenticationService* authService;
// View controller wrapping the Discover feed.
@property(nonatomic, strong)
DiscoverFeedWrapperViewController* discoverFeedWrapperViewController;
......@@ -75,6 +92,18 @@
@property(nonatomic, strong)
ContentSuggestionsHeaderSynchronizer* headerSynchronizer;
// The ViewController displayed by this Coordinator. This is the returned
// ViewController and will contain the |containedViewController| (Which can
// change depending on Feed visibility).
@property(nonatomic, strong) UIViewController* containerViewController;
// The coordinator contained ViewController. It can be either a
// NewTabPageViewController (When the Discover Feed is being shown) or a
// ContentSuggestionsViewController (When the Discover Feed is hidden or when
// the non refactored NTP is being used.)
// TODO(crbug.com/1114792): Update this comment when the NTP refactors launches.
@property(nonatomic, strong) UIViewController* containedViewController;
@end
@implementation NewTabPageCoordinator
......@@ -82,7 +111,11 @@
#pragma mark - ChromeCoordinator
- (instancetype)initWithBrowser:(Browser*)browser {
return [super initWithBaseViewController:nil browser:browser];
self = [super initWithBaseViewController:nil browser:browser];
if (self) {
self.containerViewController = [[UIViewController alloc] init];
}
return self;
}
- (void)start {
......@@ -99,19 +132,43 @@
UrlLoadingBrowserAgent::FromBrowser(self.browser);
self.incognitoViewController =
[[IncognitoViewController alloc] initWithUrlLoader:URLLoader];
} else {
self.started = YES;
return;
}
DCHECK(!self.contentSuggestionsCoordinator);
self.authService = AuthenticationServiceFactory::GetForBrowserState(
self.browser->GetBrowserState());
TemplateURLService* templateURLService =
ios::TemplateURLServiceFactory::GetForBrowserState(
self.browser->GetBrowserState());
self.NTPMediator = [[NTPHomeMediator alloc]
initWithWebState:self.webState
templateURLService:templateURLService
URLLoader:UrlLoadingBrowserAgent::FromBrowser(self.browser)
authService:self.authService
identityManager:IdentityManagerFactory::GetForBrowserState(
self.browser->GetBrowserState())
logoVendor:ios::GetChromeBrowserProvider()->CreateLogoVendor(
self.browser, self.webState)
voiceSearchAvailability:&_voiceSearchAvailability];
self.NTPMediator.browser = self.browser;
self.contentSuggestionsCoordinator = [[ContentSuggestionsCoordinator alloc]
initWithBaseViewController:nil
browser:self.browser];
self.contentSuggestionsCoordinator.webState = self.webState;
self.contentSuggestionsCoordinator.toolbarDelegate = self.toolbarDelegate;
self.contentSuggestionsCoordinator.panGestureHandler =
self.panGestureHandler;
self.contentSuggestionsCoordinator.panGestureHandler = self.panGestureHandler;
self.contentSuggestionsCoordinator.ntpMediator = self.NTPMediator;
self.contentSuggestionsCoordinator.ntpCommandHandler = self;
[self.contentSuggestionsCoordinator start];
if (IsRefactoredNTP()) {
if ([self isNTPRefactoredAndFeedVisible]) {
self.ntpViewController = [[NewTabPageViewController alloc]
initWithContentSuggestionsViewController:
self.contentSuggestionsCoordinator.viewController];
......@@ -146,7 +203,24 @@
[sceneState addObserver:self];
self.sceneInForeground =
sceneState.activationLevel >= SceneActivationLevelForegroundInactive;
}
UIViewController* containedViewController =
[self isNTPRefactoredAndFeedVisible]
? self.ntpViewController
: self.contentSuggestionsCoordinator.viewController;
[containedViewController
willMoveToParentViewController:self.containerViewController];
[self.containerViewController addChildViewController:containedViewController];
[self.containerViewController.view addSubview:containedViewController.view];
[containedViewController
didMoveToParentViewController:self.containerViewController];
containedViewController.view.translatesAutoresizingMaskIntoConstraints = NO;
AddSameConstraints(containedViewController.view,
self.containerViewController.view);
self.containedViewController = containedViewController;
self.started = YES;
}
......@@ -164,6 +238,11 @@
self.incognitoViewController = nil;
self.ntpViewController = nil;
self.discoverFeedWrapperViewController = nil;
[self.containedViewController willMoveToParentViewController:nil];
[self.containedViewController.view removeFromSuperview];
[self.containedViewController removeFromParentViewController];
self.started = NO;
}
......@@ -198,9 +277,7 @@
if (self.browser->GetBrowserState()->IsOffTheRecord()) {
return self.incognitoViewController;
} else {
return IsRefactoredNTP()
? self.ntpViewController
: self.contentSuggestionsCoordinator.viewController;
return self.containerViewController;
}
}
......@@ -219,7 +296,7 @@
}
- (void)willUpdateSnapshot {
if (IsRefactoredNTP()) {
if ([self isNTPRefactoredAndFeedVisible]) {
[self.ntpViewController willUpdateSnapshot];
} else {
[self.contentSuggestionsCoordinator willUpdateSnapshot];
......@@ -231,7 +308,7 @@
}
- (void)reload {
if (IsRefactoredNTP()) {
if ([self isNTPRefactoredAndFeedVisible]) {
ios::GetChromeBrowserProvider()->GetDiscoverFeedProvider()->RefreshFeed();
}
[self reloadContentSuggestions];
......@@ -255,6 +332,14 @@
[self updateVisible];
}
#pragma mark - NewTabPageCommands
- (void)setDiscoverFeedVisible:(BOOL)visible {
[self stop];
[self start];
[self.containerViewController.view layoutIfNeeded];
}
#pragma mark - LogoAnimationControllerOwnerOwner
- (id<LogoAnimationControllerOwner>)logoAnimationControllerOwner {
......@@ -346,4 +431,12 @@
.headerController heightAboveFakeOmnibox];
}
#pragma mark - Private
// YES if we're using the refactored NTP and the Discover Feed is visible.
- (BOOL)isNTPRefactoredAndFeedVisible {
return IsRefactoredNTP() &&
[self.contentSuggestionsCoordinator isDiscoverFeedVisible];
}
@end
......@@ -90,7 +90,8 @@ class NewTabPageCoordinatorTest : public PlatformTest {
NewTabPageCoordinator* coordinator_;
};
// Tests that the coordinator vends a content suggestions VC on the record.
// Tests that the coordinator doesn't vend an IncognitoViewController VC on the
// record.
TEST_F(NewTabPageCoordinatorTest, StartOnTheRecord) {
CreateCoordinator(/*off_the_record=*/false);
id omniboxCommandsHandlerMock = OCMProtocolMock(@protocol(OmniboxCommands));
......@@ -103,13 +104,7 @@ TEST_F(NewTabPageCoordinatorTest, StartOnTheRecord) {
forProtocol:@protocol(SnackbarCommands)];
[coordinator_ start];
UIViewController* viewController = [coordinator_ viewController];
if (IsRefactoredNTP()) {
EXPECT_TRUE(
[viewController isKindOfClass:[NewTabPageViewController class]]);
} else {
EXPECT_TRUE([viewController
isKindOfClass:[ContentSuggestionsViewController class]]);
}
EXPECT_FALSE([viewController isKindOfClass:[IncognitoViewController class]]);
[coordinator_ stop];
}
......
......@@ -40,7 +40,8 @@
_suggestionViewController = [[ContentSuggestionsViewController alloc]
initWithStyle:CollectionViewControllerStyleDefault
offset:0];
offset:0
feedVisible:NO];
[_suggestionViewController setDataSource:_dataSource];
_suggestionViewController.suggestionCommandHandler =
......
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