| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_article_i
tem.h" | |
| 6 | |
| 7 #include "base/time/time.h" | |
| 8 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" | |
| 9 #import "ios/chrome/browser/ui/uikit_ui_util.h" | |
| 10 #import "ios/chrome/browser/ui/util/i18n_string.h" | |
| 11 #import "ios/third_party/material_components_ios/src/components/Typography/src/M
aterialTypography.h" | |
| 12 #include "url/gurl.h" | |
| 13 | |
| 14 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
| 15 #error "This file requires ARC support." | |
| 16 #endif | |
| 17 | |
| 18 namespace { | |
| 19 const CGFloat kImageSize = 72; | |
| 20 // When updating this, make sure to update |layoutSubviews|. | |
| 21 const CGFloat kStandardSpacing = 8; | |
| 22 } | |
| 23 | |
| 24 @interface ContentSuggestionsArticleItem () | |
| 25 | |
| 26 @property(nonatomic, copy) NSString* subtitle; | |
| 27 // Used to check if the image has already been fetched. There is no way to | |
| 28 // discriminate between failed image download and nonexitent image. The article | |
| 29 // tries to download the image only once. | |
| 30 @property(nonatomic, assign) BOOL imageFetched; | |
| 31 | |
| 32 @end | |
| 33 | |
| 34 #pragma mark - ContentSuggestionsArticleItem | |
| 35 | |
| 36 @implementation ContentSuggestionsArticleItem | |
| 37 | |
| 38 @synthesize title = _title; | |
| 39 @synthesize subtitle = _subtitle; | |
| 40 @synthesize image = _image; | |
| 41 @synthesize articleURL = _articleURL; | |
| 42 @synthesize publisher = _publisher; | |
| 43 @synthesize publishDate = _publishDate; | |
| 44 @synthesize suggestionIdentifier = _suggestionIdentifier; | |
| 45 @synthesize delegate = _delegate; | |
| 46 @synthesize imageFetched = _imageFetched; | |
| 47 | |
| 48 - (instancetype)initWithType:(NSInteger)type | |
| 49 title:(NSString*)title | |
| 50 subtitle:(NSString*)subtitle | |
| 51 delegate:(id<ContentSuggestionsArticleItemDelegate>)delegate | |
| 52 url:(const GURL&)url { | |
| 53 self = [super initWithType:type]; | |
| 54 if (self) { | |
| 55 self.cellClass = [ContentSuggestionsArticleCell class]; | |
| 56 _title = [title copy]; | |
| 57 _subtitle = [subtitle copy]; | |
| 58 _articleURL = url; | |
| 59 _delegate = delegate; | |
| 60 _image = [self emptyImageBackground]; | |
| 61 } | |
| 62 return self; | |
| 63 } | |
| 64 | |
| 65 - (void)configureCell:(ContentSuggestionsArticleCell*)cell { | |
| 66 [super configureCell:cell]; | |
| 67 if (!self.imageFetched) { | |
| 68 self.imageFetched = YES; | |
| 69 // Fetch the image. During the fetch the cell's image should still be set. | |
| 70 [self.delegate loadImageForArticleItem:self]; | |
| 71 } | |
| 72 cell.titleLabel.text = self.title; | |
| 73 cell.subtitleLabel.text = self.subtitle; | |
| 74 cell.imageView.image = self.image; | |
| 75 [cell setPublisherName:self.publisher date:self.publishDate]; | |
| 76 } | |
| 77 | |
| 78 #pragma mark - Private | |
| 79 | |
| 80 - (UIImage*)emptyImageBackground { | |
| 81 // TODO(crbug.com/698171): Remove this function once we have real background | |
| 82 // image. | |
| 83 UIColor* color = [UIColor lightGrayColor]; | |
| 84 CGRect rect = CGRectMake(0, 0, 1, 1); | |
| 85 UIGraphicsBeginImageContext(rect.size); | |
| 86 [color setFill]; | |
| 87 UIRectFill(rect); | |
| 88 UIImage* image = UIGraphicsGetImageFromCurrentImageContext(); | |
| 89 UIGraphicsEndImageContext(); | |
| 90 return image; | |
| 91 } | |
| 92 | |
| 93 @end | |
| 94 | |
| 95 #pragma mark - ContentSuggestionsArticleCell | |
| 96 | |
| 97 @interface ContentSuggestionsArticleCell () | |
| 98 | |
| 99 @property(nonatomic, strong) UILabel* publisherLabel; | |
| 100 | |
| 101 // Applies the constraints on the elements. Called in the init. | |
| 102 - (void)applyConstraints; | |
| 103 | |
| 104 @end | |
| 105 | |
| 106 @implementation ContentSuggestionsArticleCell | |
| 107 | |
| 108 @synthesize titleLabel = _titleLabel; | |
| 109 @synthesize subtitleLabel = _subtitleLabel; | |
| 110 @synthesize imageView = _imageView; | |
| 111 @synthesize publisherLabel = _publisherLabel; | |
| 112 | |
| 113 - (instancetype)initWithFrame:(CGRect)frame { | |
| 114 self = [super initWithFrame:frame]; | |
| 115 if (self) { | |
| 116 _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; | |
| 117 _subtitleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; | |
| 118 _imageView = [[UIImageView alloc] initWithFrame:CGRectZero]; | |
| 119 _publisherLabel = [[UILabel alloc] initWithFrame:CGRectZero]; | |
| 120 | |
| 121 _titleLabel.numberOfLines = 2; | |
| 122 _subtitleLabel.numberOfLines = 0; | |
| 123 [_subtitleLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh | |
| 124 forAxis:UILayoutConstraintAxisVertical]; | |
| 125 [_titleLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh | |
| 126 forAxis:UILayoutConstraintAxisVertical]; | |
| 127 _imageView.contentMode = UIViewContentModeScaleAspectFill; | |
| 128 _imageView.clipsToBounds = YES; | |
| 129 | |
| 130 _imageView.translatesAutoresizingMaskIntoConstraints = NO; | |
| 131 _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; | |
| 132 _subtitleLabel.translatesAutoresizingMaskIntoConstraints = NO; | |
| 133 _publisherLabel.translatesAutoresizingMaskIntoConstraints = NO; | |
| 134 | |
| 135 [self.contentView addSubview:_imageView]; | |
| 136 [self.contentView addSubview:_titleLabel]; | |
| 137 [self.contentView addSubview:_subtitleLabel]; | |
| 138 [self.contentView addSubview:_publisherLabel]; | |
| 139 | |
| 140 _titleLabel.font = [MDCTypography subheadFont]; | |
| 141 _subtitleLabel.font = [MDCTypography body1Font]; | |
| 142 _publisherLabel.font = [MDCTypography captionFont]; | |
| 143 | |
| 144 _subtitleLabel.textColor = [[MDCPalette greyPalette] tint700]; | |
| 145 _publisherLabel.textColor = [[MDCPalette greyPalette] tint700]; | |
| 146 | |
| 147 [self applyConstraints]; | |
| 148 } | |
| 149 return self; | |
| 150 } | |
| 151 | |
| 152 - (void)setPublisherName:(NSString*)publisherName date:(base::Time)publishDate { | |
| 153 NSDate* date = [NSDate dateWithTimeIntervalSince1970:publishDate.ToDoubleT()]; | |
| 154 NSString* dateString = | |
| 155 [NSDateFormatter localizedStringFromDate:date | |
| 156 dateStyle:NSDateFormatterMediumStyle | |
| 157 timeStyle:NSDateFormatterNoStyle]; | |
| 158 | |
| 159 self.publisherLabel.text = AdjustStringForLocaleDirection( | |
| 160 [NSString stringWithFormat:@"%@ - %@.", publisherName, dateString]); | |
| 161 } | |
| 162 | |
| 163 #pragma mark - UIView | |
| 164 | |
| 165 // Implements -layoutSubviews as per instructions in documentation for | |
| 166 // +[MDCCollectionViewCell cr_preferredHeightForWidth:forItem:]. | |
| 167 - (void)layoutSubviews { | |
| 168 [super layoutSubviews]; | |
| 169 | |
| 170 // Adjust the text label preferredMaxLayoutWidth when the parent's width | |
| 171 // changes, for instance on screen rotation. | |
| 172 CGFloat parentWidth = CGRectGetWidth(self.contentView.bounds); | |
| 173 | |
| 174 self.titleLabel.preferredMaxLayoutWidth = | |
| 175 parentWidth - kImageSize - 3 * kStandardSpacing; | |
| 176 self.subtitleLabel.preferredMaxLayoutWidth = | |
| 177 parentWidth - kImageSize - 3 * kStandardSpacing; | |
| 178 | |
| 179 // Re-layout with the new preferred width to allow the label to adjust its | |
| 180 // height. | |
| 181 [super layoutSubviews]; | |
| 182 } | |
| 183 | |
| 184 #pragma mark - Private | |
| 185 | |
| 186 - (void)applyConstraints { | |
| 187 [NSLayoutConstraint activateConstraints:@[ | |
| 188 [_imageView.widthAnchor constraintEqualToConstant:kImageSize], | |
| 189 [_imageView.heightAnchor constraintEqualToAnchor:_imageView.widthAnchor], | |
| 190 [_publisherLabel.topAnchor | |
| 191 constraintGreaterThanOrEqualToAnchor:_imageView.bottomAnchor | |
| 192 constant:kStandardSpacing], | |
| 193 [_publisherLabel.topAnchor | |
| 194 constraintGreaterThanOrEqualToAnchor:_subtitleLabel.bottomAnchor | |
| 195 constant:kStandardSpacing], | |
| 196 ]]; | |
| 197 | |
| 198 ApplyVisualConstraintsWithMetrics( | |
| 199 @[ | |
| 200 @"H:|-(space)-[title]-(space)-[image]-(space)-|", | |
| 201 @"H:|-(space)-[text]-(space)-[image]", | |
| 202 @"V:|-[title]-[text]", | |
| 203 @"V:|-[image]", | |
| 204 @"H:|-[publish]-|", | |
| 205 @"V:[publish]-|", | |
| 206 ], | |
| 207 @{ | |
| 208 @"image" : _imageView, | |
| 209 @"title" : _titleLabel, | |
| 210 @"text" : _subtitleLabel, | |
| 211 @"publish" : _publisherLabel, | |
| 212 }, | |
| 213 @{ @"space" : @(kStandardSpacing) }); | |
| 214 } | |
| 215 | |
| 216 @end | |
| OLD | NEW |