Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Unified Diff: ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.mm

Issue 2865183003: Use the same design for all suggestions (Closed)
Patch Set: Address comments Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.mm
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_article_item.mm b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.mm
similarity index 60%
rename from ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_article_item.mm
rename to ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.mm
index 214804e36bf1643723933ca61fafa7799baead96..ffa77783fd2e258197fee48f4b17510300ee38d7 100644
--- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_article_item.mm
+++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.mm
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_article_item.h"
+#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_item.h"
#include "base/time/time.h"
#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
@@ -23,106 +23,129 @@ const CGFloat kImageSize = 72;
const CGFloat kStandardSpacing = 16;
const CGFloat kSmallSpacing = 8;
+// Name of the icon displayed when a suggestion is available offline.
+NSString* const kOfflineIconName = @"content_suggestions_offline";
+// Size of the icon displayed when a suggestion is available offline.
+const CGFloat kOfflineIconSize = 24;
+
// Size of the favicon view.
const CGFloat kFaviconSize = 16;
-// Size of the icon displayed when there is not image.
+// Size of the icon displayed when there is not image but one should be
+// displayed.
const CGFloat kIconSize = 24;
-// Name of the icon displayed when there is not image.
+// Name of the icon displayed when there is not image but one should be
+// displayed.
NSString* const kNoImageIconName = @"content_suggestions_no_image";
// No image icon percentage of white.
const CGFloat kNoImageIconWhite = 0.38;
// No image background percentage of white.
const CGFloat kNoImageBackgroundWhite = 0.95;
-// Duration of the animation to display the image for the article.
+// Duration of the animation to display the image.
const CGFloat kAnimationDuration = 0.3;
}
-@interface ContentSuggestionsArticleItem ()
+@interface ContentSuggestionsItem ()
@property(nonatomic, copy) NSString* subtitle;
// Used to check if the image has already been fetched. There is no way to
-// discriminate between failed image download and nonexitent image. The article
-// tries to download the image only once.
+// discriminate between failed image download and nonexitent image. The
+// suggestion tries to download the image only once.
@property(nonatomic, assign) BOOL imageFetched;
@end
-#pragma mark - ContentSuggestionsArticleItem
+#pragma mark - ContentSuggestionsItem
-@implementation ContentSuggestionsArticleItem
+@implementation ContentSuggestionsItem
@synthesize title = _title;
@synthesize subtitle = _subtitle;
@synthesize image = _image;
-@synthesize articleURL = _articleURL;
+@synthesize URL = _URL;
@synthesize publisher = _publisher;
@synthesize publishDate = _publishDate;
@synthesize suggestionIdentifier = _suggestionIdentifier;
@synthesize delegate = _delegate;
@synthesize imageFetched = _imageFetched;
@synthesize attributes = _attributes;
+@synthesize hasImage = _hasImage;
+@synthesize availableOffline = _availableOffline;
- (instancetype)initWithType:(NSInteger)type
title:(NSString*)title
subtitle:(NSString*)subtitle
- delegate:(id<ContentSuggestionsArticleItemDelegate>)delegate
+ delegate:(id<ContentSuggestionsItemDelegate>)delegate
url:(const GURL&)url {
self = [super initWithType:type];
if (self) {
- self.cellClass = [ContentSuggestionsArticleCell class];
+ self.cellClass = [ContentSuggestionsCell class];
_title = [title copy];
_subtitle = [subtitle copy];
- _articleURL = url;
+ _URL = url;
_delegate = delegate;
}
return self;
}
-- (void)configureCell:(ContentSuggestionsArticleCell*)cell {
+- (void)configureCell:(ContentSuggestionsCell*)cell {
[super configureCell:cell];
- if (!self.imageFetched) {
+ if (self.hasImage && !self.imageFetched) {
self.imageFetched = YES;
// Fetch the image. During the fetch the cell's image should still be set.
- [self.delegate loadImageForArticleItem:self];
+ [self.delegate loadImageForSuggestionItem:self];
}
- if (self.attributes)
- [cell.faviconView configureWithAttributes:self.attributes];
+ [cell.faviconView configureWithAttributes:self.attributes];
cell.titleLabel.text = self.title;
- cell.subtitleLabel.text = self.subtitle;
+ [cell setSubtitleText:self.subtitle];
+ cell.displayImage = self.hasImage;
[cell setContentImage:self.image];
- [cell setPublisherName:self.publisher date:self.publishDate];
+ [cell setAdditionalInformationWithPublisherName:self.publisher
+ date:self.publishDate
+ offlineAvailability:self.availableOffline];
}
@end
-#pragma mark - ContentSuggestionsArticleCell
+#pragma mark - ContentSuggestionsCell
-@interface ContentSuggestionsArticleCell ()
+@interface ContentSuggestionsCell ()
-@property(nonatomic, strong) UILabel* publisherLabel;
+@property(nonatomic, strong) UILabel* additionalInformationLabel;
// Contains the no-image icon or the image.
@property(nonatomic, strong) UIView* imageContainer;
// The no-image icon displayed when there is no image.
@property(nonatomic, strong) UIImageView* noImageIcon;
-// Displays the image associated with this article. It is added to the
+// Displays the image associated with this suggestion. It is added to the
// imageContainer only if there is an image to display, hiding the no-image
// icon.
@property(nonatomic, strong) UIImageView* contentImageView;
+// Constraint for the size of the image.
+@property(nonatomic, strong) NSLayoutConstraint* imageSize;
+// Constraint for the distance between the texts and the image.
+@property(nonatomic, strong) NSLayoutConstraint* imageTitleSpacing;
+// Constraint for the vertical distance between the title and the subtitle.
+@property(nonatomic, strong) NSLayoutConstraint* titleSubtitleSpacing;
+// Label for the subtitle.
+@property(nonatomic, readonly, strong) UILabel* subtitleLabel;
// Applies the constraints on the elements. Called in the init.
- (void)applyConstraints;
@end
-@implementation ContentSuggestionsArticleCell
+@implementation ContentSuggestionsCell
@synthesize titleLabel = _titleLabel;
@synthesize subtitleLabel = _subtitleLabel;
@synthesize imageContainer = _imageContainer;
@synthesize noImageIcon = _noImageIcon;
-@synthesize publisherLabel = _publisherLabel;
+@synthesize additionalInformationLabel = _additionalInformationLabel;
@synthesize contentImageView = _contentImageView;
@synthesize faviconView = _faviconView;
+@synthesize imageSize = _imageSize;
+@synthesize imageTitleSpacing = _imageTitleSpacing;
+@synthesize displayImage = _displayImage;
+@synthesize titleSubtitleSpacing = _titleSubtitleSpacing;
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
@@ -131,7 +154,7 @@ const CGFloat kAnimationDuration = 0.3;
_subtitleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
_imageContainer = [[UIView alloc] initWithFrame:CGRectZero];
_noImageIcon = [[UIImageView alloc] initWithFrame:CGRectZero];
- _publisherLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+ _additionalInformationLabel = [[UILabel alloc] initWithFrame:CGRectZero];
_contentImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
_faviconView = [[FaviconViewNew alloc] init];
@@ -150,14 +173,14 @@ const CGFloat kAnimationDuration = 0.3;
_noImageIcon.translatesAutoresizingMaskIntoConstraints = NO;
_titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
_subtitleLabel.translatesAutoresizingMaskIntoConstraints = NO;
- _publisherLabel.translatesAutoresizingMaskIntoConstraints = NO;
+ _additionalInformationLabel.translatesAutoresizingMaskIntoConstraints = NO;
_contentImageView.translatesAutoresizingMaskIntoConstraints = NO;
_faviconView.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:_imageContainer];
[self.contentView addSubview:_titleLabel];
[self.contentView addSubview:_subtitleLabel];
- [self.contentView addSubview:_publisherLabel];
+ [self.contentView addSubview:_additionalInformationLabel];
[self.contentView addSubview:_faviconView];
[_imageContainer addSubview:_noImageIcon];
@@ -172,11 +195,11 @@ const CGFloat kAnimationDuration = 0.3;
_titleLabel.font = [MDCTypography subheadFont];
_subtitleLabel.font = [MDCTypography body1Font];
- _publisherLabel.font = [MDCTypography captionFont];
+ _additionalInformationLabel.font = [MDCTypography captionFont];
_faviconView.font = [[MDCTypography fontLoader] mediumFontOfSize:10];
_subtitleLabel.textColor = [[MDCPalette greyPalette] tint700];
- _publisherLabel.textColor = [[MDCPalette greyPalette] tint700];
+ _additionalInformationLabel.textColor = [[MDCPalette greyPalette] tint700];
[self applyConstraints];
}
@@ -200,17 +223,62 @@ const CGFloat kAnimationDuration = 0.3;
}];
}
-- (void)setPublisherName:(NSString*)publisherName date:(base::Time)publishDate {
+- (void)setAdditionalInformationWithPublisherName:(NSString*)publisherName
+ date:(base::Time)publishDate
+ offlineAvailability:(BOOL)availableOffline {
NSDate* date = [NSDate dateWithTimeIntervalSince1970:publishDate.ToDoubleT()];
NSString* dateString =
[NSDateFormatter localizedStringFromDate:date
dateStyle:NSDateFormatterMediumStyle
timeStyle:NSDateFormatterNoStyle];
- self.publisherLabel.text = AdjustStringForLocaleDirection(
- [NSString stringWithFormat:@"%@ - %@.", publisherName, dateString]);
+ NSString* publisherString = AdjustStringForLocaleDirection(
+ [NSString stringWithFormat:@"%@ - %@ ", publisherName, dateString]);
+
+ NSMutableAttributedString* additionInformation =
+ [[NSMutableAttributedString alloc] initWithString:publisherString
+ attributes:nil];
+
+ if (availableOffline) {
+ NSTextAttachment* offlineIcon = [[NSTextAttachment alloc] init];
+ offlineIcon.image = [[UIImage imageNamed:kOfflineIconName]
+ imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+ offlineIcon.bounds = CGRectMake(
+ 0, (_additionalInformationLabel.font.xHeight - kOfflineIconSize) / 2,
+ kOfflineIconSize, kOfflineIconSize);
+
+ [additionInformation
+ appendAttributedString:[NSAttributedString
+ attributedStringWithAttachment:offlineIcon]];
+ }
+
+ self.additionalInformationLabel.attributedText = additionInformation;
+}
+
+- (void)setSubtitleText:(NSString*)subtitle {
+ self.subtitleLabel.text = subtitle;
+ if (subtitle.length > 0) {
+ self.titleSubtitleSpacing.constant = kSmallSpacing;
+ } else {
+ self.titleSubtitleSpacing.constant = 0;
+ }
}
+- (void)setDisplayImage:(BOOL)displayImage {
+ if (displayImage) {
+ self.imageTitleSpacing.constant = kStandardSpacing;
+ self.imageSize.constant = kImageSize;
+ self.imageContainer.hidden = NO;
+ } else {
+ self.imageTitleSpacing.constant = 0;
+ self.imageSize.constant = 0;
+ self.imageContainer.hidden = YES;
+ }
+ _displayImage = displayImage;
+}
+
+#pragma mark - UICollectionViewCell
+
- (void)prepareForReuse {
self.contentImageView.hidden = YES;
}
@@ -226,11 +294,16 @@ const CGFloat kAnimationDuration = 0.3;
// changes, for instance on screen rotation.
CGFloat parentWidth = CGRectGetWidth(self.contentView.bounds);
+ CGFloat offset = 0;
+ if (self.displayImage) {
+ offset = kImageSize + kStandardSpacing;
+ }
+
self.titleLabel.preferredMaxLayoutWidth =
- parentWidth - kImageSize - 3 * kStandardSpacing;
+ parentWidth - 2 * kStandardSpacing - offset;
self.subtitleLabel.preferredMaxLayoutWidth =
- parentWidth - kImageSize - 3 * kStandardSpacing;
- self.publisherLabel.preferredMaxLayoutWidth =
+ parentWidth - 2 * kStandardSpacing - offset;
+ self.additionalInformationLabel.preferredMaxLayoutWidth =
parentWidth - kFaviconSize - kSmallSpacing - 2 * kStandardSpacing;
// Re-layout with the new preferred width to allow the label to adjust its
@@ -241,20 +314,35 @@ const CGFloat kAnimationDuration = 0.3;
#pragma mark - Private
- (void)applyConstraints {
+ _imageSize =
+ [_imageContainer.heightAnchor constraintEqualToConstant:kImageSize];
+ _imageTitleSpacing = [_imageContainer.leadingAnchor
+ constraintEqualToAnchor:_titleLabel.trailingAnchor
+ constant:kStandardSpacing];
+ _titleSubtitleSpacing =
+ [_subtitleLabel.topAnchor constraintEqualToAnchor:_titleLabel.bottomAnchor
+ constant:kSmallSpacing];
+
[NSLayoutConstraint activateConstraints:@[
- [_imageContainer.widthAnchor constraintEqualToConstant:kImageSize],
- [_imageContainer.heightAnchor
- constraintEqualToAnchor:_imageContainer.widthAnchor],
+ // Image.
+ _imageSize,
+ [_imageContainer.widthAnchor
+ constraintEqualToAnchor:_imageContainer.heightAnchor],
[_imageContainer.topAnchor constraintEqualToAnchor:_titleLabel.topAnchor],
- // Publisher.
- [_publisherLabel.topAnchor
+ // Text.
+ _imageTitleSpacing, _titleSubtitleSpacing,
+ [_titleLabel.trailingAnchor
+ constraintEqualToAnchor:_subtitleLabel.trailingAnchor],
+
+ // Additional Information.
+ [_additionalInformationLabel.topAnchor
constraintGreaterThanOrEqualToAnchor:_imageContainer.bottomAnchor
constant:kStandardSpacing],
- [_publisherLabel.topAnchor
+ [_additionalInformationLabel.topAnchor
constraintGreaterThanOrEqualToAnchor:_subtitleLabel.bottomAnchor
constant:kStandardSpacing],
- [_publisherLabel.bottomAnchor
+ [_additionalInformationLabel.bottomAnchor
constraintLessThanOrEqualToAnchor:self.contentView.bottomAnchor
constant:-kStandardSpacing],
@@ -266,7 +354,7 @@ const CGFloat kAnimationDuration = 0.3;
constraintGreaterThanOrEqualToAnchor:_subtitleLabel.bottomAnchor
constant:kStandardSpacing],
[_faviconView.centerYAnchor
- constraintEqualToAnchor:_publisherLabel.centerYAnchor],
+ constraintEqualToAnchor:_additionalInformationLabel.centerYAnchor],
[_faviconView.bottomAnchor
constraintLessThanOrEqualToAnchor:self.contentView.bottomAnchor
constant:-kStandardSpacing],
@@ -287,16 +375,17 @@ const CGFloat kAnimationDuration = 0.3;
ApplyVisualConstraintsWithMetrics(
@[
- @"H:|-(space)-[title]-(space)-[image]-(space)-|",
- @"H:|-(space)-[text]-(space)-[image]",
- @"V:|-(space)-[title]-[text]",
- @"H:|-(space)-[favicon]-(small)-[publish]-(space)-|",
+ @"H:|-(space)-[title]",
+ @"H:[image]-(space)-|",
+ @"H:|-(space)-[text]",
+ @"V:|-(space)-[title]",
+ @"H:|-(space)-[favicon]-(small)-[additional]-(space)-|",
],
@{
@"image" : _imageContainer,
@"title" : _titleLabel,
@"text" : _subtitleLabel,
- @"publish" : _publisherLabel,
+ @"additional" : _additionalInformationLabel,
@"favicon" : _faviconView,
},
@{ @"space" : @(kStandardSpacing),

Powered by Google App Engine
This is Rietveld 408576698