// Copyright 2024 The Chromium Authors
// 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/tab_switcher/tab_grid/grid/regular/inactive_tabs_button_cell.h"
#import "base/strings/string_number_conversions.h"
#import "ios/chrome/browser/shared/ui/symbols/symbols.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_constants.h"
#import "ios/chrome/common/ui/colors/semantic_color_names.h"
#import "ios/chrome/grit/ios_strings.h"
#import "ui/base/l10n/l10n_util_mac.h"
namespace {
constexpr CGFloat kHorizontalPadding = 16;
constexpr CGFloat kVerticalPadding = 10;
constexpr CGFloat kInterTextSpacing = 4;
constexpr CGFloat kDefaultPadding = 8;
constexpr CGFloat kCornerRadius = 10;
} // namespace
@implementation InactiveTabsButtonCell {
UILabel* _titleLabel;
UILabel* _subtitleLabel;
UILabel* _countLabel;
UIView* _disclosureIndicator;
NSArray<NSLayoutConstraint*>* _regularConstraints;
NSArray<NSLayoutConstraint*>* _accessibilityConstraints;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor =
[UIColor colorNamed:kGroupedSecondaryBackgroundColor];
self.layer.cornerRadius = kCornerRadius;
self.accessibilityIdentifier = kInactiveTabsButtonAccessibilityIdentifier;
self.isAccessibilityElement = YES;
self.accessibilityTraits = UIAccessibilityTraitButton;
[self updateAccessibilityLabel];
UIView* contentView = self.contentView;
_titleLabel = [self createTitleLabel];
[contentView addSubview:_titleLabel];
_subtitleLabel = [self createSubtitleLabel];
[contentView addSubview:_subtitleLabel];
_countLabel = [self createCountLabel];
[contentView addSubview:_countLabel];
UIView* disclosureIndicator = [self createDisclosureIndicator];
[contentView addSubview:disclosureIndicator];
UILayoutGuide* textGuide = [[UILayoutGuide alloc] init];
[contentView addLayoutGuide:textGuide];
[NSLayoutConstraint activateConstraints:@[
[disclosureIndicator.trailingAnchor
constraintEqualToAnchor:contentView.trailingAnchor
constant:-kHorizontalPadding],
[disclosureIndicator.centerYAnchor
constraintEqualToAnchor:contentView.centerYAnchor],
[textGuide.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor
constant:kHorizontalPadding],
[textGuide.topAnchor constraintEqualToAnchor:contentView.topAnchor
constant:kVerticalPadding],
[textGuide.bottomAnchor constraintEqualToAnchor:contentView.bottomAnchor
constant:-kVerticalPadding],
[_titleLabel.leadingAnchor
constraintEqualToAnchor:textGuide.leadingAnchor],
[_titleLabel.topAnchor constraintEqualToAnchor:textGuide.topAnchor],
[_titleLabel.trailingAnchor
constraintLessThanOrEqualToAnchor:textGuide.trailingAnchor],
[_subtitleLabel.leadingAnchor
constraintEqualToAnchor:textGuide.leadingAnchor],
[_subtitleLabel.bottomAnchor
constraintEqualToAnchor:textGuide.bottomAnchor],
[_subtitleLabel.trailingAnchor
constraintLessThanOrEqualToAnchor:textGuide.trailingAnchor],
]];
_regularConstraints = @[
[_countLabel.leadingAnchor
constraintEqualToAnchor:textGuide.trailingAnchor
constant:kDefaultPadding],
[_countLabel.trailingAnchor
constraintEqualToAnchor:disclosureIndicator.leadingAnchor
constant:-kDefaultPadding],
[_countLabel.centerYAnchor
constraintEqualToAnchor:contentView.centerYAnchor],
[_subtitleLabel.topAnchor constraintEqualToAnchor:_titleLabel.bottomAnchor
constant:kInterTextSpacing],
];
_accessibilityConstraints = @[
[_countLabel.leadingAnchor
constraintEqualToAnchor:textGuide.leadingAnchor],
[_countLabel.topAnchor constraintEqualToAnchor:_titleLabel.bottomAnchor
constant:kDefaultPadding],
[_countLabel.bottomAnchor constraintEqualToAnchor:_subtitleLabel.topAnchor
constant:-kDefaultPadding],
[textGuide.trailingAnchor
constraintEqualToAnchor:disclosureIndicator.leadingAnchor
constant:-kDefaultPadding],
];
if (UIContentSizeCategoryIsAccessibilityCategory(
self.traitCollection.preferredContentSizeCategory)) {
[NSLayoutConstraint activateConstraints:_accessibilityConstraints];
} else {
[NSLayoutConstraint activateConstraints:_regularConstraints];
}
if (@available(iOS 17, *)) {
[self
registerForTraitChanges:@[ UITraitPreferredContentSizeCategory.class ]
withTarget:self
action:@selector
(updateConstraintsForFontSizeChange)];
}
}
return self;
}
#pragma mark - Accessor
- (void)setCount:(NSInteger)count {
_count = count;
NSString* countText =
count > 99 ? @"99+" : [NSString stringWithFormat:@"%ld", count];
_countLabel.text = countText;
[self updateAccessibilityLabel];
}
- (void)setDaysThreshold:(NSInteger)daysThreshold {
_daysThreshold = daysThreshold;
_subtitleLabel.text =
l10n_util::GetNSStringF(IDS_IOS_INACTIVE_TABS_BUTTON_SUBTITLE,
base::NumberToString16(daysThreshold));
[self updateAccessibilityLabel];
}
#pragma mark - UICollectionViewCell
- (void)setHighlighted:(BOOL)highlighted {
[super setHighlighted:highlighted];
if (highlighted) {
self.backgroundColor = [UIColor systemGray4Color];
} else {
self.backgroundColor =
[UIColor colorNamed:kGroupedSecondaryBackgroundColor];
}
}
#pragma mark - UIView
#if !defined(__IPHONE_17_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_17_0
- (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection {
[super traitCollectionDidChange:previousTraitCollection];
if (@available(iOS 17, *)) {
return;
}
// Update constraints for user's preferredContentSize.
if (self.traitCollection.preferredContentSizeCategory !=
previousTraitCollection.preferredContentSizeCategory) {
[self updateConstraintsForFontSizeChange];
}
}
#endif
#pragma mark - Private
// Updates the constraints to take into account the accessibility category.
- (void)updateConstraintsForFontSizeChange {
if (UIContentSizeCategoryIsAccessibilityCategory(
self.traitCollection.preferredContentSizeCategory)) {
[NSLayoutConstraint deactivateConstraints:_regularConstraints];
[NSLayoutConstraint activateConstraints:_accessibilityConstraints];
} else {
[NSLayoutConstraint deactivateConstraints:_accessibilityConstraints];
[NSLayoutConstraint activateConstraints:_regularConstraints];
}
}
// Returns a configured title label.
- (UILabel*)createTitleLabel {
UILabel* label = [[UILabel alloc] init];
label.translatesAutoresizingMaskIntoConstraints = NO;
label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
label.adjustsFontForContentSizeCategory = YES;
label.text = l10n_util::GetNSString(IDS_IOS_INACTIVE_TABS_BUTTON_TITLE);
label.textColor = UIColor.whiteColor;
return label;
}
// Returns a configured subtitle label.
- (UILabel*)createSubtitleLabel {
UILabel* label = [[UILabel alloc] init];
label.translatesAutoresizingMaskIntoConstraints = NO;
label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote];
label.adjustsFontForContentSizeCategory = YES;
label.text =
l10n_util::GetNSStringF(IDS_IOS_INACTIVE_TABS_BUTTON_SUBTITLE,
base::NumberToString16(self.daysThreshold));
label.textColor = [UIColor colorNamed:kTextSecondaryColor];
return label;
}
// Returns a configured count label.
- (UILabel*)createCountLabel {
UILabel* label = [[UILabel alloc] init];
label.translatesAutoresizingMaskIntoConstraints = NO;
label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
label.adjustsFontForContentSizeCategory = YES;
label.textColor = [UIColor colorNamed:kTextSecondaryColor];
return label;
}
// Returns a configured disclosure indicator.
- (UIView*)createDisclosureIndicator {
UIImageSymbolConfiguration* conf = [UIImageSymbolConfiguration
configurationWithTextStyle:UIFontTextStyleBody];
UIImageSymbolConfiguration* boldConf = [UIImageSymbolConfiguration
configurationWithWeight:UIImageSymbolWeightSemibold];
conf = [conf configurationByApplyingConfiguration:boldConf];
UIImage* disclosure =
DefaultSymbolWithConfiguration(kChevronForwardSymbol, conf);
UIImageView* disclosureIndicator =
[[UIImageView alloc] initWithImage:disclosure];
disclosureIndicator.tintColor = [UIColor colorNamed:kTextTertiaryColor];
disclosureIndicator.translatesAutoresizingMaskIntoConstraints = NO;
return disclosureIndicator;
}
// Updates the accessibility label of the cell.
- (void)updateAccessibilityLabel {
self.accessibilityLabel = [NSString
stringWithFormat:@"%@, %@, %ld",
l10n_util::GetNSString(
IDS_IOS_INACTIVE_TABS_BUTTON_TITLE),
l10n_util::GetNSStringF(
IDS_IOS_INACTIVE_TABS_BUTTON_SUBTITLE,
base::NumberToString16(self.daysThreshold)),
self.count];
}
@end