chromium/ios/chrome/browser/ui/content_suggestions/set_up_list/set_up_list_show_more_item_view.mm

// Copyright 2023 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/content_suggestions/set_up_list/set_up_list_show_more_item_view.h"

#import "base/notreached.h"
#import "ios/chrome/browser/ntp/model/set_up_list_item_type.h"
#import "ios/chrome/browser/segmentation_platform/model/segmented_default_browser_utils.h"
#import "ios/chrome/browser/shared/public/features/features.h"
#import "ios/chrome/browser/shared/ui/elements/crossfade_label.h"
#import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
#import "ios/chrome/browser/ui/content_suggestions/set_up_list/constants.h"
#import "ios/chrome/browser/ui/content_suggestions/set_up_list/set_up_list_item_icon.h"
#import "ios/chrome/browser/ui/content_suggestions/set_up_list/set_up_list_item_view.h"
#import "ios/chrome/browser/ui/content_suggestions/set_up_list/set_up_list_item_view_data.h"
#import "ios/chrome/browser/ui/content_suggestions/set_up_list/set_up_list_tap_delegate.h"
#import "ios/chrome/common/ui/colors/semantic_color_names.h"
#import "ios/chrome/common/ui/util/constraints_ui_util.h"
#import "ios/chrome/grit/ios_branded_strings.h"
#import "ios/chrome/grit/ios_strings.h"
#import "ui/base/l10n/l10n_util.h"

namespace {

const CGFloat kExtraSpacingForSmallerCompleteIcon = 16.0f;

const CGFloat kContentStackViewSpacing = 16.0f;
const CGFloat kContentStackVerticalSpacing = 15.0f;
const CGFloat kIconImageContainerWidth = 64.0f;
const CGFloat kTryButtonWidth = 64.0f;
const CGFloat kTitleDescriptionSpacing = 5.0f;

// Returns an NSAttributedString with strikethrough.
NSAttributedString* Strikethrough(NSString* text) {
  NSDictionary<NSAttributedStringKey, id>* attrs =
      @{NSStrikethroughStyleAttributeName : @(NSUnderlineStyleSingle)};
  return [[NSAttributedString alloc] initWithString:text attributes:attrs];
}

}  // namespace

@implementation SetUpListShowMoreItemView {
  SetUpListItemViewData* _data;
}

- (instancetype)initWithData:(SetUpListItemViewData*)data {
  self = [super init];
  if (self) {
    _data = data;
  }
  return self;
}

#pragma mark - UIView

- (void)willMoveToSuperview:(UIView*)newSuperview {
  [super willMoveToSuperview:newSuperview];

  [self createSubviews];
}

#pragma mark - Private

- (void)createSubviews {
  // Return if the subviews have already been created and added.
  if (!(self.subviews.count == 0)) {
    return;
  }

  // Add a horizontal stack to contain the icon(s) and the text stack.
  UIStackView* contentStack = [[UIStackView alloc] init];
  contentStack.translatesAutoresizingMaskIntoConstraints = NO;
  contentStack.alignment = UIStackViewAlignmentCenter;
  contentStack.distribution = UIStackViewDistributionFill;
  CGFloat extraSpacingForSmallerCompleteIcon =
      _data.complete ? kExtraSpacingForSmallerCompleteIcon : 0;
  contentStack.spacing =
      kContentStackViewSpacing + extraSpacingForSmallerCompleteIcon;
  [self addSubview:contentStack];
  AddSameConstraintsWithInsets(
      contentStack, self,
      NSDirectionalEdgeInsetsMake(kContentStackVerticalSpacing,
                                  extraSpacingForSmallerCompleteIcon,
                                  kContentStackVerticalSpacing, 0));

  SetUpListItemIcon* icon =
      [[SetUpListItemIcon alloc] initWithType:_data.type
                                     complete:_data.complete
                                compactLayout:NO
                                     inSquare:YES];
  if (!_data.complete) {
    icon.translatesAutoresizingMaskIntoConstraints = NO;
    UIView* imageContainerView = [[UIView alloc] init];
    imageContainerView.backgroundColor = [UIColor colorNamed:kGrey100Color];
    imageContainerView.layer.cornerRadius = 12;
    imageContainerView.layer.masksToBounds = NO;
    imageContainerView.clipsToBounds = YES;
    [imageContainerView addSubview:icon];
    AddSameCenterConstraints(icon, imageContainerView);
    [NSLayoutConstraint activateConstraints:@[
      [imageContainerView.widthAnchor
          constraintEqualToConstant:kIconImageContainerWidth],
      [imageContainerView.widthAnchor
          constraintEqualToAnchor:imageContainerView.heightAnchor],
    ]];
    [contentStack addArrangedSubview:imageContainerView];
  } else {
    [contentStack addArrangedSubview:icon];
  }

  UILabel* title = [self createTitle];
  UILabel* description = [self createDescription];

  // Add a vertical stack for the title and description labels.
  UIStackView* textStack =
      [[UIStackView alloc] initWithArrangedSubviews:@[ title, description ]];
  textStack.axis = UILayoutConstraintAxisVertical;
  textStack.spacing = kTitleDescriptionSpacing;
  [contentStack addArrangedSubview:textStack];

  if (!_data.complete) {
    UIButton* tryButton = [[UIButton alloc] init];
    tryButton.backgroundColor =
        [UIColor colorNamed:kGroupedPrimaryBackgroundColor];
    tryButton.titleLabel.font =
        CreateDynamicFont(UIFontTextStyleSubheadline, UIFontWeightSemibold);
    NSString* tryButtonTitle =
        l10n_util::GetNSString(IDS_IOS_SET_UP_LIST_TRY_BUTTON_TEXT);
    [tryButton setTitle:tryButtonTitle forState:UIControlStateNormal];
    [tryButton setTitleColor:[UIColor colorNamed:kBlueColor]
                    forState:UIControlStateNormal];
    [tryButton addTarget:self
                  action:@selector(tryTapped)
        forControlEvents:UIControlEventTouchUpInside];
    NSString* itemTitle = [self titleText];
    tryButton.accessibilityIdentifier =
        [NSString stringWithFormat:@"%@ Try Button", itemTitle];
    tryButton.accessibilityLabel =
        [NSString stringWithFormat:@"%@, %@", tryButtonTitle, itemTitle];
    tryButton.layer.cornerRadius = 15;
    tryButton.pointerInteractionEnabled = YES;
    [NSLayoutConstraint activateConstraints:@[
      [tryButton.widthAnchor constraintEqualToConstant:kTryButtonWidth],
    ]];
    [contentStack addArrangedSubview:tryButton];
    self.accessibilityHint = l10n_util::GetNSString(
        IDS_IOS_SET_UP_LIST_TRY_BUTTON_ACCESSIBILITY_HINT);
  } else {
    self.accessibilityTraits |= UIAccessibilityTraitNotEnabled;
  }

  self.isAccessibilityElement = YES;
  self.accessibilityLabel =
      [NSString stringWithFormat:@"%@, %@", title.text, description.text];
}

