blob: 19a27c76fa853bacd3320ffe277c7a273ab8489c [file] [log] [blame]
// Copyright 2017 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/clean/chrome/browser/ui/ntp/ntp_home_coordinator.h"
#include "base/mac/foundation_util.h"
#include "base/metrics/user_metrics.h"
#include "base/metrics/user_metrics_action.h"
#include "base/strings/sys_string_conversions.h"
#include "components/ntp_snippets/content_suggestions_service.h"
#include "components/ntp_tiles/most_visited_sites.h"
#include "components/reading_list/core/reading_list_model.h"
#include "components/strings/grit/components_strings.h"
#import "ios/chrome/browser/content_suggestions/content_suggestions_alert_factory.h"
#import "ios/chrome/browser/content_suggestions/content_suggestions_mediator.h"
#include "ios/chrome/browser/favicon/ios_chrome_large_icon_cache_factory.h"
#include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h"
#include "ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.h"
#include "ios/chrome/browser/ntp_tiles/ios_most_visited_sites_factory.h"
#include "ios/chrome/browser/reading_list/reading_list_model_factory.h"
#import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h"
#import "ios/chrome/browser/ui/browser_list/browser.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_gesture_commands.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.h"
#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_commands.h"
#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_header_controlling.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_delegate.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_delegate.h"
#import "ios/chrome/browser/ui/ntp/google_landing_mediator.h"
#import "ios/chrome/browser/ui/ntp/google_landing_view_controller.h"
#import "ios/chrome/browser/ui/ntp/new_tab_page_header_constants.h"
#import "ios/chrome/browser/ui/ntp/notification_promo_whats_new.h"
#import "ios/chrome/browser/ui/uikit_ui_util.h"
#include "ios/chrome/grit/ios_strings.h"
#import "ios/clean/chrome/browser/ui/ntp/ntp_home_header_coordinator.h"
#import "ios/shared/chrome/browser/ui/commands/command_dispatcher.h"
#import "ios/shared/chrome/browser/ui/coordinators/browser_coordinator+internal.h"
#import "ios/third_party/material_components_ios/src/components/Snackbar/src/MaterialSnackbar.h"
#include "ui/base/l10n/l10n_util.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface NTPHomeCoordinator ()<
ContentSuggestionsCommands,
ContentSuggestionsGestureCommands,
ContentSuggestionsHeaderViewControllerCommandHandler,
ContentSuggestionsHeaderViewControllerDelegate,
ContentSuggestionsViewControllerAudience>
@property(nonatomic, strong) AlertCoordinator* alertCoordinator;
@property(nonatomic, strong) GoogleLandingMediator* googleLandingMediator;
@property(nonatomic, strong) ContentSuggestionsMediator* suggestionsMediator;
@property(nonatomic, strong) NTPHomeHeaderCoordinator* headerCoordinator;
@property(nonatomic, strong) ContentSuggestionsViewController* viewController;
@property(nonatomic, strong)
ContentSuggestionsHeaderSynchronizer* headerCollectionInteractionHandler;
@end
@implementation NTPHomeCoordinator
@synthesize alertCoordinator = _alertCoordinator;
@synthesize headerCoordinator = _headerCoordinator;
@synthesize googleLandingMediator = _googleLandingMediator;
@synthesize viewController = _viewController;
@synthesize suggestionsMediator = _suggestionsMediator;
@synthesize headerCollectionInteractionHandler =
_headerCollectionInteractionHandler;
#pragma mark - BrowserCoordinator
- (void)start {
ntp_snippets::ContentSuggestionsService* contentSuggestionsService =
IOSChromeContentSuggestionsServiceFactory::GetForBrowserState(
self.browser->browser_state());
contentSuggestionsService->remote_suggestions_scheduler()
->OnSuggestionsSurfaceOpened();
self.headerCoordinator = [[NTPHomeHeaderCoordinator alloc] init];
self.headerCoordinator.delegate = self;
self.headerCoordinator.commandHandler = self;
[self addChildCoordinator:self.headerCoordinator];
[self.headerCoordinator start];
self.googleLandingMediator = [[GoogleLandingMediator alloc]
initWithConsumer:self.headerCoordinator.consumer
browserState:self.browser->browser_state()
dispatcher:static_cast<id>(self.browser->dispatcher())
webStateList:&self.browser->web_state_list()];
favicon::LargeIconService* largeIconService =
IOSChromeLargeIconServiceFactory::GetForBrowserState(
self.browser->browser_state());
LargeIconCache* cache = IOSChromeLargeIconCacheFactory::GetForBrowserState(
self.browser->browser_state());
std::unique_ptr<ntp_tiles::MostVisitedSites> mostVisitedFactory =
IOSMostVisitedSitesFactory::NewForBrowserState(
self.browser->browser_state());
self.suggestionsMediator = [[ContentSuggestionsMediator alloc]
initWithContentService:contentSuggestionsService
largeIconService:largeIconService
largeIconCache:cache
mostVisitedSite:std::move(mostVisitedFactory)];
self.suggestionsMediator.commandHandler = self;
self.suggestionsMediator.headerProvider =
self.headerCoordinator.headerProvider;
self.viewController = [[ContentSuggestionsViewController alloc]
initWithStyle:CollectionViewControllerStyleDefault
dataSource:self.suggestionsMediator];
self.viewController.suggestionCommandHandler = self;
self.viewController.suggestionsDelegate =
self.headerCoordinator.collectionDelegate;
self.viewController.audience = self;
[self.viewController
addChildViewController:self.headerCoordinator.viewController];
[self.headerCoordinator.viewController
didMoveToParentViewController:self.viewController];
self.headerCollectionInteractionHandler =
[[ContentSuggestionsHeaderSynchronizer alloc]
initWithCollectionController:self.viewController
headerController:self.headerCoordinator.headerController];
self.viewController.headerCommandHandler =
self.headerCollectionInteractionHandler;
self.headerCoordinator.collectionSynchronizer =
self.headerCollectionInteractionHandler;
[super start];
}
- (void)stop {
[super stop];
[self.googleLandingMediator shutdown];
[self.headerCoordinator stop];
self.viewController = nil;
self.suggestionsMediator = nil;
self.googleLandingMediator = nil;
self.headerCoordinator = nil;
}
#pragma mark - ContentSuggestionsCommands
- (void)openReadingList {
// TODO: implement this.
}
- (void)openPageForItem:(CollectionViewItem*)item {
// TODO: implement this.
}
- (void)openMostVisitedItem:(CollectionViewItem*)item
atIndex:(NSInteger)mostVisitedIndex {
// TODO: implement this.
}
- (void)displayContextMenuForSuggestion:(CollectionViewItem*)item
atPoint:(CGPoint)touchLocation
atIndexPath:(NSIndexPath*)indexPath
readLaterAction:(BOOL)readLaterAction {
ContentSuggestionsItem* suggestionsItem =
base::mac::ObjCCastStrict<ContentSuggestionsItem>(item);
self.alertCoordinator = [ContentSuggestionsAlertFactory
alertCoordinatorForSuggestionItem:suggestionsItem
onViewController:self.viewController
atPoint:touchLocation
atIndexPath:indexPath
readLaterAction:readLaterAction
commandHandler:self];
[self.alertCoordinator start];
}
- (void)displayContextMenuForMostVisitedItem:(CollectionViewItem*)item
atPoint:(CGPoint)touchLocation
atIndexPath:(NSIndexPath*)indexPath {
ContentSuggestionsMostVisitedItem* mostVisitedItem =
base::mac::ObjCCastStrict<ContentSuggestionsMostVisitedItem>(item);
self.alertCoordinator = [ContentSuggestionsAlertFactory
alertCoordinatorForMostVisitedItem:mostVisitedItem
onViewController:self.viewController
atPoint:touchLocation
atIndexPath:indexPath
commandHandler:self];
[self.alertCoordinator start];
}
- (void)handlePromoTapped {
// TODO: implement this.
}
- (void)handleLearnMoreTapped {
// TODO: implement this.
}
- (void)dismissModals {
[self.alertCoordinator stop];
self.alertCoordinator = nil;
}
#pragma mark - ContentSuggestionsGestureCommands
- (void)openNewTabWithSuggestionsItem:(ContentSuggestionsItem*)item
incognito:(BOOL)incognito {
// TODO: implement this.
}
- (void)addItemToReadingList:(ContentSuggestionsItem*)item {
base::RecordAction(base::UserMetricsAction("MobileReadingListAdd"));
ReadingListModel* readingModel = ReadingListModelFactory::GetForBrowserState(
self.browser->browser_state());
readingModel->AddEntry(item.URL, base::SysNSStringToUTF8(item.title),
reading_list::ADDED_VIA_CURRENT_APP);
}
- (void)dismissSuggestion:(ContentSuggestionsItem*)item
atIndexPath:(NSIndexPath*)indexPath {
NSIndexPath* itemIndexPath = indexPath;
if (!itemIndexPath) {
// If the caller uses a nil |indexPath|, find it from the model.
itemIndexPath =
[self.viewController.collectionViewModel indexPathForItem:item];
}
// TODO(crbug.com/691979): Add metrics.
[self.suggestionsMediator dismissSuggestion:item.suggestionIdentifier];
[self.viewController dismissEntryAtIndexPath:itemIndexPath];
}
- (void)openNewTabWithMostVisitedItem:(ContentSuggestionsMostVisitedItem*)item
incognito:(BOOL)incognito
atIndex:(NSInteger)index {
// TODO: implement this.
}
- (void)openNewTabWithMostVisitedItem:(ContentSuggestionsMostVisitedItem*)item
incognito:(BOOL)incognito {
// TODO: implement this.
}
- (void)removeMostVisited:(ContentSuggestionsMostVisitedItem*)item {
base::RecordAction(base::UserMetricsAction("MostVisited_UrlBlacklisted"));
[self.suggestionsMediator blacklistMostVisitedURL:item.URL];
[self showMostVisitedUndoForURL:item.URL];
}
#pragma mark - ContentSuggestionsHeaderViewControllerDelegate
- (BOOL)isContextMenuVisible {
return self.alertCoordinator.isVisible;
}
- (BOOL)isScrolledToTop {
return self.viewController.scrolledToTop;
}
#pragma mark - ContentSuggestionsViewControllerAudience
- (void)contentOffsetDidChange {
// TODO: implement this.
}
- (void)promoShown {
NotificationPromoWhatsNew* notificationPromo =
[self.suggestionsMediator notificationPromo];
notificationPromo->HandleViewed();
[self.headerCoordinator.consumer
setPromoCanShow:notificationPromo->CanShow()];
}
#pragma mark - Private
// Shows a snackbar with an action to undo the removal of the most visited item
// with a |URL|.
- (void)showMostVisitedUndoForURL:(GURL)URL {
GURL copiedURL = URL;
MDCSnackbarMessageAction* action = [[MDCSnackbarMessageAction alloc] init];
__weak NTPHomeCoordinator* weakSelf = self;
action.handler = ^{
NTPHomeCoordinator* strongSelf = weakSelf;
if (!strongSelf)
return;
[strongSelf.suggestionsMediator whitelistMostVisitedURL:copiedURL];
};
action.title = l10n_util::GetNSString(IDS_NEW_TAB_UNDO_THUMBNAIL_REMOVE);
action.accessibilityIdentifier = @"Undo";
TriggerHapticFeedbackForNotification(UINotificationFeedbackTypeSuccess);
MDCSnackbarMessage* message = [MDCSnackbarMessage
messageWithText:l10n_util::GetNSString(
IDS_IOS_NEW_TAB_MOST_VISITED_ITEM_REMOVED)];
message.action = action;
message.category = @"MostVisitedUndo";
[MDCSnackbarManager showMessage:message];
}
@end