blob: bb427516b63db81d7fac84e33f2f12cc94c62b0d [file] [log] [blame]
// Copyright 2022 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/showcase/follow/sc_follow_view_controller.h"
#import "ios/chrome/browser/net/crurl.h"
#import "ios/chrome/browser/ui/follow/first_follow_favicon_data_source.h"
#import "ios/chrome/browser/ui/follow/first_follow_view_controller.h"
#import "ios/chrome/browser/ui/follow/follow_block_types.h"
#import "ios/chrome/browser/ui/follow/followed_web_channel.h"
#import "ios/chrome/browser/ui/icons/chrome_symbol.h"
#import "ios/chrome/browser/ui/ntp/feed_management/feed_management_follow_delegate.h"
#import "ios/chrome/browser/ui/ntp/feed_management/feed_management_navigation_delegate.h"
#import "ios/chrome/browser/ui/ntp/feed_management/feed_management_view_controller.h"
#import "ios/chrome/browser/ui/ntp/feed_management/follow_management_ui_updater.h"
#import "ios/chrome/browser/ui/ntp/feed_management/follow_management_view_controller.h"
#import "ios/chrome/browser/ui/ntp/feed_management/followed_web_channels_data_source.h"
#import "ios/chrome/browser/ui/table_view/table_view_favicon_data_source.h"
#import "ios/chrome/browser/ui/table_view/table_view_navigation_controller.h"
#import "ios/chrome/common/ui/favicon/favicon_attributes.h"
#import "ios/showcase/common/protocol_alerter.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
// Sets a custom radius for the half sheet presentation.
constexpr CGFloat kHalfSheetCornerRadius = 20;
// An example favicon URL given from the Discover backend.
static NSString* const kExampleFaviconURL = @"https://www.the-sun.com/";
// Specific symbols used to create favicons.
NSString* kGlobeSymbol = @"globe";
NSString* kGlobeAmericaSymbol = @"globe.americas.fill";
// The size of favicon symbol images.
NSInteger kFaviconSymbolPointSize = 17;
} // namespace
@interface SCFollowViewController () <FirstFollowFaviconDataSource,
FollowedWebChannelsDataSource,
TableViewFaviconDataSource>
// Shows alerts of protocol method calls.
@property(nonatomic, strong) ProtocolAlerter* alerter;
// Called to unfollow/refollow channels in the follow mgmt UI.
@property(nonatomic, weak) id<FollowManagementUIUpdater>
followManagementUIUpdater;
// An owner of the web channels list is required to test unfollow/refollow.
@property(nonatomic, strong)
NSArray<FollowedWebChannel*>* strongFollowedWebChannels;
@end
@implementation SCFollowViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.alerter = [[ProtocolAlerter alloc] initWithProtocols:@[
@protocol(FeedManagementFollowDelegate),
@protocol(FeedManagementNavigationDelegate)
]];
UIButton* button1 = [[UIButton alloc] init];
[button1 setTitle:@"Show Feed Mgmt UI" forState:UIControlStateNormal];
[button1 addTarget:self
action:@selector(handleFeedMgmtButtonTapped)
forControlEvents:UIControlEventTouchUpInside];
UIButton* button2 = [[UIButton alloc] init];
[button2 setTitle:@"Show Follow Mgmt UI" forState:UIControlStateNormal];
[button2 addTarget:self
action:@selector(handleFollowMgmtButtonTapped)
forControlEvents:UIControlEventTouchUpInside];
UIButton* button3 = [[UIButton alloc] init];
[button3 setTitle:@"Show First Follow modal" forState:UIControlStateNormal];
[button3 addTarget:self
action:@selector(handleFirstFollowButtonTapped)
forControlEvents:UIControlEventTouchUpInside];
UIStackView* verticalStack = [[UIStackView alloc]
initWithArrangedSubviews:@[ button1, button2, button3 ]];
verticalStack.axis = UILayoutConstraintAxisVertical;
verticalStack.distribution = UIStackViewDistributionFill;
verticalStack.alignment = UIStackViewAlignmentCenter;
verticalStack.spacing = 10;
verticalStack.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:verticalStack];
[NSLayoutConstraint activateConstraints:@[
[verticalStack.centerXAnchor
constraintEqualToAnchor:self.view.centerXAnchor],
[verticalStack.centerYAnchor
constraintEqualToAnchor:self.view.centerYAnchor],
]];
}
- (void)handleFeedMgmtButtonTapped {
FeedManagementViewController* feedManagementViewController =
[[FeedManagementViewController alloc]
initWithStyle:UITableViewStyleInsetGrouped];
self.alerter.baseViewController = feedManagementViewController;
feedManagementViewController.followDelegate =
static_cast<id<FeedManagementFollowDelegate>>(self.alerter);
feedManagementViewController.navigationDelegate =
static_cast<id<FeedManagementNavigationDelegate>>(self.alerter);
TableViewNavigationController* navigationController =
[[TableViewNavigationController alloc]
initWithTable:feedManagementViewController];
[self presentViewController:navigationController animated:YES completion:nil];
}
- (void)handleFollowMgmtButtonTapped {
FollowManagementViewController* followManagementViewController =
[[FollowManagementViewController alloc]
initWithStyle:UITableViewStyleInsetGrouped];
self.followManagementUIUpdater =
(id<FollowManagementUIUpdater>)followManagementViewController;
followManagementViewController.followedWebChannelsDataSource = self;
followManagementViewController.faviconDataSource = self;
TableViewNavigationController* navigationController =
[[TableViewNavigationController alloc]
initWithTable:followManagementViewController];
[self presentViewController:navigationController animated:YES completion:nil];
}
- (void)handleFirstFollowButtonTapped {
FirstFollowViewController* firstFollowViewController =
[[FirstFollowViewController alloc] init];
FollowedWebChannel* ch1 = [[FollowedWebChannel alloc] init];
ch1.title = @"First Web Channel";
ch1.available = YES;
ch1.webPageURL =
[[CrURL alloc] initWithNSURL:[NSURL URLWithString:kExampleFaviconURL]];
firstFollowViewController.followedWebChannel = ch1;
self.alerter.baseViewController = firstFollowViewController;
firstFollowViewController.faviconDataSource = self;
firstFollowViewController.imageEnclosedWithShadowAndBadge = YES;
if (@available(iOS 15, *)) {
firstFollowViewController.modalPresentationStyle =
UIModalPresentationPageSheet;
UISheetPresentationController* presentationController =
firstFollowViewController.sheetPresentationController;
presentationController.prefersEdgeAttachedInCompactHeight = YES;
presentationController.widthFollowsPreferredContentSizeWhenEdgeAttached =
YES;
presentationController.detents = @[
UISheetPresentationControllerDetent.mediumDetent,
UISheetPresentationControllerDetent.largeDetent
];
presentationController.preferredCornerRadius = kHalfSheetCornerRadius;
} else {
firstFollowViewController.modalPresentationStyle =
UIModalPresentationFormSheet;
}
[self presentViewController:firstFollowViewController
animated:YES
completion:nil];
}
#pragma mark - FollowedWebChannelsDataSource
- (NSArray<FollowedWebChannel*>*)followedWebChannels {
NSMutableArray<FollowedWebChannel*>* followedWebChannels =
[[NSMutableArray alloc] init];
for (int i = 0; i < 10; i++) {
NSString* title = [NSString stringWithFormat:@"Channel %d", i];
[followedWebChannels addObject:[self createWebChannelWithTitle:title]];
}
self.strongFollowedWebChannels = followedWebChannels;
return followedWebChannels;
}
- (FollowedWebChannel*)createWebChannelWithTitle:(NSString*)title {
FollowedWebChannel* channel = [[FollowedWebChannel alloc] init];
channel.title = title;
channel.available = YES;
channel.faviconURL =
[[CrURL alloc] initWithNSURL:[NSURL URLWithString:kExampleFaviconURL]];
__weak FollowedWebChannel* weakChannel = channel;
channel.unfollowRequestBlock = ^(RequestCompletionBlock completion) {
// This mimics a successful unfollow on the server.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC),
dispatch_get_main_queue(), ^{
[self.followManagementUIUpdater
removeFollowedWebChannel:weakChannel];
});
// This mimics refollowing after a few seconds.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 13 * NSEC_PER_SEC),
dispatch_get_main_queue(), ^{
[self.followManagementUIUpdater
addFollowedWebChannel:weakChannel];
});
};
return channel;
}
#pragma mark - TableViewFaviconDataSource & FirstFollowFaviconDataSource
- (void)faviconForURL:(CrURL*)URL
completion:(void (^)(FaviconAttributes*))completion {
// This mimics the behavior of favicon loader by immediately returning a
// default image, then fetching and returning another image.
UIImage* image1 =
DefaultSymbolTemplateWithPointSize(kGlobeSymbol, kFaviconSymbolPointSize);
UIImage* image2 = DefaultSymbolTemplateWithPointSize(kGlobeAmericaSymbol,
kFaviconSymbolPointSize);
completion([FaviconAttributes attributesWithImage:image1]);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC),
dispatch_get_main_queue(), ^{
completion([FaviconAttributes attributesWithImage:image2]);
});
}
@end