// Creates the title label.
- (CrossfadeLabel*)createTitle {
  CrossfadeLabel* label = [[CrossfadeLabel alloc] init];
  label.text = [self titleText];
  label.accessibilityIdentifier = set_up_list::kAccessibilityID;
  label.font =
      CreateDynamicFont(UIFontTextStyleSubheadline, UIFontWeightSemibold);
  if (_data.complete) {
    label.textColor = [UIColor colorNamed:kTextQuaternaryColor];
    label.attributedText = Strikethrough(label.text);
  } else {
    label.textColor = [UIColor colorNamed:kTextPrimaryColor];
  }
  return label;
}

// Returns the text for the title label.
- (NSString*)titleText {
  switch (_data.type) {
    case SetUpListItemType::kSignInSync:
      return l10n_util::GetNSString(
          IDS_IOS_CONSISTENCY_PROMO_DEFAULT_ACCOUNT_TITLE);
    case SetUpListItemType::kDefaultBrowser:
      return l10n_util::GetNSString(IDS_IOS_SET_UP_LIST_DEFAULT_BROWSER_TITLE);
    case SetUpListItemType::kAutofill:
      return l10n_util::GetNSString(IDS_IOS_SET_UP_LIST_AUTOFILL_TITLE);
    case SetUpListItemType::kNotifications:
      return IsIOSTipsNotificationsEnabled()
                 ? l10n_util::GetNSString(
                       IDS_IOS_SET_UP_LIST_NOTIFICATIONS_TITLE)
                 : l10n_util::GetNSString(
                       IDS_IOS_SET_UP_LIST_CONTENT_NOTIFICATION_TITLE);
    case SetUpListItemType::kAllSet:
      return l10n_util::GetNSString(IDS_IOS_SET_UP_LIST_ALL_SET_TITLE);
    case SetUpListItemType::kFollow:
      // TODO(crbug.com/40262090): Add a Follow item to the Set Up List.
      NOTREACHED();
  }
}

// Creates the description label.
- (CrossfadeLabel*)createDescription {
  CrossfadeLabel* label = [[CrossfadeLabel alloc] init];
  label = [[CrossfadeLabel alloc] init];
  label.text = [self descriptionText];
  label.accessibilityIdentifier = set_up_list::kAccessibilityID;
  label.numberOfLines = 0;
  label.lineBreakMode = NSLineBreakByWordWrapping;
  //  label.translatesAutoresizingMaskIntoConstraints = NO;
  label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote];
  if (_data.complete) {
    label.textColor = [UIColor colorNamed:kTextQuaternaryColor];
    label.attributedText = Strikethrough(label.text);
  } else {
    label.textColor = [UIColor colorNamed:kTextSecondaryColor];
  }
  return label;
}

// Returns the text for the description label.
- (NSString*)descriptionText {
  switch (_data.type) {
    case SetUpListItemType::kSignInSync:
      return l10n_util::GetNSString(IDS_IOS_IDENTITY_DISC_SIGN_IN_PROMO_LABEL);
    case SetUpListItemType::kDefaultBrowser:
      return l10n_util::GetNSString(
          IsSegmentedDefaultBrowserPromoEnabled()
              ? GetSetUpListDefaultBrowserDescriptionStringID(_data.userSegment)
              : IDS_IOS_SET_UP_LIST_DEFAULT_BROWSER_SEE_MORE_DESCRIPTION);
    case SetUpListItemType::kAutofill:
      return l10n_util::GetNSString(
          IDS_IOS_SET_UP_LIST_AUTOFILL_SEE_MORE_DESCRIPTION);
    case SetUpListItemType::kNotifications:
      return IsIOSTipsNotificationsEnabled()
                 ? l10n_util::GetNSString(
                       IDS_IOS_SET_UP_LIST_NOTIFICATIONS_DESCRIPTION)
                 : l10n_util::GetNSString(
                       IDS_IOS_SET_UP_LIST_CONTENT_NOTIFICATION_DESCRIPTION);
    case SetUpListItemType::kAllSet:
    case SetUpListItemType::kFollow:
      NOTREACHED();
  }
}

// Handles button tap.
- (void)tryTapped {
  [self.tapDelegate didSelectSetUpListItem:_data.type];
}

#pragma mark - UIAccessibility

- (BOOL)accessibilityActivate {
  if (_data.complete) {
    return NO;
  }
  [self tryTapped];
  return YES;
}

@end