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/cells/content_suggestions_whats_new_item.h"
6
7#import <MaterialComponents/MaterialTypography.h>
8
9#include "base/check_op.h"
10#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
11#include "ios/chrome/common/string_util.h"
12#import "ios/chrome/common/ui/colors/semantic_color_names.h"
13#import "ios/chrome/common/ui/util/constraints_ui_util.h"
14
15#if !defined(__has_feature) || !__has_feature(objc_arc)
16#error "This file requires ARC support."
17#endif
18
19namespace {
20
21const CGFloat kLabelMargin = 14;
22const CGFloat kLabelLineSpacing = 4;
23const CGFloat kLabelIconMargin = 8;
24const CGFloat kLabelFontSize = 14;
25const CGFloat kIconSize = 24;
26const CGFloat kIconTopMargin = 10;
27
28}  // namespace
29
30#pragma mark - ContentSuggestionsWhatsNewItem
31
32@implementation ContentSuggestionsWhatsNewItem
33
34@synthesize text = _text;
35@synthesize icon = _icon;
36@synthesize suggestionIdentifier = _suggestionIdentifier;
37@synthesize metricsRecorded = _metricsRecorded;
38
39- (instancetype)initWithType:(NSInteger)type {
40  self = [super initWithType:type];
41  if (self) {
42    self.cellClass = [ContentSuggestionsWhatsNewCell class];
43  }
44  return self;
45}
46
47- (void)configureCell:(ContentSuggestionsWhatsNewCell*)cell {
48  [super configureCell:cell];
49  [cell setIcon:self.icon];
50  [cell setText:self.text];
51  cell.accessibilityIdentifier = [[self class] accessibilityIdentifier];
52}
53
54- (CGFloat)cellHeightForWidth:(CGFloat)width {
55  return [self.cellClass heightForWidth:width withText:self.text];
56}
57
58+ (NSString*)accessibilityIdentifier {
59  return @"ContentSuggestionsWhatsNewIdentifier";
60}
61
62@end
63
64#pragma mark - ContentSuggestionsWhatsNewCell
65
66@interface ContentSuggestionsWhatsNewCell ()
67
68@property(nonatomic, strong) UIImageView* iconView;
69@property(nonatomic, strong) UILabel* promoLabel;
70@property(nonatomic, strong) UIView* containerView;
71
72@end
73
74@implementation ContentSuggestionsWhatsNewCell
75
76@synthesize iconView = _iconView;
77@synthesize promoLabel = _promoLabel;
78@synthesize containerView = _containerView;
79
80- (instancetype)initWithFrame:(CGRect)frame {
81  self = [super initWithFrame:frame];
82  if (self) {
83    _iconView = [[UIImageView alloc] init];
84    _promoLabel = [[UILabel alloc] init];
85    _containerView = [[UIView alloc] init];
86
87    _iconView.translatesAutoresizingMaskIntoConstraints = NO;
88    _promoLabel.translatesAutoresizingMaskIntoConstraints = NO;
89    _containerView.translatesAutoresizingMaskIntoConstraints = NO;
90
91    [self.contentView addSubview:_containerView];
92    [_containerView addSubview:_iconView];
93    [_containerView addSubview:_promoLabel];
94
95    ApplyVisualConstraintsWithMetrics(
96        @[
97          @"V:|-margin-[promo]-margin-|", @"V:|-iconMargin-[icon(==iconSize)]",
98          @"V:|[container]|", @"H:|[icon(==iconSize)]-spacing-[promo]|",
99          @"H:|->=0-[container]->=0-|"
100        ],
101        @{
102          @"icon" : _iconView,
103          @"promo" : _promoLabel,
104          @"container" : _containerView
105        },
106        @{
107          @"margin" : @(kLabelMargin),
108          @"iconMargin" : @(kIconTopMargin),
109          @"iconSize" : @(kIconSize),
110          @"spacing" : @(kLabelIconMargin)
111        });
112    [NSLayoutConstraint activateConstraints:@[
113      [_containerView.centerXAnchor
114          constraintEqualToAnchor:self.contentView.centerXAnchor]
115    ]];
116  }
117  return self;
118}
119
120- (void)setIcon:(UIImage*)icon {
121  self.iconView.image = icon;
122}
123
124- (void)setText:(NSString*)text {
125  [[self class] configureLabel:self.promoLabel withText:text];
126}
127
128+ (CGFloat)heightForWidth:(CGFloat)width withText:(NSString*)text {
129  UILabel* label = [[UILabel alloc] init];
130  [self configureLabel:label withText:text];
131  CGSize sizeForLabel = CGSizeMake(width - kLabelIconMargin - kIconSize, 500);
132
133  return 2 * kLabelMargin + [label sizeThatFits:sizeForLabel].height;
134}
135
136#pragma mark UIView
137
138// Implements -layoutSubviews as per instructions in documentation for
139// +[MDCCollectionViewCell cr_preferredHeightForWidth:forItem:].
140- (void)layoutSubviews {
141  [super layoutSubviews];
142
143  // Adjust the text label preferredMaxLayoutWidth when the parent's width
144  // changes, for instance on screen rotation.
145  CGFloat parentWidth = CGRectGetWidth(self.contentView.bounds);
146
147  self.promoLabel.preferredMaxLayoutWidth =
148      parentWidth - kIconSize - kLabelIconMargin;
149
150  // Re-layout with the new preferred width to allow the label to adjust its
151  // height.
152  [super layoutSubviews];
153}
154
155#pragma mark Private
156
157// Configures the |promoLabel| with the |text|.
158+ (void)configureLabel:(UILabel*)promoLabel withText:(NSString*)text {
159  promoLabel.font =
160      [[MDCTypography fontLoader] regularFontOfSize:kLabelFontSize];
161  promoLabel.textColor = [UIColor colorNamed:kTextPrimaryColor];
162  promoLabel.numberOfLines = 0;
163
164  NSRange linkRange;
165  NSString* strippedText = ParseStringWithLink(text, &linkRange);
166  DCHECK_NE(NSNotFound, static_cast<NSInteger>(linkRange.location));
167  DCHECK_NE(0u, linkRange.length);
168
169  NSMutableAttributedString* attributedText =
170      [[NSMutableAttributedString alloc] initWithString:strippedText];
171
172  // Sets the styling to mimic a link.
173  UIColor* linkColor = [UIColor colorNamed:kBlueColor];
174  [attributedText addAttribute:NSForegroundColorAttributeName
175                         value:linkColor
176                         range:linkRange];
177  [attributedText addAttribute:NSUnderlineStyleAttributeName
178                         value:@(NSUnderlineStyleSingle)
179                         range:linkRange];
180  [attributedText addAttribute:NSUnderlineColorAttributeName
181                         value:linkColor
182                         range:linkRange];
183
184  // Sets the line spacing on the attributed string.
185  NSInteger strLength = [strippedText length];
186  NSMutableParagraphStyle* style = [[NSMutableParagraphStyle alloc] init];
187  [style setLineSpacing:kLabelLineSpacing];
188  [attributedText addAttribute:NSParagraphStyleAttributeName
189                         value:style
190                         range:NSMakeRange(0, strLength)];
191
192  [promoLabel setAttributedText:attributedText];
193}
194
195@end
196