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