| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "ios/chrome/share_extension/share_extension_view.h" | 5 #import "ios/chrome/share_extension/share_extension_view.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #import "ios/chrome/share_extension/ui_util.h" | 8 #import "ios/chrome/share_extension/ui_util.h" |
| 9 | 9 |
| 10 #if !defined(__has_feature) || !__has_feature(objc_arc) | 10 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 else | 44 else |
| 45 self.backgroundColor = [UIColor clearColor]; | 45 self.backgroundColor = [UIColor clearColor]; |
| 46 } | 46 } |
| 47 | 47 |
| 48 @end | 48 @end |
| 49 | 49 |
| 50 #pragma mark - Share Extension View | 50 #pragma mark - Share Extension View |
| 51 | 51 |
| 52 @interface ShareExtensionView () { | 52 @interface ShareExtensionView () { |
| 53 __weak id<ShareExtensionViewActionTarget> _target; | 53 __weak id<ShareExtensionViewActionTarget> _target; |
| 54 |
| 55 // Track if a button has been pressed. All button pressing will have no effect |
| 56 // if |_dismissed| is YES. |
| 57 BOOL _dismissed; |
| 54 } | 58 } |
| 55 | 59 |
| 56 // Keep strong references of the views that need to be updated. | 60 // Keep strong references of the views that need to be updated. |
| 57 @property(nonatomic, strong) UILabel* titleLabel; | 61 @property(nonatomic, strong) UILabel* titleLabel; |
| 58 @property(nonatomic, strong) UILabel* URLLabel; | 62 @property(nonatomic, strong) UILabel* URLLabel; |
| 63 @property(nonatomic, strong) UIButton* readingListButton; |
| 59 @property(nonatomic, strong) UIImageView* screenshotView; | 64 @property(nonatomic, strong) UIImageView* screenshotView; |
| 60 @property(nonatomic, strong) UIStackView* itemStack; | 65 @property(nonatomic, strong) UIStackView* itemStack; |
| 61 | 66 |
| 62 // View creation helpers. | 67 // View creation helpers. |
| 63 // Returns a view containing the shared items (title, URL, screenshot). This | 68 // Returns a view containing the shared items (title, URL, screenshot). This |
| 64 // method will set the ivars. | 69 // method will set the ivars. |
| 65 - (UIView*)sharedItemView; | 70 - (UIView*)sharedItemView; |
| 66 | 71 |
| 67 // Returns a button containing the with title |title| and action |selector| on | 72 // Returns a button containing the with title |title| and action |selector| on |
| 68 // |_target|. | 73 // |_target|. |
| 69 - (UIButton*)buttonWithTitle:(NSString*)title selector:(SEL)selector; | 74 - (UIButton*)buttonWithTitle:(NSString*)title selector:(SEL)selector; |
| 70 | 75 |
| 71 // Returns a view containing a divider with vibrancy effect. | 76 // Returns a view containing a divider with vibrancy effect. |
| 72 - (UIView*)dividerViewWithVibrancy:(UIVisualEffect*)vibrancyEffect; | 77 - (UIView*)dividerViewWithVibrancy:(UIVisualEffect*)vibrancyEffect; |
| 73 | 78 |
| 74 // Returns a navigationBar. | 79 // Returns a navigationBar. |
| 75 - (UINavigationBar*)navigationBar; | 80 - (UINavigationBar*)navigationBar; |
| 76 | 81 |
| 82 // Called when "Read Later" button has been pressed. |
| 83 - (void)addToReadingListPressed:(UIButton*)sender; |
| 84 |
| 85 // Called when "Add to bookmarks" button has been pressed. |
| 86 - (void)addToBookmarksPressed:(UIButton*)sender; |
| 87 |
| 88 // Called when "Cancel" button has been pressed. |
| 89 - (void)cancelPressed:(UIButton*)sender; |
| 90 |
| 91 // Animates the button |sender| by replaceing its string to "Added", then call |
| 92 // completion. |
| 93 - (void)animateButtonPressed:(UIButton*)sender |
| 94 withCompletion:(void (^)(void))completion; |
| 95 |
| 77 @end | 96 @end |
| 78 | 97 |
| 79 @implementation ShareExtensionView | 98 @implementation ShareExtensionView |
| 80 | 99 |
| 81 @synthesize titleLabel = _titleLabel; | 100 @synthesize titleLabel = _titleLabel; |
| 82 @synthesize URLLabel = _URLLabel; | 101 @synthesize URLLabel = _URLLabel; |
| 102 @synthesize readingListButton = _readingListButton; |
| 83 @synthesize screenshotView = _screenshotView; | 103 @synthesize screenshotView = _screenshotView; |
| 84 @synthesize itemStack = _itemStack; | 104 @synthesize itemStack = _itemStack; |
| 85 | 105 |
| 86 #pragma mark - Lifecycle | 106 #pragma mark - Lifecycle |
| 87 | 107 |
| 88 - (instancetype)initWithActionTarget: | 108 - (instancetype)initWithActionTarget: |
| 89 (id<ShareExtensionViewActionTarget>)target { | 109 (id<ShareExtensionViewActionTarget>)target { |
| 90 self = [super initWithFrame:CGRectZero]; | 110 self = [super initWithFrame:CGRectZero]; |
| 91 if (self) { | 111 if (self) { |
| 92 DCHECK(target); | 112 DCHECK(target); |
| 93 _target = target; | 113 _target = target; |
| 114 _dismissed = NO; |
| 94 | 115 |
| 95 [self.layer setCornerRadius:kCornerRadius]; | 116 [self.layer setCornerRadius:kCornerRadius]; |
| 96 [self setClipsToBounds:YES]; | 117 [self setClipsToBounds:YES]; |
| 97 UIBlurEffect* blurEffect = | 118 UIBlurEffect* blurEffect = |
| 98 [UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight]; | 119 [UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight]; |
| 99 UIVibrancyEffect* vibrancyEffect = | 120 UIVibrancyEffect* vibrancyEffect = |
| 100 [UIVibrancyEffect effectForBlurEffect:blurEffect]; | 121 [UIVibrancyEffect effectForBlurEffect:blurEffect]; |
| 101 | 122 |
| 102 self.backgroundColor = [UIColor colorWithWhite:242.0f / 255.0f alpha:1]; | 123 self.backgroundColor = [UIColor colorWithWhite:242.0f / 255.0f alpha:1]; |
| 103 | 124 |
| 104 // Add the blur effect to the whole widget. | 125 // Add the blur effect to the whole widget. |
| 105 UIVisualEffectView* blurringView = | 126 UIVisualEffectView* blurringView = |
| 106 [[UIVisualEffectView alloc] initWithEffect:blurEffect]; | 127 [[UIVisualEffectView alloc] initWithEffect:blurEffect]; |
| 107 [self addSubview:blurringView]; | 128 [self addSubview:blurringView]; |
| 108 ui_util::ConstrainAllSidesOfViewToView(self, blurringView); | 129 ui_util::ConstrainAllSidesOfViewToView(self, blurringView); |
| 109 [[blurringView layer] setCornerRadius:kCornerRadius]; | 130 [[blurringView layer] setCornerRadius:kCornerRadius]; |
| 110 [blurringView setClipsToBounds:YES]; | 131 [blurringView setClipsToBounds:YES]; |
| 111 | 132 |
| 112 NSString* addToReadingListTitle = NSLocalizedString( | 133 NSString* addToReadingListTitle = NSLocalizedString( |
| 113 @"IDS_IOS_ADD_READING_LIST_SHARE_EXTENSION", | 134 @"IDS_IOS_ADD_READING_LIST_SHARE_EXTENSION", |
| 114 @"The add to reading list button text in share extension."); | 135 @"The add to reading list button text in share extension."); |
| 115 UIButton* readingListButton = [self | 136 self.readingListButton = |
| 116 buttonWithTitle:addToReadingListTitle | 137 [self buttonWithTitle:addToReadingListTitle |
| 117 selector:@selector( | 138 selector:@selector(addToReadingListPressed:)]; |
| 118 shareExtensionViewDidSelectAddToReadingList:)]; | |
| 119 | 139 |
| 120 NSString* addToBookmarksTitle = NSLocalizedString( | 140 NSString* addToBookmarksTitle = NSLocalizedString( |
| 121 @"IDS_IOS_ADD_BOOKMARKS_SHARE_EXTENSION", | 141 @"IDS_IOS_ADD_BOOKMARKS_SHARE_EXTENSION", |
| 122 @"The Add to bookmarks button text in share extension."); | 142 @"The Add to bookmarks button text in share extension."); |
| 123 UIButton* bookmarksButton = [self | 143 UIButton* bookmarksButton = |
| 124 buttonWithTitle:addToBookmarksTitle | 144 [self buttonWithTitle:addToBookmarksTitle |
| 125 selector:@selector(shareExtensionViewDidSelectAddToBookmarks:)]; | 145 selector:@selector(addToBookmarksPressed:)]; |
| 126 | 146 |
| 127 UIStackView* contentStack = [[UIStackView alloc] initWithArrangedSubviews:@[ | 147 UIStackView* contentStack = [[UIStackView alloc] initWithArrangedSubviews:@[ |
| 128 [self navigationBar], [self dividerViewWithVibrancy:vibrancyEffect], | 148 [self navigationBar], [self dividerViewWithVibrancy:vibrancyEffect], |
| 129 [self sharedItemView], [self dividerViewWithVibrancy:vibrancyEffect], | 149 [self sharedItemView], [self dividerViewWithVibrancy:vibrancyEffect], |
| 130 readingListButton, [self dividerViewWithVibrancy:vibrancyEffect], | 150 self.readingListButton, [self dividerViewWithVibrancy:vibrancyEffect], |
| 131 bookmarksButton | 151 bookmarksButton |
| 132 ]]; | 152 ]]; |
| 133 [contentStack setAxis:UILayoutConstraintAxisVertical]; | 153 [contentStack setAxis:UILayoutConstraintAxisVertical]; |
| 134 [[blurringView contentView] addSubview:contentStack]; | 154 [[blurringView contentView] addSubview:contentStack]; |
| 135 | 155 |
| 136 [blurringView setTranslatesAutoresizingMaskIntoConstraints:NO]; | 156 [blurringView setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 137 [contentStack setTranslatesAutoresizingMaskIntoConstraints:NO]; | 157 [contentStack setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 138 | 158 |
| 139 ui_util::ConstrainAllSidesOfViewToView([blurringView contentView], | 159 ui_util::ConstrainAllSidesOfViewToView([blurringView contentView], |
| 140 contentStack); | 160 contentStack); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 | 269 |
| 250 - (UIButton*)buttonWithTitle:(NSString*)title selector:(SEL)selector { | 270 - (UIButton*)buttonWithTitle:(NSString*)title selector:(SEL)selector { |
| 251 UIButton* systemButton = [UIButton buttonWithType:UIButtonTypeSystem]; | 271 UIButton* systemButton = [UIButton buttonWithType:UIButtonTypeSystem]; |
| 252 UIColor* systemColor = [systemButton titleColorForState:UIControlStateNormal]; | 272 UIColor* systemColor = [systemButton titleColorForState:UIControlStateNormal]; |
| 253 | 273 |
| 254 UIButton* button = [[ShareExtensionButton alloc] initWithFrame:CGRectZero]; | 274 UIButton* button = [[ShareExtensionButton alloc] initWithFrame:CGRectZero]; |
| 255 [button setTitle:title forState:UIControlStateNormal]; | 275 [button setTitle:title forState:UIControlStateNormal]; |
| 256 [button setTitleColor:systemColor forState:UIControlStateNormal]; | 276 [button setTitleColor:systemColor forState:UIControlStateNormal]; |
| 257 [[button titleLabel] setFont:[UIFont systemFontOfSize:kButtonFontSize]]; | 277 [[button titleLabel] setFont:[UIFont systemFontOfSize:kButtonFontSize]]; |
| 258 [button setTranslatesAutoresizingMaskIntoConstraints:NO]; | 278 [button setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 259 [button addTarget:_target | 279 [button addTarget:self |
| 260 action:selector | 280 action:selector |
| 261 forControlEvents:UIControlEventTouchUpInside]; | 281 forControlEvents:UIControlEventTouchUpInside]; |
| 262 [button.heightAnchor constraintEqualToConstant:kButtonHeight].active = YES; | 282 [button.heightAnchor constraintEqualToConstant:kButtonHeight].active = YES; |
| 263 return button; | 283 return button; |
| 264 } | 284 } |
| 265 | 285 |
| 266 - (UINavigationBar*)navigationBar { | 286 - (UINavigationBar*)navigationBar { |
| 267 // Create the navigation bar. | 287 // Create the navigation bar. |
| 268 UINavigationBar* navigationBar = | 288 UINavigationBar* navigationBar = |
| 269 [[UINavigationBar alloc] initWithFrame:CGRectZero]; | 289 [[UINavigationBar alloc] initWithFrame:CGRectZero]; |
| 270 [[navigationBar layer] setCornerRadius:kCornerRadius]; | 290 [[navigationBar layer] setCornerRadius:kCornerRadius]; |
| 271 [navigationBar setClipsToBounds:YES]; | 291 [navigationBar setClipsToBounds:YES]; |
| 272 | 292 |
| 273 // Create an empty image to replace the standard gray background of the | 293 // Create an empty image to replace the standard gray background of the |
| 274 // UINavigationBar. | 294 // UINavigationBar. |
| 275 UIImage* emptyImage = [[UIImage alloc] init]; | 295 UIImage* emptyImage = [[UIImage alloc] init]; |
| 276 [navigationBar setBackgroundImage:emptyImage | 296 [navigationBar setBackgroundImage:emptyImage |
| 277 forBarMetrics:UIBarMetricsDefault]; | 297 forBarMetrics:UIBarMetricsDefault]; |
| 278 [navigationBar setShadowImage:emptyImage]; | 298 [navigationBar setShadowImage:emptyImage]; |
| 279 [navigationBar setTranslucent:YES]; | 299 [navigationBar setTranslucent:YES]; |
| 280 [navigationBar setTranslatesAutoresizingMaskIntoConstraints:NO]; | 300 [navigationBar setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 281 | 301 |
| 282 UIBarButtonItem* cancelButton = [[UIBarButtonItem alloc] | 302 UIBarButtonItem* cancelButton = [[UIBarButtonItem alloc] |
| 283 initWithBarButtonSystemItem:UIBarButtonSystemItemCancel | 303 initWithBarButtonSystemItem:UIBarButtonSystemItemCancel |
| 284 target:_target | 304 target:self |
| 285 action:@selector( | 305 action:@selector(cancelPressed:)]; |
| 286 shareExtensionViewDidSelectCancel:)]; | |
| 287 | 306 |
| 288 NSString* appName = | 307 NSString* appName = |
| 289 [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]; | 308 [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]; |
| 290 UINavigationItem* titleItem = | 309 UINavigationItem* titleItem = |
| 291 [[UINavigationItem alloc] initWithTitle:appName]; | 310 [[UINavigationItem alloc] initWithTitle:appName]; |
| 292 [titleItem setLeftBarButtonItem:cancelButton]; | 311 [titleItem setLeftBarButtonItem:cancelButton]; |
| 293 [titleItem setHidesBackButton:YES]; | 312 [titleItem setHidesBackButton:YES]; |
| 294 [navigationBar pushNavigationItem:titleItem animated:NO]; | 313 [navigationBar pushNavigationItem:titleItem animated:NO]; |
| 295 return navigationBar; | 314 return navigationBar; |
| 296 } | 315 } |
| 297 | 316 |
| 317 - (void)addToReadingListPressed:(UIButton*)sender { |
| 318 if (_dismissed) { |
| 319 return; |
| 320 } |
| 321 _dismissed = YES; |
| 322 [self animateButtonPressed:sender |
| 323 withCompletion:^{ |
| 324 [_target shareExtensionViewDidSelectAddToReadingList:sender]; |
| 325 }]; |
| 326 } |
| 327 |
| 328 - (void)addToBookmarksPressed:(UIButton*)sender { |
| 329 if (_dismissed) { |
| 330 return; |
| 331 } |
| 332 _dismissed = YES; |
| 333 [self animateButtonPressed:sender |
| 334 withCompletion:^{ |
| 335 [_target shareExtensionViewDidSelectAddToBookmarks:sender]; |
| 336 }]; |
| 337 } |
| 338 |
| 339 - (void)animateButtonPressed:(UIButton*)sender |
| 340 withCompletion:(void (^)(void))completion { |
| 341 NSString* addedString = |
| 342 NSLocalizedString(@"IDS_IOS_ADDED_ITEM_SHARE_EXTENSION", |
| 343 @"Button label after being pressed."); |
| 344 NSString* addedCheckedString = |
| 345 [addedString stringByAppendingString:@" \u2713"]; |
| 346 // Create a label with the same style as the split animation between the text |
| 347 // and the checkmark. |
| 348 UILabel* addedLabel = [[UILabel alloc] initWithFrame:CGRectZero]; |
| 349 [addedLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| 350 [addedLabel setText:addedString]; |
| 351 [self addSubview:addedLabel]; |
| 352 [addedLabel setFont:[sender titleLabel].font]; |
| 353 [addedLabel setTextColor:[sender titleColorForState:UIControlStateNormal]]; |
| 354 [addedLabel.leadingAnchor |
| 355 constraintEqualToAnchor:[sender titleLabel].leadingAnchor] |
| 356 .active = YES; |
| 357 [addedLabel.centerYAnchor |
| 358 constraintEqualToAnchor:[sender titleLabel].centerYAnchor] |
| 359 .active = YES; |
| 360 [addedLabel setAlpha:0]; |
| 361 |
| 362 void (^step3ShowCheck)() = ^{ |
| 363 [UIView animateWithDuration:ui_util::kAnimationDuration |
| 364 animations:^{ |
| 365 [addedLabel setAlpha:0]; |
| 366 [sender setAlpha:1]; |
| 367 } |
| 368 completion:^(BOOL finished) { |
| 369 if (completion) { |
| 370 completion(); |
| 371 } |
| 372 }]; |
| 373 }; |
| 374 |
| 375 void (^step2ShowTextWithoutCheck)() = ^{ |
| 376 [sender setTitle:addedCheckedString forState:UIControlStateNormal]; |
| 377 [UIView animateWithDuration:ui_util::kAnimationDuration |
| 378 animations:^{ |
| 379 [addedLabel setAlpha:1]; |
| 380 } |
| 381 completion:^(BOOL finished) { |
| 382 step3ShowCheck(); |
| 383 }]; |
| 384 }; |
| 385 |
| 386 void (^step1HideText)() = ^{ |
| 387 [UIView animateWithDuration:ui_util::kAnimationDuration |
| 388 animations:^{ |
| 389 [sender setAlpha:0]; |
| 390 } |
| 391 completion:^(BOOL finished) { |
| 392 step2ShowTextWithoutCheck(); |
| 393 }]; |
| 394 }; |
| 395 step1HideText(); |
| 396 } |
| 397 |
| 398 - (void)cancelPressed:(UIButton*)sender { |
| 399 if (_dismissed) { |
| 400 return; |
| 401 } |
| 402 _dismissed = YES; |
| 403 [_target shareExtensionViewDidSelectCancel:sender]; |
| 404 } |
| 405 |
| 298 #pragma mark - Content getters and setters. | 406 #pragma mark - Content getters and setters. |
| 299 | 407 |
| 300 - (void)setURL:(NSURL*)URL { | 408 - (void)setURL:(NSURL*)URL { |
| 301 [[self URLLabel] setText:[URL absoluteString]]; | 409 [[self URLLabel] setText:[URL absoluteString]]; |
| 302 } | 410 } |
| 303 | 411 |
| 304 - (void)setTitle:(NSString*)title { | 412 - (void)setTitle:(NSString*)title { |
| 305 [[self titleLabel] setText:title]; | 413 [[self titleLabel] setText:title]; |
| 306 } | 414 } |
| 307 | 415 |
| 308 - (void)setScreenshot:(UIImage*)screenshot { | 416 - (void)setScreenshot:(UIImage*)screenshot { |
| 309 [[self screenshotView] setHidden:NO]; | 417 [[self screenshotView] setHidden:NO]; |
| 310 [[self screenshotView] setImage:screenshot]; | 418 [[self screenshotView] setImage:screenshot]; |
| 311 [[self itemStack] addArrangedSubview:[self screenshotView]]; | 419 [[self itemStack] addArrangedSubview:[self screenshotView]]; |
| 312 } | 420 } |
| 313 | 421 |
| 314 @end | 422 @end |
| OLD | NEW |