chromium/ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/inactive_tabs_user_education_coordinator.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/tab_switcher/tab_grid/inactive_tabs/inactive_tabs_user_education_coordinator.h"

#import <CoreGraphics/CoreGraphics.h>

#import "base/i18n/message_formatter.h"
#import "base/strings/sys_string_conversions.h"
#import "base/time/time.h"
#import "ios/chrome/browser/shared/ui/symbols/symbols.h"
#import "ios/chrome/browser/tabs/model/inactive_tabs/features.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/inactive_tabs/inactive_tabs_constants.h"
#import "ios/chrome/common/ui/colors/semantic_color_names.h"
#import "ios/chrome/common/ui/confirmation_alert/confirmation_alert_action_handler.h"
#import "ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.h"
#import "ios/chrome/grit/ios_strings.h"
#import "ui/base/l10n/l10n_util.h"

namespace {

// Layout constants for the image.
const CGFloat kTileSize = 60;
const CGFloat kTileCornerRadius = 13;
const CGFloat kTileShadowRadius = 20;
const CGFloat kTileShadowOffsetX = 0;
const CGFloat kTileShadowOffsetY = 5;
const CGFloat kTileShadowOpacity = 0.1;
const CGFloat kIconPadding = 12;
const CGFloat kImageTopSpacing = 20;
const CGFloat kImageBottomSpacing = 8;
const CGFloat kSpacing = 1;

// Returns the image to show in the user-education confirmation alert.
UIImage* ConfirmationAlertImage() {
  CGRect tileFrame = CGRectMake(0, 0, kTileSize, kTileSize);
  // Enlarge the frame to account for the drop shadow.
  CGRect frame = CGRectInset(tileFrame, -kTileShadowRadius, -kTileShadowRadius);
  // Recenter the tile frame.
  tileFrame = CGRectOffset(tileFrame, kTileShadowRadius, kTileShadowRadius);

  UIGraphicsImageRendererFormat* format =
      [UIGraphicsImageRendererFormat preferredFormat];
  format.opaque = NO;

  UIGraphicsImageRenderer* renderer =
      [[UIGraphicsImageRenderer alloc] initWithSize:frame.size format:format];

  return [renderer imageWithActions:^(
                       UIGraphicsImageRendererContext* UIContext) {
    CGContextRef context = UIContext.CGContext;

    // Draw the background with a shadow.
    [[UIColor colorNamed:kBlue500Color] setFill];
    UIBezierPath* path =
        [UIBezierPath bezierPathWithRoundedRect:tileFrame
                                   cornerRadius:kTileCornerRadius];
    CGContextSaveGState(context);
    CGColorRef shadowColor =
        [UIColor.blackColor colorWithAlphaComponent:kTileShadowOpacity].CGColor;
    CGContextSetShadowWithColor(
        context, CGSizeMake(kTileShadowOffsetX, kTileShadowOffsetY),
        kTileShadowRadius, shadowColor);
    [path fill];
    CGContextRestoreGState(context);

    // Draw the icon.
    [UIColor.whiteColor setFill];
    UIImage* icon =
        DefaultSymbolTemplateWithPointSize(kSquareOnSquareDashedSymbol, 0);
    if (icon.size.width > icon.size.height) {
      CGFloat ratio = icon.size.height / icon.size.width;
      CGFloat drawingWidth = kTileSize - 2 * kIconPadding;
      CGFloat drawingHeight = drawingWidth * ratio;
      CGFloat verticalPadding = (kTileSize - drawingHeight) / 2;
      [icon drawInRect:CGRectInset(tileFrame, kIconPadding, verticalPadding)];
    } else {
      CGFloat ratio = icon.size.width / icon.size.height;
      CGFloat drawingHeight = kTileSize - 2 * kIconPadding;
      CGFloat drawingWidth = drawingHeight * ratio;
      CGFloat horizontalPadding = (kTileSize - drawingWidth) / 2;
      [icon drawInRect:CGRectInset(tileFrame, horizontalPadding, kIconPadding)];
    }
  }];
}

}  // namespace

@interface InactiveTabsUserEducationCoordinator () <
    ConfirmationAlertActionHandler,
    UIAdaptivePresentationControllerDelegate>
@end

@implementation InactiveTabsUserEducationCoordinator {
  // The confirmation alert showing the user education infos.
  ConfirmationAlertViewController* _confirmationAlert;
}

- (void)start {
  [super start];

  _confirmationAlert = [[ConfirmationAlertViewController alloc] init];
  _confirmationAlert.titleString =
      l10n_util::GetNSString(IDS_IOS_INACTIVE_TABS_USER_EDU_TITLE);
  _confirmationAlert.titleTextStyle = UIFontTextStyleTitle2;
  _confirmationAlert.subtitleString = base::SysUTF16ToNSString(
      base::i18n::MessageFormatter::FormatWithNumberedArgs(
          l10n_util::GetStringUTF16(IDS_IOS_INACTIVE_TABS_USER_EDU_SUBTITLE),
          InactiveTabsTimeThreshold().InDays()));
  _confirmationAlert.primaryActionString =
      l10n_util::GetNSString(IDS_IOS_INACTIVE_TABS_USER_EDU_DONE);
  _confirmationAlert.secondaryActionString =
      l10n_util::GetNSString(IDS_IOS_INACTIVE_TABS_USER_EDU_GO_TO_SETTINGS);
  _confirmationAlert.image = ConfirmationAlertImage();
  _confirmationAlert.imageHasFixedSize = YES;
  _confirmationAlert.customSpacingBeforeImageIfNoNavigationBar =
      kImageTopSpacing;
  _confirmationAlert.customSpacingAfterImage = kImageBottomSpacing;
  _confirmationAlert.customSpacing = kSpacing;
  _confirmationAlert.topAlignedLayout = YES;
  _confirmationAlert.showDismissBarButton = NO;
  _confirmationAlert.actionHandler = self;
  _confirmationAlert.presentationController.delegate = self;
  _confirmationAlert.modalPresentationStyle = UIModalPresentationPageSheet;
  UISheetPresentationController* presentationController =
      _confirmationAlert.sheetPresentationController;
  presentationController.prefersEdgeAttachedInCompactHeight = YES;
  presentationController.detents = @[
    UISheetPresentationControllerDetent.mediumDetent,
    UISheetPresentationControllerDetent.largeDetent
  ];
  presentationController.preferredCornerRadius = 20;
  _confirmationAlert.view.accessibilityIdentifier =
      kInactiveTabsUserEducationAccessibilityIdentifier;

  [self.baseViewController presentViewController:_confirmationAlert
                                        animated:YES
                                      completion:nil];
}

- (void)stop {
  [super stop];
  [_confirmationAlert dismissViewControllerAnimated:YES completion:nil];
}

#pragma mark - ConfirmationAlertActionHandler

- (void)confirmationAlertPrimaryAction {
  [_delegate inactiveTabsUserEducationCoordinatorDidFinish:self];
}

- (void)confirmationAlertSecondaryAction {
  [_delegate inactiveTabsUserEducationCoordinatorDidTapSettingsButton:self];
}

#pragma mark - UIAdaptivePresentationControllerDelegate

- (void)presentationControllerDidDismiss:
    (UIPresentationController*)presentationController {
  [_delegate inactiveTabsUserEducationCoordinatorDidFinish:self];
}

@end