Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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/browser/ui/content_suggestions/cells/content_suggestions_art icle_item.h" | 5 #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_art icle_item.h" |
| 6 | 6 |
| 7 #include "base/time/time.h" | 7 #include "base/time/time.h" |
| 8 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" | 8 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" |
| 9 #import "ios/chrome/browser/ui/favicon/favicon_attributes.h" | |
| 10 #import "ios/chrome/browser/ui/favicon/favicon_view.h" | |
| 9 #import "ios/chrome/browser/ui/uikit_ui_util.h" | 11 #import "ios/chrome/browser/ui/uikit_ui_util.h" |
| 10 #import "ios/chrome/browser/ui/util/i18n_string.h" | 12 #import "ios/chrome/browser/ui/util/i18n_string.h" |
| 11 #import "ios/third_party/material_components_ios/src/components/Palettes/src/Mat erialPalettes.h" | 13 #import "ios/third_party/material_components_ios/src/components/Palettes/src/Mat erialPalettes.h" |
| 12 #import "ios/third_party/material_components_ios/src/components/Typography/src/M aterialTypography.h" | 14 #import "ios/third_party/material_components_ios/src/components/Typography/src/M aterialTypography.h" |
| 13 #include "url/gurl.h" | 15 #include "url/gurl.h" |
| 14 | 16 |
| 15 #if !defined(__has_feature) || !__has_feature(objc_arc) | 17 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 16 #error "This file requires ARC support." | 18 #error "This file requires ARC support." |
| 17 #endif | 19 #endif |
| 18 | 20 |
| 19 namespace { | 21 namespace { |
| 20 const CGFloat kImageSize = 72; | 22 const CGFloat kImageSize = 72; |
| 21 // When updating this, make sure to update |layoutSubviews|. | 23 // When updating this, make sure to update |layoutSubviews|. |
|
lpromero
2017/03/29 14:33:01
Why? Here and below.
gambard
2017/03/29 16:25:14
Because it is the spacing between the labels and t
lpromero
2017/03/29 16:35:47
I don't get why this comment is here.
gambard
2017/03/30 06:52:24
Well... Yes, the comment does not make sense as is
| |
| 22 const CGFloat kStandardSpacing = 16; | 24 const CGFloat kStandardSpacing = 16; |
| 25 // When updating this, make sure to update |layoutSubviews|. | |
|
Olivier
2017/03/29 14:38:24
why?
gambard
2017/03/29 16:25:14
Because it is the spacing between the labels and t
| |
| 26 const CGFloat kSmallSpacing = 8; | |
| 27 // Size of the favicon view. | |
| 28 const CGFloat kFaviconSize = 16; | |
| 23 // Size of the icon displayed when there is not image. | 29 // Size of the icon displayed when there is not image. |
| 24 const CGFloat kIconSize = 24; | 30 const CGFloat kIconSize = 24; |
| 25 // Name of the icon displayed when there is not image. | 31 // Name of the icon displayed when there is not image. |
| 26 NSString* const kNoImageIconName = @"content_suggestions_no_image"; | 32 NSString* const kNoImageIconName = @"content_suggestions_no_image"; |
| 27 // No image icon percentage of white. | 33 // No image icon percentage of white. |
| 28 const CGFloat kNoImageIconWhite = 0.38; | 34 const CGFloat kNoImageIconWhite = 0.38; |
| 29 // No image background percentage of white. | 35 // No image background percentage of white. |
| 30 const CGFloat kNoImageBackgroundWhite = 0.95; | 36 const CGFloat kNoImageBackgroundWhite = 0.95; |
| 31 // Duration of the animation to display the image for the article. | 37 // Duration of the animation to display the image for the article. |
| 32 const CGFloat kAnimationDuration = 0.3; | 38 const CGFloat kAnimationDuration = 0.3; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 48 | 54 |
| 49 @synthesize title = _title; | 55 @synthesize title = _title; |
| 50 @synthesize subtitle = _subtitle; | 56 @synthesize subtitle = _subtitle; |
| 51 @synthesize image = _image; | 57 @synthesize image = _image; |
| 52 @synthesize articleURL = _articleURL; | 58 @synthesize articleURL = _articleURL; |
| 53 @synthesize publisher = _publisher; | 59 @synthesize publisher = _publisher; |
| 54 @synthesize publishDate = _publishDate; | 60 @synthesize publishDate = _publishDate; |
| 55 @synthesize suggestionIdentifier = _suggestionIdentifier; | 61 @synthesize suggestionIdentifier = _suggestionIdentifier; |
| 56 @synthesize delegate = _delegate; | 62 @synthesize delegate = _delegate; |
| 57 @synthesize imageFetched = _imageFetched; | 63 @synthesize imageFetched = _imageFetched; |
| 64 @synthesize attributes = _attributes; | |
| 58 | 65 |
| 59 - (instancetype)initWithType:(NSInteger)type | 66 - (instancetype)initWithType:(NSInteger)type |
| 60 title:(NSString*)title | 67 title:(NSString*)title |
| 61 subtitle:(NSString*)subtitle | 68 subtitle:(NSString*)subtitle |
| 62 delegate:(id<ContentSuggestionsArticleItemDelegate>)delegate | 69 delegate:(id<ContentSuggestionsArticleItemDelegate>)delegate |
| 63 url:(const GURL&)url { | 70 url:(const GURL&)url { |
| 64 self = [super initWithType:type]; | 71 self = [super initWithType:type]; |
| 65 if (self) { | 72 if (self) { |
| 66 self.cellClass = [ContentSuggestionsArticleCell class]; | 73 self.cellClass = [ContentSuggestionsArticleCell class]; |
| 67 _title = [title copy]; | 74 _title = [title copy]; |
| 68 _subtitle = [subtitle copy]; | 75 _subtitle = [subtitle copy]; |
| 69 _articleURL = url; | 76 _articleURL = url; |
| 70 _delegate = delegate; | 77 _delegate = delegate; |
| 71 } | 78 } |
| 72 return self; | 79 return self; |
| 73 } | 80 } |
| 74 | 81 |
| 75 - (void)configureCell:(ContentSuggestionsArticleCell*)cell { | 82 - (void)configureCell:(ContentSuggestionsArticleCell*)cell { |
| 76 [super configureCell:cell]; | 83 [super configureCell:cell]; |
| 77 if (!self.imageFetched) { | 84 if (!self.imageFetched) { |
| 78 self.imageFetched = YES; | 85 self.imageFetched = YES; |
| 79 // Fetch the image. During the fetch the cell's image should still be set. | 86 // Fetch the image. During the fetch the cell's image should still be set. |
| 80 [self.delegate loadImageForArticleItem:self]; | 87 [self.delegate loadImageForArticleItem:self]; |
| 81 } | 88 } |
| 89 if (self.attributes) | |
|
lpromero
2017/03/29 14:33:01
If there are no attributes, the favicon view is no
gambard
2017/03/29 16:25:13
In theory yes. But the call to self.attributes = .
| |
| 90 [cell.faviconView configureWithAttributes:self.attributes]; | |
| 82 cell.titleLabel.text = self.title; | 91 cell.titleLabel.text = self.title; |
| 83 cell.subtitleLabel.text = self.subtitle; | 92 cell.subtitleLabel.text = self.subtitle; |
| 84 [cell setContentImage:self.image]; | 93 [cell setContentImage:self.image]; |
| 85 [cell setPublisherName:self.publisher date:self.publishDate]; | 94 [cell setPublisherName:self.publisher date:self.publishDate]; |
| 86 } | 95 } |
| 87 | 96 |
| 88 @end | 97 @end |
| 89 | 98 |
| 90 #pragma mark - ContentSuggestionsArticleCell | 99 #pragma mark - ContentSuggestionsArticleCell |
| 91 | 100 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 107 @end | 116 @end |
| 108 | 117 |
| 109 @implementation ContentSuggestionsArticleCell | 118 @implementation ContentSuggestionsArticleCell |
| 110 | 119 |
| 111 @synthesize titleLabel = _titleLabel; | 120 @synthesize titleLabel = _titleLabel; |
| 112 @synthesize subtitleLabel = _subtitleLabel; | 121 @synthesize subtitleLabel = _subtitleLabel; |
| 113 @synthesize imageContainer = _imageContainer; | 122 @synthesize imageContainer = _imageContainer; |
| 114 @synthesize noImageIcon = _noImageIcon; | 123 @synthesize noImageIcon = _noImageIcon; |
| 115 @synthesize publisherLabel = _publisherLabel; | 124 @synthesize publisherLabel = _publisherLabel; |
| 116 @synthesize contentImageView = _contentImageView; | 125 @synthesize contentImageView = _contentImageView; |
| 126 @synthesize faviconView = _faviconView; | |
| 117 | 127 |
| 118 - (instancetype)initWithFrame:(CGRect)frame { | 128 - (instancetype)initWithFrame:(CGRect)frame { |
| 119 self = [super initWithFrame:frame]; | 129 self = [super initWithFrame:frame]; |
| 120 if (self) { | 130 if (self) { |
| 121 _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; | 131 _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; |
| 122 _subtitleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; | 132 _subtitleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; |
| 123 _imageContainer = [[UIView alloc] initWithFrame:CGRectZero]; | 133 _imageContainer = [[UIView alloc] initWithFrame:CGRectZero]; |
| 124 _noImageIcon = [[UIImageView alloc] initWithFrame:CGRectZero]; | 134 _noImageIcon = [[UIImageView alloc] initWithFrame:CGRectZero]; |
| 125 _publisherLabel = [[UILabel alloc] initWithFrame:CGRectZero]; | 135 _publisherLabel = [[UILabel alloc] initWithFrame:CGRectZero]; |
| 136 _faviconView = [[FaviconViewNew alloc] init]; | |
| 126 | 137 |
| 127 _titleLabel.numberOfLines = 2; | 138 _titleLabel.numberOfLines = 2; |
| 128 _subtitleLabel.numberOfLines = 2; | 139 _subtitleLabel.numberOfLines = 2; |
| 129 [_subtitleLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh | 140 [_subtitleLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh |
| 130 forAxis:UILayoutConstraintAxisVertical]; | 141 forAxis:UILayoutConstraintAxisVertical]; |
| 131 [_titleLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh | 142 [_titleLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh |
| 132 forAxis:UILayoutConstraintAxisVertical]; | 143 forAxis:UILayoutConstraintAxisVertical]; |
| 133 | 144 |
| 134 _imageContainer.translatesAutoresizingMaskIntoConstraints = NO; | 145 _imageContainer.translatesAutoresizingMaskIntoConstraints = NO; |
| 135 _noImageIcon.translatesAutoresizingMaskIntoConstraints = NO; | 146 _noImageIcon.translatesAutoresizingMaskIntoConstraints = NO; |
| 136 _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; | 147 _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; |
| 137 _subtitleLabel.translatesAutoresizingMaskIntoConstraints = NO; | 148 _subtitleLabel.translatesAutoresizingMaskIntoConstraints = NO; |
| 138 _publisherLabel.translatesAutoresizingMaskIntoConstraints = NO; | 149 _publisherLabel.translatesAutoresizingMaskIntoConstraints = NO; |
| 150 _faviconView.translatesAutoresizingMaskIntoConstraints = NO; | |
| 139 | 151 |
| 140 [self.contentView addSubview:_imageContainer]; | 152 [self.contentView addSubview:_imageContainer]; |
| 141 [self.contentView addSubview:_titleLabel]; | 153 [self.contentView addSubview:_titleLabel]; |
| 142 [self.contentView addSubview:_subtitleLabel]; | 154 [self.contentView addSubview:_subtitleLabel]; |
| 143 [self.contentView addSubview:_publisherLabel]; | 155 [self.contentView addSubview:_publisherLabel]; |
| 156 [self.contentView addSubview:_faviconView]; | |
| 144 | 157 |
| 145 [_imageContainer addSubview:_noImageIcon]; | 158 [_imageContainer addSubview:_noImageIcon]; |
| 146 | 159 |
| 147 _imageContainer.backgroundColor = | 160 _imageContainer.backgroundColor = |
| 148 [UIColor colorWithWhite:kNoImageBackgroundWhite alpha:1]; | 161 [UIColor colorWithWhite:kNoImageBackgroundWhite alpha:1]; |
| 149 _noImageIcon.image = [[UIImage imageNamed:kNoImageIconName] | 162 _noImageIcon.image = [[UIImage imageNamed:kNoImageIconName] |
| 150 imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; | 163 imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; |
| 151 [_noImageIcon | 164 [_noImageIcon |
| 152 setTintColor:[UIColor colorWithWhite:kNoImageIconWhite alpha:1]]; | 165 setTintColor:[UIColor colorWithWhite:kNoImageIconWhite alpha:1]]; |
| 153 | 166 |
| 154 _titleLabel.font = [MDCTypography subheadFont]; | 167 _titleLabel.font = [MDCTypography subheadFont]; |
| 155 _subtitleLabel.font = [MDCTypography body1Font]; | 168 _subtitleLabel.font = [MDCTypography body1Font]; |
| 156 _publisherLabel.font = [MDCTypography captionFont]; | 169 _publisherLabel.font = [MDCTypography captionFont]; |
| 170 _faviconView.font = | |
| 171 [[MDCTypography fontLoader] regularFontOfSize:kFaviconSize / 2]; | |
| 157 | 172 |
| 158 _subtitleLabel.textColor = [[MDCPalette greyPalette] tint700]; | 173 _subtitleLabel.textColor = [[MDCPalette greyPalette] tint700]; |
| 159 _publisherLabel.textColor = [[MDCPalette greyPalette] tint700]; | 174 _publisherLabel.textColor = [[MDCPalette greyPalette] tint700]; |
| 160 | 175 |
| 161 [self applyConstraints]; | 176 [self applyConstraints]; |
| 162 } | 177 } |
| 163 return self; | 178 return self; |
| 164 } | 179 } |
| 165 | 180 |
| 166 - (void)setContentImage:(UIImage*)image { | 181 - (void)setContentImage:(UIImage*)image { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 219 } | 234 } |
| 220 | 235 |
| 221 #pragma mark - Private | 236 #pragma mark - Private |
| 222 | 237 |
| 223 - (void)applyConstraints { | 238 - (void)applyConstraints { |
| 224 [NSLayoutConstraint activateConstraints:@[ | 239 [NSLayoutConstraint activateConstraints:@[ |
| 225 [_imageContainer.widthAnchor constraintEqualToConstant:kImageSize], | 240 [_imageContainer.widthAnchor constraintEqualToConstant:kImageSize], |
| 226 [_imageContainer.heightAnchor | 241 [_imageContainer.heightAnchor |
| 227 constraintEqualToAnchor:_imageContainer.widthAnchor], | 242 constraintEqualToAnchor:_imageContainer.widthAnchor], |
| 228 [_imageContainer.topAnchor constraintEqualToAnchor:_titleLabel.topAnchor], | 243 [_imageContainer.topAnchor constraintEqualToAnchor:_titleLabel.topAnchor], |
| 244 | |
| 245 // Publisher. | |
| 229 [_publisherLabel.topAnchor | 246 [_publisherLabel.topAnchor |
| 230 constraintGreaterThanOrEqualToAnchor:_imageContainer.bottomAnchor | 247 constraintGreaterThanOrEqualToAnchor:_imageContainer.bottomAnchor |
| 231 constant:kStandardSpacing], | 248 constant:kStandardSpacing], |
| 232 [_publisherLabel.topAnchor | 249 [_publisherLabel.topAnchor |
| 233 constraintGreaterThanOrEqualToAnchor:_subtitleLabel.bottomAnchor | 250 constraintGreaterThanOrEqualToAnchor:_subtitleLabel.bottomAnchor |
| 234 constant:kStandardSpacing], | 251 constant:kStandardSpacing], |
| 252 [_publisherLabel.bottomAnchor | |
| 253 constraintLessThanOrEqualToAnchor:self.contentView.bottomAnchor | |
| 254 constant:-kStandardSpacing], | |
| 255 | |
| 256 // Favicon. | |
| 257 [_faviconView.topAnchor | |
| 258 constraintGreaterThanOrEqualToAnchor:_imageContainer.bottomAnchor | |
| 259 constant:kStandardSpacing], | |
| 260 [_faviconView.topAnchor | |
| 261 constraintGreaterThanOrEqualToAnchor:_subtitleLabel.bottomAnchor | |
| 262 constant:kStandardSpacing], | |
| 263 [_faviconView.centerYAnchor | |
| 264 constraintEqualToAnchor:_publisherLabel.centerYAnchor], | |
| 265 [_faviconView.bottomAnchor | |
| 266 constraintLessThanOrEqualToAnchor:self.contentView.bottomAnchor | |
| 267 constant:-kStandardSpacing], | |
| 268 [_faviconView.heightAnchor constraintEqualToConstant:kFaviconSize], | |
|
Olivier
2017/03/29 14:38:24
If attributes is nil (supported), this view will s
gambard
2017/03/29 16:25:14
Yes. The callback should be quick enough. I plan t
| |
| 269 [_faviconView.widthAnchor | |
| 270 constraintEqualToAnchor:_faviconView.heightAnchor], | |
| 235 | 271 |
| 236 // No image icon. | 272 // No image icon. |
| 237 [_noImageIcon.centerXAnchor | 273 [_noImageIcon.centerXAnchor |
| 238 constraintEqualToAnchor:_imageContainer.centerXAnchor], | 274 constraintEqualToAnchor:_imageContainer.centerXAnchor], |
| 239 [_noImageIcon.centerYAnchor | 275 [_noImageIcon.centerYAnchor |
| 240 constraintEqualToAnchor:_imageContainer.centerYAnchor], | 276 constraintEqualToAnchor:_imageContainer.centerYAnchor], |
| 241 [_noImageIcon.widthAnchor constraintEqualToConstant:kIconSize], | 277 [_noImageIcon.widthAnchor constraintEqualToConstant:kIconSize], |
| 242 [_noImageIcon.heightAnchor constraintEqualToAnchor:_noImageIcon.widthAnchor] | 278 [_noImageIcon.heightAnchor constraintEqualToAnchor:_noImageIcon.widthAnchor] |
| 243 ]]; | 279 ]]; |
| 244 | 280 |
| 245 ApplyVisualConstraintsWithMetrics( | 281 ApplyVisualConstraintsWithMetrics( |
| 246 @[ | 282 @[ |
| 247 @"H:|-(space)-[title]-(space)-[image]-(space)-|", | 283 @"H:|-(space)-[title]-(space)-[image]-(space)-|", |
| 248 @"H:|-(space)-[text]-(space)-[image]", | 284 @"H:|-(space)-[text]-(space)-[image]", |
| 249 @"V:|-(space)-[title]-[text]", | 285 @"V:|-(space)-[title]-[text]", |
| 250 @"H:|-(space)-[publish]-(space)-|", | 286 @"H:|-(space)-[favicon]-(small)-[publish]-(space)-|", |
| 251 @"V:[publish]-|", | |
| 252 ], | 287 ], |
| 253 @{ | 288 @{ |
| 254 @"image" : _imageContainer, | 289 @"image" : _imageContainer, |
| 255 @"title" : _titleLabel, | 290 @"title" : _titleLabel, |
| 256 @"text" : _subtitleLabel, | 291 @"text" : _subtitleLabel, |
| 257 @"publish" : _publisherLabel, | 292 @"publish" : _publisherLabel, |
| 293 @"favicon" : _faviconView, | |
| 258 }, | 294 }, |
| 259 @{ @"space" : @(kStandardSpacing) }); | 295 @{ @"space" : @(kStandardSpacing), |
| 296 @"small" : @(kSmallSpacing) }); | |
| 260 } | 297 } |
| 261 | 298 |
| 262 @end | 299 @end |
| OLD | NEW |