| Index: ios/chrome/share_extension/share_extension_view.mm
|
| diff --git a/ios/chrome/share_extension/share_extension_view.mm b/ios/chrome/share_extension/share_extension_view.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c417dd5b913158c9ee88e064246b7d4613719faa
|
| --- /dev/null
|
| +++ b/ios/chrome/share_extension/share_extension_view.mm
|
| @@ -0,0 +1,305 @@
|
| +// Copyright 2016 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/chrome/share_extension/share_extension_view.h"
|
| +
|
| +#include "base/logging.h"
|
| +#import "ios/chrome/share_extension/ui_util.h"
|
| +
|
| +#if !defined(__has_feature) || !__has_feature(objc_arc)
|
| +#error "This file requires ARC support."
|
| +#endif
|
| +
|
| +namespace {
|
| +
|
| +const CGFloat kCornerRadius = 6;
|
| +// Minimum size around the widget
|
| +const CGFloat kDividerHeight = 0.5;
|
| +const CGFloat kShareExtensionPadding = 16;
|
| +const CGFloat kButtonHeight = 44;
|
| +const CGFloat kLowAlpha = 0.3;
|
| +
|
| +// Size of the icon if present.
|
| +const CGFloat kScreenshotSize = 80;
|
| +
|
| +// Size for the buttons font.
|
| +const CGFloat kButtonFontSize = 17;
|
| +
|
| +} // namespace
|
| +
|
| +#pragma mark - Share Extension Button
|
| +
|
| +// UIButton with the background color changing when it is highlighted.
|
| +@interface ShareExtensionButton : UIButton
|
| +@end
|
| +
|
| +@implementation ShareExtensionButton
|
| +
|
| +- (void)setHighlighted:(BOOL)highlighted {
|
| + [super setHighlighted:highlighted];
|
| +
|
| + if (highlighted)
|
| + self.backgroundColor = [UIColor colorWithWhite:0.98 alpha:1];
|
| + else
|
| + self.backgroundColor = [UIColor clearColor];
|
| +}
|
| +
|
| +@end
|
| +
|
| +#pragma mark - Share Extension View
|
| +
|
| +@interface ShareExtensionView () {
|
| + __weak id<ShareExtensionViewActionTarget> _target;
|
| +}
|
| +
|
| +// Keep strong references of the views that need to be updated.
|
| +@property(nonatomic, strong) UILabel* titleLabel;
|
| +@property(nonatomic, strong) UILabel* URLLabel;
|
| +@property(nonatomic, strong) UIImageView* screenshotView;
|
| +
|
| +// View creation helpers.
|
| +// Returns a view containing the shared items (title, URL, screenshot). This
|
| +// method will set the ivars.
|
| +- (UIView*)sharedItemView;
|
| +
|
| +// Returns a button containing the with title |title| and action |selector| on
|
| +// |_target|.
|
| +- (UIButton*)buttonWithTitle:(NSString*)title selector:(SEL)selector;
|
| +
|
| +// Returns a view containing a divider with vibrancy effect.
|
| +- (UIView*)dividerViewWithVibrancy:(UIVisualEffect*)vibrancyEffect;
|
| +
|
| +// Returns a navigationBar.
|
| +- (UINavigationBar*)navigationBar;
|
| +
|
| +@end
|
| +
|
| +@implementation ShareExtensionView
|
| +
|
| +@synthesize titleLabel = _titleLabel;
|
| +@synthesize URLLabel = _URLLabel;
|
| +@synthesize screenshotView = _screenshotView;
|
| +
|
| +#pragma mark - Lifecycle
|
| +
|
| +- (instancetype)initWithActionTarget:
|
| + (id<ShareExtensionViewActionTarget>)target {
|
| + self = [super initWithFrame:CGRectZero];
|
| + if (self) {
|
| + DCHECK(target);
|
| + _target = target;
|
| +
|
| + [self.layer setCornerRadius:kCornerRadius];
|
| + [self setClipsToBounds:YES];
|
| + UIBlurEffect* blurEffect =
|
| + [UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight];
|
| + UIVibrancyEffect* vibrancyEffect =
|
| + [UIVibrancyEffect effectForBlurEffect:blurEffect];
|
| +
|
| + // Add the blur effect to the whole widget.
|
| + UIVisualEffectView* blurringView =
|
| + [[UIVisualEffectView alloc] initWithEffect:blurEffect];
|
| + [self addSubview:blurringView];
|
| + ui_util::ConstrainAllSidesOfViewToView(self, blurringView);
|
| + [[blurringView layer] setCornerRadius:kCornerRadius];
|
| + [blurringView setClipsToBounds:YES];
|
| +
|
| + NSString* addToReadingListTitle = NSLocalizedString(
|
| + @"IDS_IOS_ADD_READING_LIST_SHARE_EXTENSION",
|
| + @"The add to reading list button text in share extension.");
|
| + UIButton* readingListButton = [self
|
| + buttonWithTitle:addToReadingListTitle
|
| + selector:@selector(
|
| + shareExtensionViewDidSelectAddToReadingList:)];
|
| +
|
| + NSString* addToBookmarksTitle = NSLocalizedString(
|
| + @"IDS_IOS_ADD_BOOKMARKS_SHARE_EXTENSION",
|
| + @"The Add to bookmarks button text in share extension.");
|
| + UIButton* bookmarksButton = [self
|
| + buttonWithTitle:addToBookmarksTitle
|
| + selector:@selector(shareExtensionViewDidSelectAddToBookmarks:)];
|
| +
|
| + UIStackView* contentStack = [[UIStackView alloc] initWithArrangedSubviews:@[
|
| + [self navigationBar], [self dividerViewWithVibrancy:vibrancyEffect],
|
| + [self sharedItemView], [self dividerViewWithVibrancy:vibrancyEffect],
|
| + readingListButton, [self dividerViewWithVibrancy:vibrancyEffect],
|
| + bookmarksButton
|
| + ]];
|
| + [contentStack setAxis:UILayoutConstraintAxisVertical];
|
| + [[blurringView contentView] addSubview:contentStack];
|
| +
|
| + [blurringView setTranslatesAutoresizingMaskIntoConstraints:NO];
|
| + [contentStack setTranslatesAutoresizingMaskIntoConstraints:NO];
|
| +
|
| + ui_util::ConstrainAllSidesOfViewToView([blurringView contentView],
|
| + contentStack);
|
| + }
|
| + return self;
|
| +}
|
| +
|
| +#pragma mark Init helpers
|
| +
|
| +- (UIView*)sharedItemView {
|
| + // Title label. Text will be filled by |setTitle:| when available.
|
| + _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
|
| + [_titleLabel setFont:[UIFont boldSystemFontOfSize:16]];
|
| + [_titleLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
|
| +
|
| + // URL label. Text will be filled by |setURL:| when available.
|
| + _URLLabel = [[UILabel alloc] initWithFrame:CGRectZero];
|
| + [_URLLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
|
| + [_URLLabel setNumberOfLines:3];
|
| + [_URLLabel setLineBreakMode:NSLineBreakByWordWrapping];
|
| + [_URLLabel setFont:[UIFont systemFontOfSize:12]];
|
| +
|
| + // Screenshot view. Image will be filled by |setScreenshot:| when available.
|
| + _screenshotView = [[UIImageView alloc] initWithFrame:CGRectZero];
|
| + [_screenshotView.widthAnchor
|
| + constraintLessThanOrEqualToConstant:kScreenshotSize]
|
| + .active = YES;
|
| + [_screenshotView.heightAnchor
|
| + constraintLessThanOrEqualToConstant:kScreenshotSize]
|
| + .active = YES;
|
| + [_screenshotView setContentMode:UIViewContentModeScaleAspectFill];
|
| + [_screenshotView setHidden:YES];
|
| +
|
| + // |_screenshotView| should take as much space as needed. Lower compression
|
| + // resistance of the other elements.
|
| + [_titleLabel
|
| + setContentCompressionResistancePriority:UILayoutPriorityDefaultLow
|
| + forAxis:UILayoutConstraintAxisHorizontal];
|
| + [_titleLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh
|
| + forAxis:UILayoutConstraintAxisVertical];
|
| + [_URLLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh
|
| + forAxis:UILayoutConstraintAxisVertical];
|
| +
|
| + [_URLLabel
|
| + setContentCompressionResistancePriority:UILayoutPriorityDefaultLow
|
| + forAxis:UILayoutConstraintAxisHorizontal];
|
| +
|
| + UIStackView* titleURLStack = [[UIStackView alloc]
|
| + initWithArrangedSubviews:@[ _titleLabel, _URLLabel ]];
|
| + [titleURLStack setAxis:UILayoutConstraintAxisVertical];
|
| +
|
| + UIView* titleURLContainer = [[UIView alloc] initWithFrame:CGRectZero];
|
| + [titleURLContainer setTranslatesAutoresizingMaskIntoConstraints:NO];
|
| + [titleURLContainer addSubview:titleURLStack];
|
| + [[titleURLStack topAnchor]
|
| + constraintEqualToAnchor:[titleURLContainer topAnchor]
|
| + constant:kShareExtensionPadding]
|
| + .active = YES;
|
| + [[titleURLStack bottomAnchor]
|
| + constraintEqualToAnchor:[titleURLContainer bottomAnchor]
|
| + constant:-kShareExtensionPadding]
|
| + .active = YES;
|
| +
|
| + [titleURLStack.centerYAnchor
|
| + constraintEqualToAnchor:titleURLContainer.centerYAnchor]
|
| + .active = YES;
|
| + [titleURLStack.centerXAnchor
|
| + constraintEqualToAnchor:titleURLContainer.centerXAnchor]
|
| + .active = YES;
|
| + [titleURLStack.widthAnchor
|
| + constraintEqualToAnchor:titleURLContainer.widthAnchor]
|
| + .active = YES;
|
| +
|
| + UIStackView* itemStack = [[UIStackView alloc]
|
| + initWithArrangedSubviews:@[ titleURLContainer, _screenshotView ]];
|
| + [itemStack setAxis:UILayoutConstraintAxisHorizontal];
|
| + [itemStack setLayoutMargins:UIEdgeInsetsMake(kShareExtensionPadding,
|
| + kShareExtensionPadding,
|
| + kShareExtensionPadding,
|
| + kShareExtensionPadding)];
|
| + [itemStack setLayoutMarginsRelativeArrangement:YES];
|
| + [itemStack setSpacing:kShareExtensionPadding];
|
| +
|
| + [_titleLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
|
| + [_URLLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
|
| + [_screenshotView setTranslatesAutoresizingMaskIntoConstraints:NO];
|
| + [titleURLStack setTranslatesAutoresizingMaskIntoConstraints:NO];
|
| + [itemStack setTranslatesAutoresizingMaskIntoConstraints:NO];
|
| +
|
| + return itemStack;
|
| +}
|
| +
|
| +- (UIView*)dividerViewWithVibrancy:(UIVisualEffect*)vibrancyEffect {
|
| + UIVisualEffectView* dividerVibrancy =
|
| + [[UIVisualEffectView alloc] initWithEffect:vibrancyEffect];
|
| + UIView* divider = [[UIView alloc] initWithFrame:CGRectZero];
|
| + [divider setBackgroundColor:[UIColor colorWithWhite:0 alpha:kLowAlpha]];
|
| + [[dividerVibrancy contentView] addSubview:divider];
|
| + [dividerVibrancy setTranslatesAutoresizingMaskIntoConstraints:NO];
|
| + [divider setTranslatesAutoresizingMaskIntoConstraints:NO];
|
| + ui_util::ConstrainAllSidesOfViewToView([dividerVibrancy contentView],
|
| + divider);
|
| + CGFloat slidingConstant = ui_util::AlignValueToPixel(kDividerHeight);
|
| + [[dividerVibrancy heightAnchor] constraintEqualToConstant:slidingConstant]
|
| + .active = YES;
|
| + return dividerVibrancy;
|
| +}
|
| +
|
| +- (UIButton*)buttonWithTitle:(NSString*)title selector:(SEL)selector {
|
| + UIButton* systemButton = [UIButton buttonWithType:UIButtonTypeSystem];
|
| + UIColor* systemColor = [systemButton titleColorForState:UIControlStateNormal];
|
| +
|
| + UIButton* button = [[ShareExtensionButton alloc] initWithFrame:CGRectZero];
|
| + [button setTitle:title forState:UIControlStateNormal];
|
| + [button setTitleColor:systemColor forState:UIControlStateNormal];
|
| + [[button titleLabel] setFont:[UIFont systemFontOfSize:kButtonFontSize]];
|
| + [button setTranslatesAutoresizingMaskIntoConstraints:NO];
|
| + [button addTarget:_target
|
| + action:selector
|
| + forControlEvents:UIControlEventTouchUpInside];
|
| + [button.heightAnchor constraintEqualToConstant:kButtonHeight].active = YES;
|
| + return button;
|
| +}
|
| +
|
| +- (UINavigationBar*)navigationBar {
|
| + // Create the navigation bar.
|
| + UINavigationBar* navigationBar =
|
| + [[UINavigationBar alloc] initWithFrame:CGRectZero];
|
| + [[navigationBar layer] setCornerRadius:kCornerRadius];
|
| + [navigationBar setClipsToBounds:YES];
|
| +
|
| + // Create an empty image to replace the standard gray background of the
|
| + // UINavigationBar.
|
| + UIImage* emptyImage = [[UIImage alloc] init];
|
| + [navigationBar setBackgroundImage:emptyImage
|
| + forBarMetrics:UIBarMetricsDefault];
|
| + [navigationBar setShadowImage:emptyImage];
|
| + [navigationBar setTranslucent:YES];
|
| + [navigationBar setTranslatesAutoresizingMaskIntoConstraints:NO];
|
| +
|
| + UIBarButtonItem* cancelButton = [[UIBarButtonItem alloc]
|
| + initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
|
| + target:_target
|
| + action:@selector(
|
| + shareExtensionViewDidSelectCancel:)];
|
| +
|
| + NSString* appName =
|
| + [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
|
| + UINavigationItem* titleItem =
|
| + [[UINavigationItem alloc] initWithTitle:appName];
|
| + [titleItem setLeftBarButtonItem:cancelButton];
|
| + [titleItem setHidesBackButton:YES];
|
| + [navigationBar pushNavigationItem:titleItem animated:NO];
|
| + return navigationBar;
|
| +}
|
| +
|
| +#pragma mark - Content getters and setters.
|
| +
|
| +- (void)setURL:(NSURL*)URL {
|
| + [[self URLLabel] setText:[URL absoluteString]];
|
| +}
|
| +
|
| +- (void)setTitle:(NSString*)title {
|
| + [[self titleLabel] setText:title];
|
| +}
|
| +
|
| +- (void)setScreenshot:(UIImage*)screenshot {
|
| + [[self screenshotView] setHidden:NO];
|
| + [[self screenshotView] setImage:screenshot];
|
| +}
|
| +
|
| +@end
|
|
|