// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/follow/ui_bundled/first_follow_coordinator.h"
#import "ios/chrome/browser/discover_feed/model/discover_feed_service.h"
#import "ios/chrome/browser/discover_feed/model/discover_feed_service_factory.h"
#import "ios/chrome/browser/favicon/model/favicon_loader.h"
#import "ios/chrome/browser/favicon/model/ios_chrome_favicon_loader_factory.h"
#import "ios/chrome/browser/follow/model/followed_web_site.h"
#import "ios/chrome/browser/follow/model/followed_web_site_state.h"
#import "ios/chrome/browser/follow/ui_bundled/first_follow_view_controller.h"
#import "ios/chrome/browser/net/model/crurl.h"
#import "ios/chrome/browser/ntp/shared/metrics/feed_metrics_recorder.h"
#import "ios/chrome/browser/shared/model/browser/browser.h"
#import "ios/chrome/browser/shared/public/commands/command_dispatcher.h"
#import "ios/chrome/browser/shared/public/commands/new_tab_page_commands.h"
#import "ios/chrome/common/ui/confirmation_alert/confirmation_alert_action_handler.h"
#import "ios/chrome/common/ui/favicon/favicon_attributes.h"
#import "ios/chrome/common/ui/favicon/favicon_constants.h"
#import "net/base/apple/url_conversions.h"
namespace {
// Sets a custom radius for the half sheet presentation.
constexpr CGFloat kHalfSheetCornerRadius = 20;
} // namespace
@interface FirstFollowCoordinator () <ConfirmationAlertActionHandler>
// FaviconLoader retrieves favicons for a given page URL.
@property(nonatomic, assign) FaviconLoader* faviconLoader;
// Feed metrics recorder.
@property(nonatomic, weak) FeedMetricsRecorder* feedMetricsRecorder;
@end
@implementation FirstFollowCoordinator {
FollowedWebSite* _followedWebSite;
}
#pragma mark - ChromeCoordinator
- (instancetype)initWithBaseViewController:(UIViewController*)viewController
browser:(Browser*)browser
followedWebSite:(FollowedWebSite*)followedWebSite {
if ((self = [super initWithBaseViewController:viewController
browser:browser])) {
_followedWebSite = followedWebSite;
}
return self;
}
- (void)start {
self.feedMetricsRecorder = DiscoverFeedServiceFactory::GetForBrowserState(
self.browser->GetBrowserState())
->GetFeedMetricsRecorder();
__weak __typeof(self) weakSelf = self;
// Most of time the page url of a followed site is a valid url, but sometimes
// it is an invalid url with only a scheme. At this time, use the RSS url
// instead. For a followed website, at least one url between the `webPageURL`
// and `RSSURL` should be valid with a host.
NSURL* followedSiteURL = _followedWebSite.webPageURL.host
? _followedWebSite.webPageURL
: _followedWebSite.RSSURL;
DCHECK(followedSiteURL.host);
FirstFollowViewController* firstFollowViewController =
[[FirstFollowViewController alloc]
initWithTitle:_followedWebSite.title
active:_followedWebSite.state ==
FollowedWebSiteStateStateActive
? YES
: NO
faviconSource:^(void (^completion)(UIImage* favicon)) {
[weakSelf faviconForPageURL:followedSiteURL completion:completion];
}];
firstFollowViewController.actionHandler = self;
self.faviconLoader = IOSChromeFaviconLoaderFactory::GetForBrowserState(
self.browser->GetBrowserState());
firstFollowViewController.modalPresentationStyle =
UIModalPresentationPageSheet;
UISheetPresentationController* presentationController =
firstFollowViewController.sheetPresentationController;
presentationController.prefersEdgeAttachedInCompactHeight = YES;
presentationController.widthFollowsPreferredContentSizeWhenEdgeAttached = YES;
presentationController.detents = @[
UISheetPresentationControllerDetent.mediumDetent,
UISheetPresentationControllerDetent.largeDetent
];
presentationController.preferredCornerRadius = kHalfSheetCornerRadius;
[self.baseViewController
presentViewController:firstFollowViewController
animated:YES
completion:^() {
[weakSelf.feedMetricsRecorder recordFirstFollowShown];
}];
}
- (void)stop {
if (self.baseViewController.presentedViewController) {
[self.baseViewController dismissViewControllerAnimated:NO completion:nil];
}
}
#pragma mark - ConfirmationAlertActionHandler
- (void)confirmationAlertPrimaryAction {
[self.feedMetricsRecorder recordFirstFollowTappedGoToFeed];
if (self.baseViewController.presentedViewController) {
__weak __typeof(self) weakSelf = self;
[self.baseViewController
dismissViewControllerAnimated:YES
completion:^{
[weakSelf openNTPToFollowIfFeedAvailable];
}];
}
}
- (void)confirmationAlertSecondaryAction {
[self.feedMetricsRecorder recordFirstFollowTappedGotIt];
if (self.baseViewController.presentedViewController) {
[self.baseViewController dismissViewControllerAnimated:YES completion:nil];
}
}
#pragma mark - Helpers
- (void)faviconForPageURL:(NSURL*)URL
completion:(void (^)(UIImage*))completion {
self.faviconLoader->FaviconForPageUrl(
net::GURLWithNSURL(URL), kDesiredSmallFaviconSizePt, kMinFaviconSizePt,
/*fallback_to_google_server=*/true, ^(FaviconAttributes* attributes) {
completion(attributes.faviconImage);
});
}
// The dispatcher used for NewTabPageCommands.
- (id<NewTabPageCommands>)newTabPageCommandsHandler {
return HandlerForProtocol(self.browser->GetCommandDispatcher(),
NewTabPageCommands);
}
- (void)openNTPToFollowIfFeedAvailable {
if (_followedWebSite.state == FollowedWebSiteStateStateActive) {
[self.newTabPageCommandsHandler
openNTPScrolledIntoFeedType:FeedTypeFollowing];
}
}
@end