OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #import "ios/chrome/share_extension/share_extension_view.h" |
| 6 |
| 7 #include "base/logging.h" |
| 8 #import "ios/chrome/share_extension/ui_util.h" |
| 9 |
| 10 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 11 #error "This file requires ARC support." |
| 12 #endif |
| 13 |
| 14 namespace { |
| 15 |
| 16 const CGFloat kCornerRadius = 6; |
| 17 // Minimum size around the widget |
| 18 const CGFloat kDividerHeight = 0.5; |
| 19 const CGFloat kShareExtensionPadding = 16; |
| 20 const CGFloat kButtonHeight = 44; |
| 21 const CGFloat kLowAlpha = 0.3; |
| 22 |
| 23 // Size of the icon if present. |
| 24 const CGFloat kScreenshotSize = 80; |
| 25 |
| 26 // Size for the buttons font. |
| 27 const CGFloat kButtonFontSize = 17; |
| 28 |
| 29 } // namespace |
| 30 |
| 31 #pragma mark - Share Extension Button |
| 32 |
| 33 // UIButton with the background color changing when it is highlighted. |
| 34 @interface ShareExtensionButton : UIButton |
| 35 @end |
| 36 |
| 37 @implementation ShareExtensionButton |
| 38 |
| 39 - (void)setHighlighted:(BOOL)highlighted { |
| 40 [super setHighlighted:highlighted]; |
| 41 |
| 42 if (highlighted) |
| 43 self.backgroundColor = [UIColor colorWithWhite:0.98 alpha:1]; |
| 44 else |
| 45 self.backgroundColor = [UIColor clearColor]; |
| 46 } |
| 47 |
| 48 @end |
| 49 |
| 50 #pragma mark - Share Extension View |
| 51 |
| 52 @interface ShareExtensionView () { |
| 53 __weak id<ShareExtensionViewActionTarget> _target; |
| 54 } |
| 55 |
| 56 // Keep strong references of the views that need to be updated. |
| 57 @property(nonatomic, strong) UILabel* titleLabel; |
| 58 @property(nonatomic, strong) UILabel* URLLabel; |
| 59 @property(nonatomic, strong) UIImageView* screenshotView; |
| 60 |
| 61 // View creation helpers. |
| 62 // Returns a view containing the shared items (title, URL, screenshot). This |
| 63 // method will set the ivars. |
| 64 - (UIView*)sharedItemView; |
| 65 |
| 66 // Returns a button containing the with title |title| and action |selector| on |
| 67 // |_target|. |
| 68 - (UIButton*)buttonWithTitle:(NSString*)title selector:(SEL)selector; |
| 69 |
| 70 // Returns a view containing a divider with vibrancy effect. |
| 71 - (UIView*)dividerViewWithVibrancy:(UIVisualEffect*)vibrancyEffect; |
| 72 |
| 73 // Returns a navigationBar. |
| 74 - (UINavigationBar*)navigationBar; |
| 75 |
| 76 @end |
| 77 |
| 78 @implementation ShareExtensionView |
| 79 |
| 80 @synthesize titleLabel = _titleLabel; |
| 81 @synthesize URLLabel = _URLLabel; |
| 82 @synthesize screenshotView = _screenshotView; |
| 83 |
| 84 #pragma mark - Lifecycle |
| 85 |
| 86 - (instancetype)initWithActionTarget: |
| 87 (id<ShareExtensionViewActionTarget>)target { |
| 88 self = [super initWithFrame:CGRectZero]; |
| 89 if (self) { |
| 90 DCHECK(target); |
| 91 _target = target; |
| 92 |
| 93 [self.layer setCornerRadius:kCornerRadius]; |
| 94 [self setClipsToBounds:YES]; |
| 95 UIBlurEffect* blurEffect = |
| 96 [UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight]; |
| 97 UIVibrancyEffect* vibrancyEffect = |
| 98 [UIVibrancyEffect effectForBlurEffect:blurEffect]; |
| 99 |
| 100 // Add the blur effect to the whole widget. |
| 101 UIVisualEffectView* blurringView = |
| 102 [[UIVisualEffectView alloc] initWithEffect:blurEffect]; |
| 103 [self addSubview:blurringView]; |
| 104 ui_util::ConstrainAllSidesOfViewToView(self, blurringView); |
| 105 [[blurringView layer] setCornerRadius:kCornerRadius]; |
| 106 [blurringView setClipsToBounds:YES]; |
| 107 |
| 108 NSString* addToReadingListTitle = NSLocalizedString( |
| 109 @"IDS_IOS_ADD_READING_LIST_SHARE_EXTENSION", |
| 110 @"The add to reading list button text in share extension."); |
| 111 UIButton* readingListButton = [self |
| 112 buttonWithTitle:addToReadingListTitle |
| 113 selector:@selector( |
| 114 shareExtensionViewDidSelectAddToReadingList:)]; |
| 115 |
| 116 NSString* addToBookmarksTitle = NSLocalizedString( |
| 117 @"IDS_IOS_ADD_BOOKMARKS_SHARE_EXTENSION", |
| 118 @"The Add to bookmarks button text in share extension."); |
| 119 UIButton* bookmarksButton = [self |
| 120 buttonWithTitle:addToBookmarksTitle |
| 121 selector:@selector(shareExtensionViewDidSelectAddToBookmarks:)]; |
| 122 |
| 123 UIStackView* contentStack = [[UIStackView alloc] initWithArrangedSubviews:@[ |
| 124 [self navigationBar], [self dividerViewWithVibrancy:vibrancyEffect], |
| 125 [self sharedItemView], [self dividerViewWithVibrancy:vibrancyEffect], |
| 126 readingListButton, [self dividerViewWithVibrancy:vibrancyEffect], |
| 127 bookmarksButton |
| 128 ]]; |
| 129 [contentStack setAxis:UILayoutConstraintAxisVertical]; |
| 130 [[blurringView contentView] addSubview:contentStack]; |
| 131 |
| 132 [blurringView setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 133 [contentStack setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 134 |
| 135 ui_util::ConstrainAllSidesOfViewToView([blurringView contentView], |
| 136 contentStack); |
| 137 } |
| 138 return self; |
| 139 } |
| 140 |
| 141 #pragma mark Init helpers |
| 142 |
| 143 - (UIView*)sharedItemView { |
| 144 // Title label. Text will be filled by |setTitle:| when available. |
| 145 _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; |
| 146 [_titleLabel setFont:[UIFont boldSystemFontOfSize:16]]; |
| 147 [_titleLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 148 |
| 149 // URL label. Text will be filled by |setURL:| when available. |
| 150 _URLLabel = [[UILabel alloc] initWithFrame:CGRectZero]; |
| 151 [_URLLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 152 [_URLLabel setNumberOfLines:3]; |
| 153 [_URLLabel setLineBreakMode:NSLineBreakByWordWrapping]; |
| 154 [_URLLabel setFont:[UIFont systemFontOfSize:12]]; |
| 155 |
| 156 // Screenshot view. Image will be filled by |setScreenshot:| when available. |
| 157 _screenshotView = [[UIImageView alloc] initWithFrame:CGRectZero]; |
| 158 [_screenshotView.widthAnchor |
| 159 constraintLessThanOrEqualToConstant:kScreenshotSize] |
| 160 .active = YES; |
| 161 [_screenshotView.heightAnchor |
| 162 constraintLessThanOrEqualToConstant:kScreenshotSize] |
| 163 .active = YES; |
| 164 [_screenshotView setContentMode:UIViewContentModeScaleAspectFill]; |
| 165 [_screenshotView setHidden:YES]; |
| 166 |
| 167 // |_screenshotView| should take as much space as needed. Lower compression |
| 168 // resistance of the other elements. |
| 169 [_titleLabel |
| 170 setContentCompressionResistancePriority:UILayoutPriorityDefaultLow |
| 171 forAxis:UILayoutConstraintAxisHorizontal]; |
| 172 [_titleLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh |
| 173 forAxis:UILayoutConstraintAxisVertical]; |
| 174 [_URLLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh |
| 175 forAxis:UILayoutConstraintAxisVertical]; |
| 176 |
| 177 [_URLLabel |
| 178 setContentCompressionResistancePriority:UILayoutPriorityDefaultLow |
| 179 forAxis:UILayoutConstraintAxisHorizontal]; |
| 180 |
| 181 UIStackView* titleURLStack = [[UIStackView alloc] |
| 182 initWithArrangedSubviews:@[ _titleLabel, _URLLabel ]]; |
| 183 [titleURLStack setAxis:UILayoutConstraintAxisVertical]; |
| 184 |
| 185 UIView* titleURLContainer = [[UIView alloc] initWithFrame:CGRectZero]; |
| 186 [titleURLContainer setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 187 [titleURLContainer addSubview:titleURLStack]; |
| 188 [[titleURLStack topAnchor] |
| 189 constraintEqualToAnchor:[titleURLContainer topAnchor] |
| 190 constant:kShareExtensionPadding] |
| 191 .active = YES; |
| 192 [[titleURLStack bottomAnchor] |
| 193 constraintEqualToAnchor:[titleURLContainer bottomAnchor] |
| 194 constant:-kShareExtensionPadding] |
| 195 .active = YES; |
| 196 |
| 197 [titleURLStack.centerYAnchor |
| 198 constraintEqualToAnchor:titleURLContainer.centerYAnchor] |
| 199 .active = YES; |
| 200 [titleURLStack.centerXAnchor |
| 201 constraintEqualToAnchor:titleURLContainer.centerXAnchor] |
| 202 .active = YES; |
| 203 [titleURLStack.widthAnchor |
| 204 constraintEqualToAnchor:titleURLContainer.widthAnchor] |
| 205 .active = YES; |
| 206 |
| 207 UIStackView* itemStack = [[UIStackView alloc] |
| 208 initWithArrangedSubviews:@[ titleURLContainer, _screenshotView ]]; |
| 209 [itemStack setAxis:UILayoutConstraintAxisHorizontal]; |
| 210 [itemStack setLayoutMargins:UIEdgeInsetsMake(kShareExtensionPadding, |
| 211 kShareExtensionPadding, |
| 212 kShareExtensionPadding, |
| 213 kShareExtensionPadding)]; |
| 214 [itemStack setLayoutMarginsRelativeArrangement:YES]; |
| 215 [itemStack setSpacing:kShareExtensionPadding]; |
| 216 |
| 217 [_titleLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 218 [_URLLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 219 [_screenshotView setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 220 [titleURLStack setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 221 [itemStack setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 222 |
| 223 return itemStack; |
| 224 } |
| 225 |
| 226 - (UIView*)dividerViewWithVibrancy:(UIVisualEffect*)vibrancyEffect { |
| 227 UIVisualEffectView* dividerVibrancy = |
| 228 [[UIVisualEffectView alloc] initWithEffect:vibrancyEffect]; |
| 229 UIView* divider = [[UIView alloc] initWithFrame:CGRectZero]; |
| 230 [divider setBackgroundColor:[UIColor colorWithWhite:0 alpha:kLowAlpha]]; |
| 231 [[dividerVibrancy contentView] addSubview:divider]; |
| 232 [dividerVibrancy setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 233 [divider setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 234 ui_util::ConstrainAllSidesOfViewToView([dividerVibrancy contentView], |
| 235 divider); |
| 236 CGFloat slidingConstant = ui_util::AlignValueToPixel(kDividerHeight); |
| 237 [[dividerVibrancy heightAnchor] constraintEqualToConstant:slidingConstant] |
| 238 .active = YES; |
| 239 return dividerVibrancy; |
| 240 } |
| 241 |
| 242 - (UIButton*)buttonWithTitle:(NSString*)title selector:(SEL)selector { |
| 243 UIButton* systemButton = [UIButton buttonWithType:UIButtonTypeSystem]; |
| 244 UIColor* systemColor = [systemButton titleColorForState:UIControlStateNormal]; |
| 245 |
| 246 UIButton* button = [[ShareExtensionButton alloc] initWithFrame:CGRectZero]; |
| 247 [button setTitle:title forState:UIControlStateNormal]; |
| 248 [button setTitleColor:systemColor forState:UIControlStateNormal]; |
| 249 [[button titleLabel] setFont:[UIFont systemFontOfSize:kButtonFontSize]]; |
| 250 [button setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 251 [button addTarget:_target |
| 252 action:selector |
| 253 forControlEvents:UIControlEventTouchUpInside]; |
| 254 [button.heightAnchor constraintEqualToConstant:kButtonHeight].active = YES; |
| 255 return button; |
| 256 } |
| 257 |
| 258 - (UINavigationBar*)navigationBar { |
| 259 // Create the navigation bar. |
| 260 UINavigationBar* navigationBar = |
| 261 [[UINavigationBar alloc] initWithFrame:CGRectZero]; |
| 262 [[navigationBar layer] setCornerRadius:kCornerRadius]; |
| 263 [navigationBar setClipsToBounds:YES]; |
| 264 |
| 265 // Create an empty image to replace the standard gray background of the |
| 266 // UINavigationBar. |
| 267 UIImage* emptyImage = [[UIImage alloc] init]; |
| 268 [navigationBar setBackgroundImage:emptyImage |
| 269 forBarMetrics:UIBarMetricsDefault]; |
| 270 [navigationBar setShadowImage:emptyImage]; |
| 271 [navigationBar setTranslucent:YES]; |
| 272 [navigationBar setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 273 |
| 274 UIBarButtonItem* cancelButton = [[UIBarButtonItem alloc] |
| 275 initWithBarButtonSystemItem:UIBarButtonSystemItemCancel |
| 276 target:_target |
| 277 action:@selector( |
| 278 shareExtensionViewDidSelectCancel:)]; |
| 279 |
| 280 NSString* appName = |
| 281 [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]; |
| 282 UINavigationItem* titleItem = |
| 283 [[UINavigationItem alloc] initWithTitle:appName]; |
| 284 [titleItem setLeftBarButtonItem:cancelButton]; |
| 285 [titleItem setHidesBackButton:YES]; |
| 286 [navigationBar pushNavigationItem:titleItem animated:NO]; |
| 287 return navigationBar; |
| 288 } |
| 289 |
| 290 #pragma mark - Content getters and setters. |
| 291 |
| 292 - (void)setURL:(NSURL*)URL { |
| 293 [[self URLLabel] setText:[URL absoluteString]]; |
| 294 } |
| 295 |
| 296 - (void)setTitle:(NSString*)title { |
| 297 [[self titleLabel] setText:title]; |
| 298 } |
| 299 |
| 300 - (void)setScreenshot:(UIImage*)screenshot { |
| 301 [[self screenshotView] setHidden:NO]; |
| 302 [[self screenshotView] setImage:screenshot]; |
| 303 } |
| 304 |
| 305 @end |
OLD | NEW |