public class InactiveTabsButtonHeader: UICollectionReusableView {
  private enum Dimensions {
    /// The margin at the top of the header.
    static let topMargin: CGFloat = 12
    /// The margin on the other edges of the header.
    static let margin: CGFloat = 16
  }
  /// The state driving the SwiftUI button.
  private let buttonState = InactiveTabsButton.State()
  /// The hosting controller to map to the SwiftUI button.
  private lazy var hostingController = {
    UIHostingController(rootView: InactiveTabsButton(state: buttonState))
  }()
  /// Installs the hosting controller in the parent view controller.
    didSet {
      guard hostingController.parent != parent else { return }
      if let parent {
        parent.addChild(hostingController)
        hostingController.view.backgroundColor = .clear
        hostingController.view.translatesAutoresizingMaskIntoConstraints = false
        addSubview(hostingController.view)
        hostingController.didMove(toParent: parent)
        NSLayoutConstraint.activate([
          hostingController.view.topAnchor.constraint(
            equalTo: topAnchor, constant: Dimensions.topMargin),
          hostingController.view.leadingAnchor.constraint(
            equalTo: leadingAnchor, constant: Dimensions.margin),
          hostingController.view.bottomAnchor.constraint(
            equalTo: bottomAnchor, constant: -Dimensions.margin),
          hostingController.view.trailingAnchor.constraint(
            equalTo: trailingAnchor, constant: -Dimensions.margin),
        ])
      } else {
        hostingController.willMove(toParent: nil)
        hostingController.view.removeFromSuperview()
        hostingController.removeFromParent()
      }
    }
  }
  /// The callback when the Inactive Tabs button is pressed.
    buttonState.count = count
  }
}


import SwiftUI
import ios_chrome_common_ui_colors_swift
private let kPromptInnerPaddingHorizontal: CGFloat = 12
private let kPromptInnerPaddingVertical: CGFloat = 8
private let kPromptOuterPaddingHorizontal: CGFloat = 6
private let kPromptOuterPaddingVertical: CGFloat = 8
private let kPromptCornerRadius: CGFloat = 20
private let kTextVerticalSpacing: CGFloat = 12
private let kTextMinimumScaleFactor: CGFloat = 0.5
private let kSeparatorHeight: CGFloat = 1
// The view object for "Bring Android Tabs" bottom message prompt.
struct BringAndroidTabsPromptBottomMessageView: View {
  // Number of tabs brought from Android.
  let tabsCount: Int
  // Provider object for the view.
  weak var provider: BringAndroidTabsPromptBottomMessageProvider?
  var body: some View {
    HStack(alignment: .top) {
      Image(systemName: kTabsSymbol)
        .imageScale(.large)
        .padding(.top, kTextVerticalSpacing)
      VStack(alignment: .leading, spacing: kTextVerticalSpacing) {
        HStack(alignment: .top) {
          VStack(
            alignment: .leading,
            spacing: kTextVerticalSpacing - kPromptInnerPaddingVertical
          ) {
            Text(
              L10nUtils.pluralString(
                messageId: IDS_IOS_BRING_ANDROID_TABS_PROMPT_TITLE,
                number: self.tabsCount)
            )
            .font(.body)
            .minimumScaleFactor(kTextMinimumScaleFactor)
            Text(
              L10nUtils.pluralString(
                messageId: IDS_IOS_BRING_ANDROID_TABS_PROMPT_SUBTITLE,
                number: self.tabsCount)
            )
            .font(.footnote)
            .foregroundColor(.textSecondary)
            .minimumScaleFactor(kTextMinimumScaleFactor)
          }
          .padding(.top, kTextVerticalSpacing - kPromptInnerPaddingVertical)
          Spacer()
          Button(action: self.close) {
            Image(systemName: kXMarkCircleFillSymbol)
              .foregroundColor(.textQuaternary)
          }
          .accessibilityIdentifier(
            kBringAndroidTabsPromptBottomMessageCloseButtonAXId)
        }
        .padding(0)
        Divider().overlay(Color.separator).frame(height: kSeparatorHeight)
        Button(action: self.review) {
          HStack {
            Text(
              L10nUtils.pluralString(
                messageId:
                  IDS_IOS_BRING_ANDROID_TABS_PROMPT_REVIEW_TABS_BUTTON_BOTTOM_MESSAGE,
                number: self.tabsCount)
            )
            .minimumScaleFactor(kTextMinimumScaleFactor)
            Spacer()
            Image(systemName: kChevronForwardSymbol)
              .foregroundColor(.textSecondary)
          }
        }
        .foregroundColor(.chromeBlue)
        .accessibilityIdentifier(
          kBringAndroidTabsPromptBottomMessageReviewButtonAXId)
      }
      .padding(.bottom, kTextVerticalSpacing)
    }
    .padding(.horizontal, kPromptInnerPaddingHorizontal)
    .padding(.vertical, kPromptInnerPaddingVertical)
    .background(Color.primaryBackground)
    .clipShape(RoundedRectangle(cornerRadius: kPromptCornerRadius))
    .environment(\.colorScheme, .dark)
    .onAppear { self.onAppear() }
    .padding(.horizontal, kPromptOuterPaddingHorizontal)
    .padding(.vertical, kPromptOuterPaddingVertical)
  }
  // MARK: - Action handlers.
  // Invoked when the view is displayed.
  func onAppear() {
    self.provider?.delegate?.bringAndroidTabsPromptViewControllerDidShow()
  }
  // Review button action handler.
  func review() {
    self.provider?.delegate?
      .bringAndroidTabsPromptViewControllerDidTapReviewButton()
    self.provider?.commandHandler?.reviewAllBringAndroidTabs()
  }
  // Close button action handler.
  func close() {
    self.provider?.delegate?.bringAndroidTabsPromptViewControllerDidDismiss(
      swiped: false)
    self.provider?.commandHandler?.dismissBringAndroidTabsPrompt()
  }
}


class BringAndroidTabsPromptBottomMessageProvider: NSObject {
  // Delegate to handle user actions and update browser models accordingly.
  weak var delegate: BringAndroidTabsPromptViewControllerDelegate?
  // Command handler to continue Bring Android Tabs user journey based on
  // command invocation.
  weak var commandHandler: BringAndroidTabsCommands?
  // Number of active tabs from Android.
  let tabsCount: Int
  init(tabsCount: Int) {
    self.tabsCount = tabsCount
  }
  // View controller that manages this view. Should be added to the view
  // hierarchy when the view is displayed or removed.
  lazy var viewController: UIViewController = {
    var viewController = UIHostingController(
      rootView: BringAndroidTabsPromptBottomMessageView(
        tabsCount: self.tabsCount, provider: self))
    // Workaround of SwiftUI/UIKit interoperality limitation that the topmost
    // view always have an opaque background.
    viewController.view.backgroundColor = UIColor.clear
    return viewController
  }()
}


class BringAndroidTabsPromptConfirmationAlertViewController:
  ConfirmationAlertViewController,  // super class
  ConfirmationAlertActionHandler,  // protocol
  UIAdaptivePresentationControllerDelegate
{
  // Delegate to handle user actions.
  weak var delegate: BringAndroidTabsPromptViewControllerDelegate?
  // Command handler to continue Bring Android Tabs user journey base on command
  // invocation.
  weak var commandHandler: BringAndroidTabsCommands?
  // Number of active tabs from Android.
  private let tabsCount: Int
  init(tabsCount: Int) {
    self.tabsCount = tabsCount
  }
  override func viewDidLoad() {
    // Configure confirmation alert properties. These properties need to be set
    // before calling the confirmation alert's `viewDidLoad`.
    self.image = UIImage(named: "bring_android_tabs_icon")
    self.imageHasFixedSize = true
    self.customSpacingBeforeImageIfNoNavigationBar = kSpacingBeforeImage
    self.customSpacingAfterImage = kSpacingAfterImage
    self.helpButtonAvailable = false
    self.showDismissBarButton = false
    self.titleString = L10nUtils.pluralString(
      messageId: IDS_IOS_BRING_ANDROID_TABS_PROMPT_TITLE,
      number: self.tabsCount)
    self.titleTextStyle = .title2
    self.subtitleString = L10nUtils.pluralString(
      messageId: IDS_IOS_BRING_ANDROID_TABS_PROMPT_SUBTITLE,
      number: self.tabsCount)
    self.primaryActionString = L10nUtils.pluralString(
      messageId: IDS_IOS_BRING_ANDROID_TABS_PROMPT_OPEN_TABS_BUTTON,
      number: self.tabsCount)
    self.secondaryActionString = L10nUtils.pluralString(
      messageId: IDS_IOS_BRING_ANDROID_TABS_CANCEL_BUTTON,
      number: self.tabsCount)
    self.tertiaryActionString = L10nUtils.pluralString(
      messageId:
        IDS_IOS_BRING_ANDROID_TABS_PROMPT_REVIEW_TABS_BUTTON_CONFIRMATION_ALERT,
      number: self.tabsCount)
    super.viewDidLoad()
    // Configure properties specific to the "Bring Android Tabs" prompt.
    self.actionHandler = self
    self.presentationController?.delegate = self
    self.overrideUserInterfaceStyle = .dark
    self.view.accessibilityIdentifier =
      kBringAndroidTabsPromptConfirmationAlertAXId
  }
  override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    self.delegate?.bringAndroidTabsPromptViewControllerDidShow()
  }
  // MARK: - UIAdaptivePresentationControllerDelegate
  func presentationControllerDidDismiss(_ controller: UIPresentationController) {
    self.delegate?.bringAndroidTabsPromptViewControllerDidDismiss(swiped: true)
    self.commandHandler?.dismissBringAndroidTabsPrompt()
  }
  // MARK: - ConfirmationAlertActionHandler
  func confirmationAlertPrimaryAction() {
    self.delegate?.bringAndroidTabsPromptViewControllerDidTapOpenAllButton()
    self.commandHandler?.dismissBringAndroidTabsPrompt()
  }
  func confirmationAlertSecondaryAction() {
    self.delegate?.bringAndroidTabsPromptViewControllerDidDismiss(swiped: false)
    self.commandHandler?.dismissBringAndroidTabsPrompt()
  }
  func confirmationAlertTertiaryAction() {
    self.delegate?.bringAndroidTabsPromptViewControllerDidTapReviewButton()
    self.commandHandler?.reviewAllBringAndroidTabs()
  }
}


protocol SafetyCheckTableViewControllerPresentationDelegate: AnyObject {
  // Called when the view controller is removed from its parent.
  func safetyCheckTableViewControllerDidRemove(_ controller: SafetyCheckTableViewController)
}
// Workaround to start the section identifier enum with the base value that's in
// shared ObjC code. Swift doesn't allow named constants in this context.
// Need to remember to use |settingsRawValue| instead of |rawValue|.
protocol SettingsEnum: RawRepresentable where RawValue == Int {}
extension SettingsEnum {
  var settingsRawValue: Int {
    // TODO(crbug.com/1285900): This fails on offical builders when trying
    // to use the ObjC constant. Hard-code it as a workaround.
    return self.rawValue + 10  // kSectionIdentifierEnumZero
  }
}
  // MARK: Private enums
  enum SettingsIdentifier: Int, SettingsEnum {
    case checkTypes
    case checkStart
  }
  // MARK: Private members
  // Current state of array of items that form the safety check.
  private var checkTypesItems: [TableViewItem]? {
    didSet {
      reloadData()
    }
  }
  // Header for the safety check page.
  private var safetyCheckHeaderItem: TableViewLinkHeaderFooterItem? {
    didSet {
      reloadData()
    }
  }
  // Current display state of the check start item.
  private var checkStartItem: TableViewItem? {
    didSet {
      reloadData()
    }
  }
  // Footer with timestamp for the safety check page.
  private var safetyCheckFooterItem: TableViewLinkHeaderFooterItem? {
    didSet {
      reloadData()
    }
  }
  override func viewDidLoad() {
    super.viewDidLoad()
    self.tableView.accessibilityIdentifier = SafetyCheckTableViewController.accessibilityIdentifier
    self.title = L10nUtils.string(messageId: IDS_OPTIONS_ADVANCED_SECTION_TITLE_SAFETY_CHECK)
  }
  // MARK: SafetyCheckConsumer
  func setCheck(_ items: [TableViewItem]) {
    checkTypesItems = items
  }
  func setSafetyCheckHeaderItem(_ item: TableViewLinkHeaderFooterItem!) {
    safetyCheckHeaderItem = item
  }
  func setCheckStart(_ item: TableViewItem!) {
    checkStartItem = item
  }
  func setTimestampFooterItem(_ item: TableViewLinkHeaderFooterItem!) {
    safetyCheckFooterItem = item
  }
  // MARK: ChromeTableViewController
  override func loadModel() {
    super.loadModel()
    if let items = self.checkTypesItems {
      let checkTypes = SettingsIdentifier.checkTypes.settingsRawValue
      if items.count != 0 {
        self.tableViewModel.addSection(withIdentifier: checkTypes)
        for item in items {
          self.tableViewModel.add(item, toSectionWithIdentifier: checkTypes)
        }
      }
      if let item = self.safetyCheckHeaderItem {
        self.tableViewModel.setHeader(item, forSectionWithIdentifier: checkTypes)
      }
    }
    if let item = self.checkStartItem {
      let checkStart = SettingsIdentifier.checkStart.settingsRawValue
      self.tableViewModel.addSection(withIdentifier: checkStart)
      self.tableViewModel.add(item, toSectionWithIdentifier: checkStart)
      if let footerItem = self.safetyCheckFooterItem {
        self.tableViewModel.setFooter(footerItem, forSectionWithIdentifier: checkStart)
      }
    }
  }
  // MARK: UIViewController
  override func didMove(toParent parent: UIViewController?) {
    super.didMove(toParent: parent)
    if parent == nil {
      self.presentationDelegate?.safetyCheckTableViewControllerDidRemove(self)
    }
  }
  // MARK: UITableViewDelegate
  override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    super.tableView(tableView, didSelectRowAt: indexPath)
    let item = self.tableViewModel.item(at: indexPath)
    self.serviceDelegate?.didSelect(item)
    tableView.deselectRow(at: indexPath, animated: false)
  }
  override func tableView(
    _ tableView: UITableView,
    shouldHighlightRowAt indexPath: IndexPath
  ) -> Bool {
    let item = self.tableViewModel.item(at: indexPath)
    return self.serviceDelegate?.isItemClickable(item) ?? false
  }
  // MARK: UITabelViewDataSource
  override func tableView(
    _ tableView: UITableView,
    cellForRowAt indexPath: IndexPath
  ) -> UITableViewCell {
    let cell = super.tableView(tableView, cellForRowAt: indexPath)
    let tableItem = self.tableViewModel.item(at: indexPath)
    if let delegate = self.serviceDelegate,
      let item = tableItem,
      delegate.isItemWithErrorInfo(item),
      let settingsCheckCell = cell as? SettingsCheckCell
    {
      settingsCheckCell.infoButton.tag = item.type
      settingsCheckCell.infoButton.addTarget(
        self,
        action: #selector(didTapErrorInfoButton),
        for: .touchUpInside)
    }
    return cell
  }
  // MARK: Private
  // Called when user tapped on the information button of an item. Shows popover with detailed
  // description of an error if needed.
    self.serviceDelegate?.infoButtonWasTapped(sender, usingItemType: sender.tag)
  }
}


class OverflowMenuHostingController<Content>: UIHostingController<Content> where Content: View {
  // This should be the width of the share sheet in compact height environments.
  let compactHeightSheetWidth: CGFloat = 568
  let uiConfiguration: OverflowMenuUIConfiguration
  init(rootView: Content, uiConfiguration: OverflowMenuUIConfiguration) {
    self.uiConfiguration = uiConfiguration
    super.init(rootView: rootView)
  }
  required init(coder aDecoder: NSCoder) {
    fatalError("Not using storyboards")
  }
  var compactHeightPreferredContentSize: CGSize {
    return CGSize(
      width: compactHeightSheetWidth, height: presentingViewController?.view.bounds.size.height ?? 0
    )
  }
  override func viewDidLoad() {
    super.viewDidLoad()
    // Only set the preferredContentSize in height == compact because otherwise
    // it overrides the default size of the menu on iPad.
    preferredContentSize =
      traitCollection.verticalSizeClass == .compact ? compactHeightPreferredContentSize : .zero
    uiConfiguration.presentingViewControllerHorizontalSizeClass =
      presentingViewController?.traitCollection.horizontalSizeClass == .regular
      ? .regular : .compact
    uiConfiguration.presentingViewControllerVerticalSizeClass =
      presentingViewController?.traitCollection.verticalSizeClass == .regular ? .regular : .compact
  }
  override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    // Only set the preferredContentSize in height == compact because otherwise
    // it overrides the default size of the menu on iPad.
    preferredContentSize =
      traitCollection.verticalSizeClass == .compact ? compactHeightPreferredContentSize : .zero
    uiConfiguration.presentingViewControllerHorizontalSizeClass =
      presentingViewController?.traitCollection.horizontalSizeClass == .regular
      ? .regular : .compact
    uiConfiguration.presentingViewControllerVerticalSizeClass =
      presentingViewController?.traitCollection.verticalSizeClass == .regular ? .regular : .compact
  }
}


  weak var metricsHandler: PopupMenuMetricsHandler?
  var body: some View {
    Section(
      content: {
        ForEach(actionGroup.actions) { action in
          OverflowMenuActionRow(action: action, metricsHandler: metricsHandler)
        }
      },
      header: {
        Spacer()
          .frame(height: Dimensions.headerFooterHeight)
          .listRowInsets(EdgeInsets())
          .accessibilityHidden(true)
      },
      footer: {
        if let actionFooter = actionGroup.footer {
          OverflowMenuFooterRow(footer: actionFooter)
        } else {
          Spacer()
            // Use `leastNonzeroMagnitude` to remove the footer. Otherwise,
            // it uses a default height.
            .frame(height: CGFloat.leastNonzeroMagnitude)
            .listRowInsets(EdgeInsets())
            .accessibilityHidden(true)
        }
      })
  }
}


struct OverflowMenuDestinationButton: ButtonStyle {
  enum Dimensions {
    static let cornerRadius: CGFloat = 13
    /// The padding on either side of the text in the vertical layout,
    /// separating it from the next view.
    static let verticalLayoutTextPadding: CGFloat = 3
    /// The padding on either side of the view in the horizontal layout,
    /// separating it from the next view.
    static let horizontalLayoutViewPadding: CGFloat = 16
    /// The padding around the icon and inside the background in horizontal
    /// layout.
    static let horizontalLayoutIconPadding: CGFloat = 3
    /// The spacing between the icon and the text in horizontal layout.
    static let horizontalLayoutIconSpacing: CGFloat = 14
    /// The image width, which controls the width of the overall view.
    static let imageWidth: CGFloat = 54
    /// The size of the Symbol in the icon.
    static let iconSymbolSize: CGFloat = 26
    /// The width of the icon, used for positioning the unread badge over the
    /// corner.
    static let iconWidth: CGFloat = 30
    /// The width of the badge circle.
    static let badgeWidth: CGFloat = 10
    /// The width of the new label badge.
    static let newLabelBadgeWidth: CGFloat = 20
  }
  /// The destination for this view.
  var destination: OverflowMenuDestination
  /// The layout parameters for this view.
  var layoutParameters: OverflowMenuDestinationView.LayoutParameters
  weak var metricsHandler: PopupMenuMetricsHandler?
  func makeBody(configuration: Configuration) -> some View {
    let destinationWidth = OverflowMenuDestinationButton.destinationWidth(
      forLayoutParameters: layoutParameters)
    Group {
      switch layoutParameters {
      case .vertical:
        VStack {
          icon(configuration: configuration)
          text
        }
        .frame(width: destinationWidth)
      case .horizontal:
        HStack {
          icon(configuration: configuration)
          Spacer().frame(width: Dimensions.horizontalLayoutIconSpacing)
          text
        }
        .frame(width: destinationWidth, alignment: .leading)
        // In horizontal layout, the item itself has leading and trailing
        // padding.
        .padding([.leading, .trailing], Dimensions.horizontalLayoutViewPadding)
      }
    }
    .contentShape(Rectangle())
  }
  /// Background color for the icon.
  func backgroundColor(configuration: Configuration) -> Color {
    return configuration.isPressed ? Color(.systemGray4) : .groupedSecondaryBackground
  }
  /// View representing the background of the icon.
  func iconBackground(configuration: Configuration) -> some View {
    RoundedRectangle(cornerRadius: Dimensions.cornerRadius)
      .foregroundColor(backgroundColor(configuration: configuration))
  }
  /// Icon for the destination.
  func icon(configuration: Configuration) -> some View {
    let interiorPadding: CGFloat
    let spacing: CGFloat
    switch layoutParameters {
    case .vertical(let iconSpacing, let iconPadding):
      spacing = iconSpacing
      interiorPadding = iconPadding
    case .horizontal:
      spacing = 0
      interiorPadding = Dimensions.horizontalLayoutIconPadding
    }
    let image =
      (destination.systemSymbol
      ? Image(systemName: destination.symbolName) : Image(destination.symbolName)).renderingMode(
        .template)
    return iconBuilder(
      configuration: configuration, spacing: spacing, interiorPadding: interiorPadding, image: image
    )
  }
  var newBadgeOffsetX: CGFloat {
    return Dimensions.iconWidth - (Dimensions.newLabelBadgeWidth - 10)
  }
  var newBadgeOffsetY: CGFloat {
    return -Dimensions.iconWidth + (Dimensions.newLabelBadgeWidth - 10)
  }
  var circleBadge: some View {
    return Circle()
      .frame(width: Dimensions.badgeWidth, height: Dimensions.badgeWidth)
      .offset(
        x: Dimensions.iconWidth - (Dimensions.badgeWidth / 2),
        y: -Dimensions.iconWidth + (Dimensions.badgeWidth / 2))
  }
  /// Build the image to be displayed, based on the configuration of the item.
  /// TODO(crbug.com/1315544): Remove this once only the symbols are present.
  func iconBuilder(
    configuration: Configuration, spacing: CGFloat, interiorPadding: CGFloat, image: Image
  ) -> some View {
    let configuredImage =
      image
      .overlay {
        if destination.badge == .error {
          circleBadge.foregroundColor(.red500)
        } else if destination.badge == .promo {
          circleBadge.foregroundColor(.blue600)
        } else if destination.badge == .new {
          Image(systemName: "seal.fill")
            .resizable()
            .foregroundColor(.blue600)
            .frame(width: Dimensions.newLabelBadgeWidth, height: Dimensions.newLabelBadgeWidth)
            .offset(x: newBadgeOffsetX, y: newBadgeOffsetY)
            .overlay {
              if let newLabelString = L10nUtils.stringWithFixup(
                messageId: IDS_IOS_NEW_LABEL_FEATURE_BADGE)
              {
                Text(newLabelString)
                  .font(.system(size: 10, weight: .bold, design: .rounded))
                  .offset(x: newBadgeOffsetX, y: newBadgeOffsetY)
                  .scaledToFit()
                  .foregroundColor(.primaryBackground)
              }
            }
        }
      }
      .frame(width: Dimensions.imageWidth, height: Dimensions.imageWidth)
      .padding(interiorPadding)
      .background(iconBackground(configuration: configuration))
      .padding([.leading, .trailing], spacing)
      // Without explicitly removing the image from accessibility,
      // VoiceOver will occasionally read out icons it thinks it can
      // recognize.
      .accessibilityHidden(true)
    configuredImage
      .foregroundColor(.blue600).imageScale(.medium).font(
        Font.system(size: Dimensions.iconSymbolSize, weight: .medium))
  }
  /// Text view for the destination.
  var text: some View {
    // Only the vertical layout has extra spacing around the text
    let textSpacing: CGFloat
    let maximumLines: Int?
    switch layoutParameters {
    case .vertical:
      textSpacing = Dimensions.verticalLayoutTextPadding
      maximumLines = nil
    case .horizontal:
      textSpacing = 0
      maximumLines = 1
    }
    return Text(destination.name)
      .font(.caption2)
      .padding([.leading, .trailing], textSpacing)
      .multilineTextAlignment(.center)
      .lineLimit(maximumLines)
  }
  static public func destinationWidth(
    forLayoutParameters layoutParameters: OverflowMenuDestinationView.LayoutParameters
  ) -> CGFloat {
    switch layoutParameters {
    case .vertical(let iconSpacing, let iconPadding):
      return Dimensions.imageWidth + 2 * iconSpacing + 2 * iconPadding
    case .horizontal(let itemWidth):
      return itemWidth
    }
  }
}
/// A view displaying a single destination.
struct OverflowMenuDestinationView: View {
  /// Parameters providing any necessary data to layout the view.
  enum LayoutParameters {
    /// The destination has an icon on top and text below.
    /// There is `iconSpacing` to either side of the icon, and `iconPadding`
    /// around the icon and inside the background.
    case vertical(iconSpacing: CGFloat, iconPadding: CGFloat)
    /// The destination has an icon on the left and text on the right. Here
    /// the view will have a fixed overall `itemWidth`.
    case horizontal(itemWidth: CGFloat)
  }
  enum AccessibilityIdentifier {
    /// The addition to the `accessibilityIdentfier` for this element if it
    /// has an error badge.
    static let errorBadge = "errorBadge"
    /// The addition to the `accessibilityIdentfier` for this element if it
    /// has a promo badge.
    static let promoBadge = "promoBadge"
    /// The addition to the `accessibilityIdentfier` for this element if it
    /// has a "New" badge.
    static let newBadge = "newBadge"
  }
  /// The destination for this view.
  var destination: OverflowMenuDestination
  /// The layout parameters for this view.
  var layoutParameters: LayoutParameters
  weak var metricsHandler: PopupMenuMetricsHandler?
  var body: some View {
    Button(
      action: {
        metricsHandler?.popupMenuTookAction()
        destination.handler()
      },
      label: {
        EmptyView()
      }
    )
    .accessibilityIdentifier(accessibilityIdentifier)
    .accessibilityLabel(Text(accessibilityLabel))
    .buttonStyle(
      OverflowMenuDestinationButton(destination: destination, layoutParameters: layoutParameters))
  }
  var accessibilityLabel: String {
    return [
      destination.name,
      destination.badge == .error
        ? L10nUtils.stringWithFixup(
          messageId: IDS_IOS_ITEM_ACCOUNT_ERROR_BADGE_ACCESSIBILITY_HINT) : nil,
      destination.badge == .promo
        ? L10nUtils.stringWithFixup(messageId: IDS_IOS_NEW_ITEM_ACCESSIBILITY_HINT) : nil,
      destination.badge == .new
        ? L10nUtils.stringWithFixup(messageId: IDS_IOS_TOOLS_MENU_CELL_NEW_FEATURE_BADGE) : nil,
    ].compactMap { $0 }.joined(separator: ", ")
  }
  var accessibilityIdentifier: String {
    return [
      destination.accessibilityIdentifier,
      destination.badge == .error ? AccessibilityIdentifier.errorBadge : nil,
      destination.badge == .promo ? AccessibilityIdentifier.promoBadge : nil,
      destination.badge == .new ? AccessibilityIdentifier.newBadge : nil,
    ].compactMap { $0 }.joined(separator: "-")
  }
}


  /// The size of the symbols.
  static let symbolSize: CGFloat = 18
  static let symbolImageFrameLength: CGFloat = 30
  static let symbolImagePadding: CGFloat = -4
  /// The size of the "N" IPH icon.
  static let newLabelIconWidth: CGFloat = 15
  weak var metricsHandler: PopupMenuMetricsHandler?
  var body: some View {
    Button(
      action: {
        metricsHandler?.popupMenuTookAction()
        action.handler()
      },
      label: {
        HStack {
          Text(action.name).lineLimit(1)
          if action.displayNewLabelIcon {
            newLabelIconView()
              .accessibilityIdentifier("overflowRowIPHBadgeIdentifier")
          }
          Spacer()
          imageBuilder().frame(
            width: OverflowMenuActionRow.symbolImageFrameLength,
            height: OverflowMenuActionRow.symbolImageFrameLength, alignment: .center
          )
          // Without explicitly removing the image from accessibility,
          // VoiceOver will occasionally read out icons it thinks it can
          // recognize.
          .accessibilityHidden(true)
        }
        .contentShape(Rectangle())
      }
    ).padding([.trailing], OverflowMenuActionRow.symbolImagePadding)
      .accessibilityIdentifier(action.accessibilityIdentifier)
      .disabled(!action.enabled || action.enterpriseDisabled)
      .accentColor(.textPrimary)
      .listRowSeparatorTint(.overflowMenuSeparator)
  }
  /// Build the image to be displayed, based on the configuration of the item.
  /// TODO(crbug.com/1315544): Remove this once only the symbols are present.
  func imageBuilder() -> some View {
    actionSymbol().font(Font.system(size: OverflowMenuActionRow.symbolSize, weight: .medium))
      .imageScale(
        .medium)
  }
  func actionSymbol() -> Image {
    let symbol =
      action.systemSymbol ? Image(systemName: action.symbolName) : Image(action.symbolName)
    if action.monochromeSymbol {
      return symbol.symbolRenderingMode(.monochrome)
    }
    return symbol
  }
  // Returns the "N" IPH icon view.
  func newLabelIconView() -> some View {
    return Image(systemName: "seal.fill")
      .resizable()
      .foregroundColor(.blue600)
      .frame(
        width: OverflowMenuActionRow.newLabelIconWidth,
        height: OverflowMenuActionRow.newLabelIconWidth
      )
      .overlay {
        if let newLabelString = L10nUtils.stringWithFixup(
          messageId: IDS_IOS_NEW_LABEL_FEATURE_BADGE)
        {
          Text(newLabelString)
            .font(.system(size: 10, weight: .bold, design: .rounded))
            .scaledToFit()
            .foregroundColor(.primaryBackground)
        }
      }
  }
}


import SwiftUI
extension Color {
  static var overflowMenuSeparator: Color {
    let uiColor = UIColor { traitCollection in
      let color =
        traitCollection.userInterfaceStyle == .dark
        ? UIColor(named: kTertiaryBackgroundColor) : UIColor(named: kGrey200Color)
      return color ?? .separator
    }
    if #available(iOS 15, *) {
      return Color(uiColor: uiColor)
    } else {
      return Color(uiColor)
    }
  }
}


  public static func makeViewController(
    withModel model: OverflowMenuModel,
    uiConfiguration: OverflowMenuUIConfiguration,
    metricsHandler: PopupMenuMetricsHandler
  ) -> UIViewController {
    return OverflowMenuHostingController(
      rootView: OverflowMenuView(
        model: model, uiConfiguration: uiConfiguration, metricsHandler: metricsHandler),
      uiConfiguration: uiConfiguration)
  }
}


    // Whether the destination should show an error badge.
    case error
    // Whether the destination should show a promo badge.
    case promo
    // Whether the destination should show a "New" badge
    // indicating a new destination.
    case new
    case none
  }
  public var badge: BadgeType = .none
  /// The uniquely-identifying overflow_menu::Destination of the destination.
  public var destination: Int = 0
}


  ) {
    self.link = link
    self.image = Image(uiImage: image)
    super.init(
      name: name, symbolName: "", systemSymbol: true, monochromeSymbol: true,
      accessibilityIdentifier: accessibilityIdentifier,
      enterpriseDisabled: false, displayNewLabelIcon: false,
      handler: handler)
  }
}


  /// The destinations for the overflow menu.
  public var destinations: [OverflowMenuDestination]
  /// The action groups for the overflow menu.
  public var actionGroups: [OverflowMenuActionGroup]
  public init(
    destinations: [OverflowMenuDestination],
    actionGroups: [OverflowMenuActionGroup]
  ) {
    self.destinations = destinations
    self.actionGroups = actionGroups
  }
}


  static public func numDestinationsVisibleWithoutHorizontalScrolling(
    forScreenWidth width: CGFloat, forContentSizeCategory sizeCategory: UIContentSizeCategory
  ) -> CGFloat {
    let contentSizeCategory = ContentSizeCategory(sizeCategory) ?? .medium
    return OverflowMenuDestinationList.numDestinationsVisibleWithoutHorizontalScrolling(
      forScreenWidth: width, forSizeCategory: contentSizeCategory)
  }
  public init(
    presentingViewControllerHorizontalSizeClass: UIUserInterfaceSizeClass,
    presentingViewControllerVerticalSizeClass: UIUserInterfaceSizeClass
  ) {
    self.presentingViewControllerHorizontalSizeClass =
      UserInterfaceSizeClass(presentingViewControllerHorizontalSizeClass) ?? .compact
    self.presentingViewControllerVerticalSizeClass =
      UserInterfaceSizeClass(presentingViewControllerVerticalSizeClass) ?? .compact
  }
}


struct OverflowMenuActionList: View {
  enum Constants {
    // The minimum row height for any row in the list.
    static let minimumRowHeight: CGFloat = 48
  }
  /// The list of action groups for this view.
  var actionGroups: [OverflowMenuActionGroup]
  /// The metrics handler to alert when the user takes metrics actions.
  weak var metricsHandler: PopupMenuMetricsHandler?
  var body: some View {
    List {
      ForEach(actionGroups) { actionGroup in
        OverflowMenuActionSection(actionGroup: actionGroup, metricsHandler: metricsHandler)
      }
    }
    .simultaneousGesture(
      DragGesture().onChanged({ _ in
        metricsHandler?.popupMenuScrolledVertically()
      })
    )
    .accessibilityIdentifier(kPopupMenuToolsMenuActionListId)
    .listStyle(InsetGroupedListStyle())
    // Allow sections to have very small headers controlling section spacing.
    .environment(\.defaultMinListHeaderHeight, 0)
    .environment(\.defaultMinListRowHeight, Constants.minimumRowHeight)
  }
}
/// Calls `onScroll` when the user performs a drag gesture over the content of the list.
struct ListScrollDetectionModifier: ViewModifier {
  let onScroll: () -> Void
  func body(content: Content) -> some View {
    content
      // For some reason, without this, user interaction is not forwarded to the list.
      .onTapGesture(perform: {})
      // Long press gestures are dismissed and `onPressingChanged` called with
      // `pressing` equal to `false` when the user performs a drag gesture
      // over the content, hence why this works. `DragGesture` cannot be used
      // here, even with a `simultaneousGesture` modifier, because it prevents
      // swipe-to-delete from correctly triggering within the list.
      .onLongPressGesture(
        perform: {},
        onPressingChanged: { pressing in
          if !pressing {
            onScroll()
          }
        })
  }
}


  /// Whether the action is disabled by enterprise policy.
  ) {
    self.name = name
    self.symbolName = symbolName
    self.systemSymbol = systemSymbol
    self.monochromeSymbol = monochromeSymbol
    self.accessibilityIdentifier = accessibilityIdentifier
    self.enterpriseDisabled = enterpriseDisabled
    self.displayNewLabelIcon = displayNewLabelIcon
    self.handler = handler
  }
}
// MARK: - Identifiable
extension OverflowMenuItem: Identifiable {
  public var id: String {
    return name
  }
}


struct OverflowMenuDestinationList: View {
  enum Constants {
    /// Padding breakpoints for each width. The ranges should be inclusive of
    /// the larger number. That is, a width of 320 should fall in the
    /// `(230, 320]` bucket.
    static let widthBreakpoints: [CGFloat] = [
      180, 230, 320, 400, 470, 560, 650,
    ]
    /// Array of the lower end of each breakpoint range.
    static let lowerWidthBreakpoints = [nil] + widthBreakpoints
    /// Array of the higher end of each breakpoint range.
    static let upperWidthBreakpoints = widthBreakpoints + [nil]
    /// Leading space on the first icon.
    static let iconInitialSpace: CGFloat = 16
    /// Range of spacing around icons; varies based on view width.
    static let iconSpacingRange: ClosedRange<CGFloat> = 9...13
    /// Range of icon paddings; varies based on view width.
    static let iconPaddingRange: ClosedRange<CGFloat> = 0...3
    /// When the dynamic text size is large, the width of each item is the
    /// screen width minus a fixed space.
    static let largeTextSizeSpace: CGFloat = 120
    /// Space above the list pushing them down from the grabber.
    static let topMargin: CGFloat = 20
    /// The name for the coordinate space of the scroll view, so children can
    /// find their positioning in the scroll view.
    static let coordinateSpaceName = "destinations"
  }
  /// `PreferenceKey` to track the leading offset of the scroll view.
  struct ScrollViewLeadingOffset: PreferenceKey {
    static var defaultValue: CGFloat = .greatestFiniteMagnitude
    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
      value = min(value, nextValue())
    }
  }
  /// The current dynamic type size.
  var body: some View {
    VStack {
      Spacer(minLength: Constants.topMargin)
      GeometryReader { geometry in
        scrollView(in: geometry)
          .coordinateSpace(name: Constants.coordinateSpaceName)
          .accessibilityIdentifier(kPopupMenuToolsMenuTableViewId)
      }
    }
    .background(
      Color("destination_highlight_color").opacity(uiConfiguration.highlightDestinationsRow ? 1 : 0)
    )
    .animation(
      .linear(duration: kMaterialDuration3), value: uiConfiguration.highlightDestinationsRow
    )
    .onPreferenceChange(ScrollViewLeadingOffset.self) { newOffset in
      // Only alert the handler if scroll tracking has started.
      if let listOffset = listOffset,
        newOffset != listOffset
      {
        metricsHandler?.popupMenuScrolledHorizontally()
      }
      // Only update the offset if scroll tracking has started or the newOffset
      // is approximately 0 (this starts scroll tracking). In RTL mode, the
      // offset is not exactly 0, so a strict comparison won't work.
      if listOffset != nil || (listOffset == nil && abs(newOffset) < 1e-9) {
        listOffset = newOffset
      }
    }
  }
  private func scrollView(in geometry: GeometryProxy) -> some View {
    ScrollViewReader { proxy in
      ScrollView(.horizontal, showsIndicators: false) {
        let spacing = OverflowMenuDestinationList.destinationSpacing(
          forScreenWidth: geometry.size.width)
        let layoutParameters = OverflowMenuDestinationList.layoutParameters(
          forScreenWidth: geometry.size.width, forSizeCategory: sizeCategory)
        let alignment: VerticalAlignment = sizeCategory >= .accessibilityMedium ? .center : .top
        ZStack {
          HStack(alignment: alignment, spacing: 0) {
            // Make sure the space to the first icon is constant, so add extra
            // spacing before the first item.
            Spacer().frame(width: Constants.iconInitialSpace - spacing.iconSpacing)
            ForEach(destinations) { destination in
              OverflowMenuDestinationView(
                destination: destination, layoutParameters: layoutParameters,
                metricsHandler: metricsHandler
              ).id(destination.destination)
            }
          }
          GeometryReader { innerGeometry in
            let frame = innerGeometry.frame(in: .named(Constants.coordinateSpaceName))
            let parentWidth = geometry.size.width
            // When the view is RTL, the offset should be calculated from the
            // right edge.
            let offset = layoutDirection == .leftToRight ? frame.minX : parentWidth - frame.maxX
            Color.clear
              .preference(key: ScrollViewLeadingOffset.self, value: offset)
          }
        }
      }
      .onAppear {
        if layoutDirection == .rightToLeft {
          proxy.scrollTo(destinations.first?.destination)
        }
        uiConfiguration.destinationListScreenFrame = geometry.frame(in: .global)
      }
    }
  }
  /// Finds the lower and upper breakpoint above and below `width`.
  ///
  /// Returns `nil` for either end if `width` is above or below the largest or
  /// smallest breakpoint.
  private static func findBreakpoints(forScreenWidth width: CGFloat) -> (CGFloat?, CGFloat?) {
    // Add extra sentinel values to either end of the breakpoint array.
    let x = zip(
      Constants.lowerWidthBreakpoints, Constants.upperWidthBreakpoints
    )
    // There should only be one item where the provided width is both greater
    // than the lower end and less than the upper end.
    .filter {
      (low, high) in
      // Check if width is above the low value, or default to true if low is
      // nil.
      let aboveLow = low.map { value in width > value } ?? true
      let belowHigh = high.map { value in width <= value } ?? true
      return aboveLow && belowHigh
    }.first
    return x ?? (nil, nil)
  }
  /// Calculates the icon spacing and padding for the given `width`.
  private static func destinationSpacing(forScreenWidth width: CGFloat) -> (
    iconSpacing: CGFloat, iconPadding: CGFloat
  ) {
    let (lowerBreakpoint, upperBreakpoint) = findBreakpoints(
      forScreenWidth: width)
    // If there's no lower breakpoint, `width` is lower than the lowest, so
    // default to the lower bound of the ranges.
    guard let lowerBreakpoint = lowerBreakpoint else {
      return (
        iconSpacing: Constants.iconSpacingRange.lowerBound,
        iconPadding: Constants.iconPaddingRange.lowerBound
      )
    }
    // If there's no upper breakpoint, `width` is higher than the highest, so
    // default to the higher bound of the ranges.
    guard let upperBreakpoint = upperBreakpoint else {
      return (
        iconSpacing: Constants.iconSpacingRange.upperBound,
        iconPadding: Constants.iconPaddingRange.upperBound
      )
    }
    let breakpointRange = lowerBreakpoint...upperBreakpoint
    let iconSpacing = mapNumber(
      width, from: breakpointRange, to: Constants.iconSpacingRange)
    let iconPadding = mapNumber(
      width, from: breakpointRange, to: Constants.iconPaddingRange)
    return (iconSpacing: iconSpacing, iconPadding: iconPadding)
  }
  private static func layoutParameters(
    forScreenWidth width: CGFloat, forSizeCategory sizeCategory: ContentSizeCategory
  ) -> OverflowMenuDestinationView.LayoutParameters {
    let spacing = OverflowMenuDestinationList.destinationSpacing(forScreenWidth: width)
    return sizeCategory >= .accessibilityMedium
      ? .horizontal(itemWidth: width - Constants.largeTextSizeSpace)
      : .vertical(
        iconSpacing: spacing.iconSpacing,
        iconPadding: spacing.iconPadding)
  }
  public static func numDestinationsVisibleWithoutHorizontalScrolling(
    forScreenWidth width: CGFloat, forSizeCategory sizeCategory: ContentSizeCategory
  )
    -> CGFloat
  {
    let layoutParameters = OverflowMenuDestinationList.layoutParameters(
      forScreenWidth: width, forSizeCategory: sizeCategory)
    let destinationWidth = OverflowMenuDestinationButton.destinationWidth(
      forLayoutParameters: layoutParameters)
    return (width / destinationWidth).rounded(.up)
  }
  /// Maps the given `number` from its relative position in `inRange` to its
  /// relative position in `outRange`.
  private static func mapNumber<F: FloatingPoint>(
    _ number: F, from inRange: ClosedRange<F>, to outRange: ClosedRange<F>
  ) -> F {
    let scalingFactor =
      (outRange.upperBound - outRange.lowerBound)
      / (inRange.upperBound - inRange.lowerBound)
    return (number - inRange.lowerBound) * scalingFactor + outRange.lowerBound
  }
}


struct OverflowMenuView: View {
  enum Dimensions {
    static let destinationListHeight: CGFloat = 123
  }
  var model: OverflowMenuModel
  var uiConfiguration: OverflowMenuUIConfiguration
  weak var metricsHandler: PopupMenuMetricsHandler?
  var body: some View {
    VStack(
      alignment: .leading,
      // Leave no spaces above or below Divider, the two other sections will
      // include proper spacing.
      spacing: 0
    ) {
      OverflowMenuDestinationList(
        destinations: model.destinations, metricsHandler: metricsHandler,
        uiConfiguration: uiConfiguration
      ).frame(height: Dimensions.destinationListHeight)
      Divider()
      OverflowMenuActionList(actionGroups: model.actionGroups, metricsHandler: metricsHandler)
      // Add a spacer on iPad to make sure there's space below the list.
      if uiConfiguration.presentingViewControllerHorizontalSizeClass == .regular
        && uiConfiguration.presentingViewControllerVerticalSizeClass == .regular
      {
        Spacer()
      }
    }.background(Color(.systemGroupedBackground).edgesIgnoringSafeArea(.all))
  }
}


  /// The footer at bottom.
  public var footer: OverflowMenuFooter?
  public init(groupName: String, actions: [OverflowMenuAction], footer: OverflowMenuFooter?) {
    self.groupName = groupName
    self.actions = actions
    self.footer = footer
  }
}
// MARK: - Identifiable
extension OverflowMenuActionGroup: Identifiable {
  public var id: String {
    return groupName
  }
}


import SwiftUI
/// A view that displays a footer in the overflow menu.
struct OverflowMenuFooterRow: View {
  enum Dimensions {
    /// Space between elements on the icon line.
    static let iconLineSpacing: CGFloat = 12
    /// The vertical spacing between icon line, label (name) and link.
    static let verticalSpacing: CGFloat = 3
    /// The extra vertical above and below icon line.
    static let iconLineExtraVerticalSpacing: CGFloat = 9
    // The height of the icon line dividers.
    static let iconLineDividerHeight: CGFloat = 1
  }
  /// The footer for this row.
  var body: some View {
    VStack(
      alignment: .center,
      spacing: Dimensions.verticalSpacing
    ) {
      HStack(
        alignment: .center,
        spacing: Dimensions.iconLineSpacing
      ) {
        Rectangle()
          .foregroundColor(.overflowMenuSeparator)
          .frame(height: Dimensions.iconLineDividerHeight)
        footer.image
          .fixedSize()
          .foregroundColor(.grey500)
        Rectangle()
          .foregroundColor(.overflowMenuSeparator)
          .frame(height: Dimensions.iconLineDividerHeight)
      }
      .padding([.top], Dimensions.iconLineExtraVerticalSpacing)
      Text(footer.name)
        .padding([.top], Dimensions.iconLineExtraVerticalSpacing)
        .font(.footnote)
      Text(footer.link)
        .font(.caption2)
        .foregroundColor(.chromeBlue)
        .onTapGesture(perform: footer.handler)
        .accessibilityIdentifier(footer.accessibilityIdentifier)
    }
    // Group all children together so VoiceOver doesn't have to read the two
    // text labels individually.
    .accessibilityElement(children: .combine)
    .accessibilityAction(.default, footer.handler)
  }
}


Color+Chrome

import SwiftUI
// Adds easy SwiftUI access to the Chrome color palette.
extension Color {
  /// The background color.
  public static var background: Color {
    return Color(kBackgroundColor)
  }
  /// The primary text color.
  public static var textPrimary: Color {
    return Color(kTextPrimaryColor)
  }
  /// The secondary text color.
  public static var textSecondary: Color {
    return Color(kTextSecondaryColor)
  }
  /// The tertiary text color.
  public static var textTertiary: Color {
    return Color(kTextTertiaryColor)
  }
  /// The quaternary text color.
  public static var textQuaternary: Color {
    return Color(kTextQuaternaryColor)
  }
  /// The tertiary background color
  public static var tertiaryBackground: Color {
    return Color(kTertiaryBackgroundColor)
  }
  /// The updated tertiary background color
  public static var updatedTertiaryBackground: Color {
    return Color(kUpdatedTertiaryBackgroundColor)
  }
  /// The primary grouped background color.
  public static var groupedPrimaryBackground: Color {
    return Color(kGroupedPrimaryBackgroundColor)
  }
  /// The secondary grouped background color.
  public static var groupedSecondaryBackground: Color {
    return Color(kGroupedSecondaryBackgroundColor)
  }
  /// The primary background color.
  public static var primaryBackground: Color {
    return Color(kPrimaryBackgroundColor)
  }
  /// The secondary background color.
  public static var secondaryBackground: Color {
    return Color(kSecondaryBackgroundColor)
  }
  /// The grey200 color.
  public static var grey200: Color {
    return Color(kGrey200Color)
  }
  /// The grey300 color.
  public static var grey300: Color {
    return Color(kGrey300Color)
  }
  /// The grey500 color
  public static var grey500: Color {
    return Color(kGrey500Color)
  }
  /// The grey700 color
  public static var grey700: Color {
    return Color(kGrey700Color)
  }
  /// The blue color.
  public static var chromeBlue: Color {
    return Color(kBlueColor)
  }
  /// The blue halo color.
  public static var blueHalo: Color {
    return Color(kBlueHaloColor)
  }
  /// The blue500 color.
  public static var blue500: Color {
    return Color(kBlue500Color)
  }
  /// The blue600 color.
  public static var blue600: Color {
    return Color(kBlue600Color)
  }
  /// The red500 color.
  public static var red500: Color {
    return Color(kRed500Color)
  }
  /// The table row view highlight color.
  public static var tableRowViewHighlight: Color {
    return Color(kTableViewRowHighlightColor)
  }
  /// The table view separator color.
  public static var separator: Color {
    return Color(kSeparatorColor)
  }
  /// The toolbar shadow color.
  public static var toolbarShadow: Color {
    return Color(kToolbarShadowColor)
  }
}


import Struct
import XCTest
class StructTest: XCTestCase {
  func testStruct() throws {
    var goodFoo = Foolean()
    var badFoo = Foolean()
    // Test calling static method from struct.
    goodFoo.value = true
    goodFoo.description = Foolean.GetDescriptionForValue(true)
    badFoo.value = false
    badFoo.description = Foolean.GetDescriptionForValue(true)
    // Test passing object defined in C++ and initialized in Swift to top level C++ functions.
    XCTAssertTrue(IsFooleanValid(goodFoo))
    XCTAssertFalse(IsFooleanValid(badFoo))
  }
}


import Enums
import XCTest
class EnumTest: XCTestCase {
  func testEnums() throws {
    // Explicitly typed.
    var color: Color = kBlue
    color = kYellow
    XCTAssertEqual(color, kYellow, "Typed enum doesn't match")
    // Implicit type. |x| is an |Int|.
    let x = kThree
    XCTAssertEqual(x, kThree, "Implicitly typed enum doesn't match")
    // Implicit type, |anotherColor| is a |Color|.
    let anotherColor = kYellow
    XCTAssertEqual(anotherColor, kYellow, "")
    XCTAssertNotEqual(anotherColor, kBlue)
  }
  func testClassEnum() throws {
    let pet: Pet = Pet.goat
    XCTAssertEqual(pet, Pet.goat, "")
    XCTAssertNotEqual(pet, Pet.dogcow, "")
    XCTAssertNotEqual(Pet.goat, Pet.dogcow)
  }
}


import Classes
import UIKit
import XCTest
class InlinedClassTest: XCTestCase {
  func testInlined() throws {
    var obj = InlinedClass()
    var num: Int32 = obj.AddTo(10)
    XCTAssertEqual(num, 10, "Addition didn't work correctly")
    num = obj.AddTo(5)
    XCTAssertEqual(num, 15, "Addition didn't work correctly")
    var composed = ComposedClass()
    composed.Increment(2)
    let result: Int32 = composed.Increment(8)
    XCTAssertEqual(result, 10, "Stack based class didn't work")
  }
}


import Classes
import UIKit
import XCTest
class OutlinedClassTest: XCTestCase {
  func testOutlined() throws {
    var outlined = Outlined()
    XCTAssertEqual(outlined.OutlinedAddition(8), 8, "Outlined method broken")
    XCTAssertEqual(outlined.OutlinedAddition(2), 10, "Outlined method broken")
  }
  func testOutlinedInitalCtor() throws {
    var outlined = Outlined(10)
    XCTAssertEqual(outlined.OutlinedAddition(8), 18, "Outlined method broken")
    XCTAssertEqual(outlined.OutlinedAddition(2), 20, "Outlined method broken")
  }
}


import Classes
import XCTest
class PolymorphismTest: XCTestCase {
  func testBasicInheritance() throws {
    #if swift(<5.7)
      var rect = Rectangle(10, 10)
      XCTAssertEqual(rect.Area(), 100)
      XCTAssertEqual(rect.NumberOfSides(), 4)
      var square = Square(5)
      XCTAssertEqual(square.Area(), 25)
      XCTAssertEqual(square.NumberOfSides(), 4)
      var triangle = Triangle(10, 10)
      XCTAssertEqual(triangle.Area(), 50)
      XCTAssertEqual(triangle.NumberOfSides(), 3)
    #endif
  }
  // The primary bug for inherited methods not working is
  // https://github.com/apple/swift/issues/55192. That covers several of
  // these tests.
  func testInheritedMethods_noCompile() throws {
    // Test calling a public method defined in the public base class.
    // DOESN'T COMPILE: value of type 'Rectangle' has no member 'HasSides'
    // CRASHES in 5.7-dev.
    // var rect = Rectangle(10, 10)
    // XCTAssertTrue(rect.HasSides())
  }
  func testRuntimePolymorphism_fails() throws {
    // MakeShape() creates a Triangle and returns the object as a Shape*.
    // let shape = MakeShape(10, 10)
    // DOES NOT WORK: executes the Shape implementation, not the Triangle
    // version, and thus fails the comparision (0 != 3)
    // XCTAssertEqual(shape!.pointee.NumberOfSides(), 3)
  }
  func testPureVirtualMethods_noCompile() throws {
    // MakeShape() creates a Triangle and returns the object as a Shape*.
    // let shape = MakeShape(10, 10)
    // DOES NOT COMPILE: undefined symbol Shape::Area() for lld.
    // XCTAssertEqual(shape!.pointee.Area(), 50)
  }
}


import Pointer
import XCTest
class ObjectPassingTest: XCTestCase {
  func testReferenceParameters() throws {
    let a = Object(10)
    let b = Object(20)
    let passer = ObjectPassing()
    XCTAssertEqual(a.GetValue(), 10)
    XCTAssertEqual(passer.AddReferences(a, b), 30)
  }
  func testPointerParameters() throws {
    var a = Object(10)
    var b = Object(20)
    let passer = ObjectPassing()
    XCTAssertEqual(a.GetValue(), 10)
    XCTAssertEqual(passer.AddPointers(&a, &b), 30)
  }
  func testMismatchedParameters() throws {
    // var obj = Object(10)
    // var str = "Hello"
    // let passer = ObjectPassing()
    // Correctly doesn't compile because the types don't match. Error is
    // "cannot convert value of type 'UnsafeMutablePointer<String>' to expected
    // argument type 'UnsafeMutablePointer<Object>'.
    // XCTAssertEqual(passer.AddPointers(&obj, &obj, &str), 60, "")
  }
  // Note: if this method returns `Int` instead of `Int32` the compiler
  // will crash (filed as https://github.com/apple/swift/issues/58458).
  // This has been fixed in ToT.
  // Note: prior to Swift 5.6, calling GetValue() (which is const) on these objects
  // results in a compiler error about calling immutable methods on a `let` object.
  // Omit this test on earlier Swift versions.
  func addObjects(one: Object, two: Object) -> Int32 {
    return one.GetValue() + two.GetValue()
  }
  func addPointerObjects(one: UnsafeMutablePointer<Object>, two: UnsafeMutablePointer<Object>)
    -> Int32
  {
    return one.pointee.GetValue() + two.pointee.GetValue()
  }
  func testPassToSwift() throws {
    var a = Object(10)
    var b = Object(20)
    XCTAssertEqual(addObjects(one: a, two: b), 30)
    XCTAssertEqual(addPointerObjects(one: &a, two: &b), 30)
  }
}


import Pointer
import UIKit
import XCTest
class PointerTest: XCTestCase {
  func testReturnedPointer() throws {
    var returner = PointerReturner()
    XCTAssertEqual(returner.Valid(), true, "Object not valid?")
    let intPtr = returner.IntegerPointer()!
    XCTAssertEqual(intPtr.pointee, 17, "Pointer-to-integer return broken")
  }
  func testReturnedObjectPointer() throws {
    var returner = PointerReturner()
    let ptr = returner.ObjectPointer()!
    XCTAssertEqual(ptr.pointee.Valid(), true, "Object returned by pointer not valid?")
    let intPtr = ptr.pointee.IntegerPointer()!
    XCTAssertEqual(intPtr.pointee, 17, "Pointer-to-integer returned from pointer-to-object broken")
  }
}


import Pointer
import UIKit
import XCTest
class UniquePointerTest: XCTestCase {
  func testReturnedObjectPointer() throws {
    var returner = ValueReturner()
    let object = returner.ObjectPointer()!
    XCTAssertEqual(object.pointee.IsValid(), true, "")
    // DOESN'T COMPILE: value of type 'Value' has no member 'GetValue'
    // in 5.7 official builds. http://crbug.com/1336937
    // XCTAssertEqual(object.pointee.GetValue(), 17, "")
  }
}


import Namespace
import UIKit
import XCTest
class NamespaceTest: XCTestCase {
  func testNamespaceClass() throws {
    // Non-namespaced class.
    let goat = Goat()
    XCTAssertEqual(goat.GetValue(), 7, "Values don't match")
    // Namespaced class with the same type name, verify the namespaced one
    // is the one created.
    let spaceGoat = space.Goat()
    spaceGoat.DoNothing()
    XCTAssertEqual(spaceGoat.GetValue(), 42, "Values don't match")
  }
  func testNamespaceTypedEnum_noCompile() throws {
    // namespaced typed enum.
    // DOESN'T COMPILE: 'Vehicle' has no member 'boat' (it does).
    // let vehicle = space.Vehicle.boat
  }
  func testNamespaceClassEnum() throws {
    // Use a namespaced class enum.
    // Compiles ONLY with Swift greater than version 5.6 (Xcode 13.3).
    let animal = space.Animal.goat
    XCTAssertEqual(animal, space.Animal.goat, "values don't match")
    XCTAssertNotEqual(animal, space.Animal.dog, "values don't match")
  }
  func testNestedNamespace() throws {
    let goat = outer.inner.NestedGoat()
    XCTAssertEqual(goat.GetValue(), 50, "values don't match")
  }
  func testClassEnumInOutNamespace_crashes() throws {
    // Test the enum class not in a namespace.
    let food = SameNameEnum.watermelon
    XCTAssertNotEqual(food, SameNameEnum.orange, "something broke")
    // Test the enum class in a namespace.
    // CRASHES in XCTAssertNotEqual()
    // In progress CL: https://github.com/apple/swift/pull/42494.
    // let moreFood = sameName.SameNameEnum.watermelon;
    // XCTAssertNotEqual(moreFood, sameName.SameNameEnum.orange, "something broke")
  }
}


import Foundation
import SwiftUI
import WidgetKit
struct SearchWidget: Widget {
  // Changing |kind| or deleting this widget will cause all installed instances of this widget to
  // stop updating and show the placeholder state.
  let kind: String = "SearchWidget"
  var body: some WidgetConfiguration {
    StaticConfiguration(kind: kind, provider: Provider()) { entry in
      SearchWidgetEntryView(entry: entry)
    }
    .configurationDisplayName(
      Text("IDS_IOS_WIDGET_KIT_EXTENSION_SEARCH_DISPLAY_NAME")
    )
    .description(Text("IDS_IOS_WIDGET_KIT_EXTENSION_SEARCH_DESCRIPTION"))
    .supportedFamilies([.systemSmall])
  }
}
struct SearchWidgetEntryView: View {
  var entry: Provider.Entry
  var body: some View {
    // We wrap this widget in a link on top of using `widgetUrl` so that the voice over will treat
    // the widget as one tap target. Without the wrapping, voice over treats the content within
    // the widget as multiple tap targets.
    Link(destination: WidgetConstants.SearchWidget.url) {
      ZStack {
        Color("widget_background_color")
          .unredacted()
        VStack(alignment: .leading, spacing: 0) {
          ZStack {
            RoundedRectangle(cornerRadius: 26)
              .frame(height: 52)
              .foregroundColor(Color("widget_search_bar_color"))
            HStack(spacing: 0) {
              Image("widget_chrome_logo")
                .clipShape(Circle())
                .padding(.leading, 8)
                .unredacted()
              Spacer()
            }
          }
          .frame(minWidth: 0, maxWidth: .infinity)
          .padding([.leading, .trailing], 11)
          .padding(.top, 16)
          Spacer()
          Text("IDS_IOS_WIDGET_KIT_EXTENSION_SEARCH_TITLE")
            .foregroundColor(Color("widget_text_color"))
            .fontWeight(.semibold)
            .font(.subheadline)
            .padding([.leading, .bottom, .trailing], 16)
        }
      }
    }
    .widgetURL(WidgetConstants.SearchWidget.url)
    .accessibility(
      label: Text("IDS_IOS_WIDGET_KIT_EXTENSION_SEARCH_A11Y_LABEL"))
  }
}


import Foundation
import SwiftUI
import WidgetKit
#if IOS_ENABLE_LOCKSCREEN_WIDGET
  #if IOS_AVAILABLE_LOCKSCREEN_WIDGET
    enum LockscreenLauncherWidgetType {
      case search, incognito, voiceSearch, dinoGame
      struct Configuration {
        let displayName: LocalizedStringKey, description: LocalizedStringKey, imageName: String,
          accessibilityLabel: LocalizedStringKey,
          widgetURL: URL
        var supportedFamilies: [WidgetFamily] {
          if #available(iOS 16, *) {
            return [.accessoryCircular]
          }
          return []
        }
      }
      var configuration: Configuration {
        switch self {
        case .search:
          return Configuration(
            displayName: "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_SEARCH_DISPLAY_NAME",
            description: "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_SEARCH_DESCRIPTION",
            imageName: "lockscreen_chrome_logo",
            accessibilityLabel:
              "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_SEARCH_A11Y_LABEL",
            widgetURL: WidgetConstants.LockscreenLauncherWidget.searchUrl)
        case .incognito:
          return Configuration(
            displayName: "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_INCOGNITO_DISPLAY_NAME",
            description: "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_INCOGNITO_DESCRIPTION",
            imageName: "lockscreen_incognito_logo",
            accessibilityLabel:
              "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_INCOGNITO_A11Y_LABEL",
            widgetURL: WidgetConstants.LockscreenLauncherWidget.incognitoUrl)
        case .voiceSearch:
          return Configuration(
            displayName:
              "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_VOICESEARCH_DISPLAY_NAME",
            description: "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_VOICESEARCH_DESCRIPTION",
            imageName: "lockscreen_voicesearch_logo",
            accessibilityLabel:
              "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_VOICESEARCH_A11Y_LABEL",
            widgetURL: WidgetConstants.LockscreenLauncherWidget.voiceSearchUrl)
        case .dinoGame:
          return Configuration(
            displayName: "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_GAME_DISPLAY_NAME",
            description: "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_GAME_DESCRIPTION",
            imageName: "lockscreen_game_logo",
            accessibilityLabel: "IDS_IOS_WIDGET_KIT_EXTENSION_LOCKSCREEN_LAUNCHER_GAME_A11Y_LABEL",
            widgetURL: WidgetConstants.LockscreenLauncherWidget.gameUrl)
        }
      }
    }
    struct LockscreenLauncherWidgetEntryView: View {
      let entry: Provider.Entry
      let configuration: LockscreenLauncherWidgetType.Configuration
      var body: some View {
        let configuration = self.configuration
        ZStack {
          if #available(iOS 16, *) {
            AccessoryWidgetBackground()
          }
          Image(configuration.imageName)
            .renderingMode(.template)
            .foregroundColor(.white)
        }
        .widgetURL(configuration.widgetURL)
        .accessibilityElement()
        .accessibilityLabel(configuration.accessibilityLabel)
      }
    }
    func lockscreenLauncherWidgetConfiguration(
      ofKind kind: String, forType type: LockscreenLauncherWidgetType
    ) -> some WidgetConfiguration {
      let configuration = type.configuration
      return StaticConfiguration(kind: kind, provider: Provider()) { entry in
        LockscreenLauncherWidgetEntryView(entry: entry, configuration: configuration)
      }
      .configurationDisplayName(
        Text(configuration.displayName)
      )
      .description(Text(configuration.description))
      .supportedFamilies(configuration.supportedFamilies)
    }
    struct LockscreenLauncherSearchWidget: Widget {
      // Changing |kind| or deleting this widget will cause all installed instances of this widget
      // to stop updating and show the placeholder state.
      let kind: String = "LockscreenLauncherSearchWidget"
      var body: some WidgetConfiguration {
        lockscreenLauncherWidgetConfiguration(ofKind: kind, forType: .search)
      }
    }
    struct LockscreenLauncherIncognitoWidget: Widget {
      // Changing |kind| or deleting this widget will cause all installed instances of this widget
      // to stop updating and show the placeholder state.
      let kind: String = "LockscreenLauncherIncognitoWidget"
      var body: some WidgetConfiguration {
        lockscreenLauncherWidgetConfiguration(ofKind: kind, forType: .incognito)
      }
    }
    struct LockscreenLauncherVoiceSearchWidget: Widget {
      // Changing |kind| or deleting this widget will cause all installed instances of this widget
      // to stop updating and show the placeholder state.
      let kind: String = "LockscreenLauncherVoiceSearchWidget"
      var body: some WidgetConfiguration {
        lockscreenLauncherWidgetConfiguration(ofKind: kind, forType: .voiceSearch)
      }
    }
    struct LockscreenLauncherGameWidget: Widget {
      // Changing |kind| or deleting this widget will cause all installed instances of this widget
      // to stop updating and show the placeholder state.
      let kind: String = "LockscreenLauncherGameWidget"
      var body: some WidgetConfiguration {
        lockscreenLauncherWidgetConfiguration(ofKind: kind, forType: .dinoGame)
      }
    }
  #endif  // IOS_AVAILABLE_LOCKSCREEN_WIDGET
#endif  // IOS_ENABLE_LOCKSCREEN_WIDGET


import Foundation
import SwiftUI
import WidgetKit
struct ShortcutsWidget: Widget {
  // Changing 'kind' or deleting this widget will cause all installed instances of this widget to
  // stop updating and show the placeholder state.
  let kind: String = "ShortcutsWidget"
  var body: some WidgetConfiguration {
    StaticConfiguration(
      kind: kind,
      provider: Provider()
    ) { entry in
      ShortcutsWidgetEntryView(entry: entry)
    }
    .configurationDisplayName(
      Text("Shortcuts Widget")
    )
    .description(Text("Shortcuts Widget Description"))
    .supportedFamilies([.systemMedium])
  }
}
struct ShortcutsWidgetEntryView: View {
  let entry: Provider.Entry
  var body: some View {
    EmptyView()
  }
}


import Foundation
import SwiftUI
import WidgetKit
struct ConfigureQuickActionsWidgetEntry: TimelineEntry {
  let date: Date
  let useLens: Bool
}
struct ConfigureQuickActionsWidgetEntryProvider: TimelineProvider {
  func placeholder(in context: Context) -> ConfigureQuickActionsWidgetEntry {
    ConfigureQuickActionsWidgetEntry(date: Date(), useLens: false)
  }
  func shouldUseLens() -> Bool {
    let sharedDefaults: UserDefaults = AppGroupHelper.groupUserDefaults()
    let useLens: Bool =
      sharedDefaults.bool(
        forKey: WidgetConstants.QuickActionsWidget.isGoogleDefaultSearchEngineKey)
      && sharedDefaults.bool(
        forKey: WidgetConstants.QuickActionsWidget.enableLensInWidgetKey)
    return useLens
  }
  func getSnapshot(
    in context: Context,
  ) {
    let entry = ConfigureQuickActionsWidgetEntry(
      date: Date(),
      useLens: shouldUseLens()
    )
    let entries: [ConfigureQuickActionsWidgetEntry] = [entry]
    let timeline: Timeline = Timeline(entries: entries, policy: .never)
    completion(timeline)
  }
}
struct QuickActionsWidget: Widget {
  // Changing |kind| or deleting this widget will cause all installed instances of this widget to
  // stop updating and show the placeholder state.
  let kind: String = "QuickActionsWidget"
  var body: some WidgetConfiguration {
    StaticConfiguration(
      kind: kind,
      provider: ConfigureQuickActionsWidgetEntryProvider()
    ) { entry in
      QuickActionsWidgetEntryView(entry: entry)
    }
    .configurationDisplayName(
      Text("IDS_IOS_WIDGET_KIT_EXTENSION_QUICK_ACTIONS_DISPLAY_NAME")
    )
    .description(Text("IDS_IOS_WIDGET_KIT_EXTENSION_QUICK_ACTIONS_DESCRIPTION"))
    .supportedFamilies([.systemMedium])
  }
}
struct QuickActionsWidgetEntryView: View {
  var entry: ConfigureQuickActionsWidgetEntry
  private let searchAreaHeight: CGFloat = 92
  private let separatorHeight: CGFloat = 32
  private let incognitoA11yLabel: LocalizedStringKey =
    "IDS_IOS_WIDGET_KIT_EXTENSION_QUICK_ACTIONS_INCOGNITO_A11Y_LABEL"
  private let voiceSearchA11yLabel: LocalizedStringKey =
    "IDS_IOS_WIDGET_KIT_EXTENSION_QUICK_ACTIONS_VOICE_SEARCH_A11Y_LABEL"
  private let lensA11yLabel: LocalizedStringKey =
    "IDS_IOS_WIDGET_KIT_EXTENSION_QUICK_ACTIONS_LENS_A11Y_LABEL"
  private let qrA11yLabel: LocalizedStringKey =
    "IDS_IOS_WIDGET_KIT_EXTENSION_QUICK_ACTIONS_QR_SCAN_A11Y_LABEL"
  func symbolWithName(symbolName: String, system: Bool) -> some View {
    let image = system ? Image(systemName: symbolName) : Image(symbolName)
    return image.foregroundColor(Color("widget_actions_icon_color")).font(
      .system(size: 20, weight: .medium)
    ).imageScale(.medium)
  }
  var body: some View {
    VStack(spacing: 0) {
      ZStack {
        Color("widget_background_color")
          .unredacted()
        VStack {
          Spacer()
          Link(destination: WidgetConstants.QuickActionsWidget.searchUrl) {
            ZStack {
              RoundedRectangle(cornerRadius: 26)
                .frame(height: 52)
                .foregroundColor(Color("widget_search_bar_color"))
              HStack(spacing: 12) {
                Image("widget_chrome_logo")
                  .clipShape(Circle())
                  // Without .clipShape(Circle()), in the redacted/placeholder
                  // state the Widget shows an rectangle placeholder instead of
                  // a circular one.
                  .padding(.leading, 8)
                  .unredacted()
                Text("IDS_IOS_WIDGET_KIT_EXTENSION_QUICK_ACTIONS_TITLE")
                  .font(.subheadline)
                  .foregroundColor(Color("widget_text_color"))
                Spacer()
              }
            }
            .frame(minWidth: 0, maxWidth: .infinity)
            .padding([.leading, .trailing], 11)
          }
          .accessibility(
            label:
              Text(
                "IDS_IOS_WIDGET_KIT_EXTENSION_QUICK_ACTIONS_SEARCH_A11Y_LABEL"
              )
          )
          Spacer()
        }
        .frame(height: searchAreaHeight)
      }
      ZStack {
        Rectangle()
          .foregroundColor(Color("widget_actions_row_background_color"))
          .frame(minWidth: 0, maxWidth: .infinity)
        HStack {
          // Show interactive buttons if the widget is fully loaded, and show
          // the custom placeholder otherwise.
          if redactionReasons.isEmpty {
            Link(destination: WidgetConstants.QuickActionsWidget.incognitoUrl) {
              symbolWithName(symbolName: "widget_incognito_icon", system: false)
                .frame(minWidth: 0, maxWidth: .infinity)
            }
            .accessibility(label: Text(incognitoA11yLabel))
            Separator(height: separatorHeight)
            Link(
              destination: WidgetConstants.QuickActionsWidget.voiceSearchUrl
            ) {
              symbolWithName(symbolName: "mic", system: true)
                .frame(minWidth: 0, maxWidth: .infinity)
            }
            .accessibility(label: Text(voiceSearchA11yLabel))
            Separator(height: separatorHeight)
            if entry.useLens {
              Link(destination: WidgetConstants.QuickActionsWidget.lensUrl) {
                symbolWithName(symbolName: "widget_lens_icon", system: false)
                  .frame(minWidth: 0, maxWidth: .infinity)
              }
              .accessibility(label: Text(lensA11yLabel))
            } else {
              Link(destination: WidgetConstants.QuickActionsWidget.qrCodeUrl) {
                symbolWithName(symbolName: "qrcode", system: true)
                  .frame(minWidth: 0, maxWidth: .infinity)
              }
              .accessibility(label: Text(qrA11yLabel))
            }
          } else {
            ButtonPlaceholder()
            Separator(height: separatorHeight)
            ButtonPlaceholder()
            Separator(height: separatorHeight)
            ButtonPlaceholder()
          }
        }
        .frame(minWidth: 0, maxWidth: .infinity)
        .padding([.leading, .trailing], 11)
      }
    }
  }
}
struct Separator: View {
  let height: CGFloat
  var body: some View {
    RoundedRectangle(cornerRadius: 1)
      .foregroundColor(Color("widget_separator_color"))
      .frame(width: 2, height: height)
  }
}
struct ButtonPlaceholder: View {
  private let widthOfPlaceholder: CGFloat = 28
  var body: some View {
    Group {
      RoundedRectangle(cornerRadius: 4, style: .continuous)
        .frame(width: widthOfPlaceholder, height: widthOfPlaceholder)
        .foregroundColor(Color("widget_text_color"))
        .opacity(0.3)
    }.frame(minWidth: 0, maxWidth: .infinity)
  }
}


main

  ) {
    let entry = SimpleEntry(date: Date())
    completion(entry)
  }
  func getTimeline(
    in context: Context,
struct ChromeWidgets: WidgetBundle {
  init() {
    CrashHelper.configure()
  }
  var body: some Widget {
    QuickActionsWidget()
    SearchWidget()
    DinoGameWidget()
    #if IOS_ENABLE_SHORTCUTS_WIDGET
      ShortcutsWidget()
    #endif
    #if IOS_ENABLE_LOCKSCREEN_WIDGET
      #if IOS_AVAILABLE_LOCKSCREEN_WIDGET
        LockscreenLauncherSearchWidget()
        LockscreenLauncherIncognitoWidget()
        LockscreenLauncherVoiceSearchWidget()
        LockscreenLauncherGameWidget()
      #endif
    #endif
  }
}


import Foundation
import SwiftUI
import WidgetKit
struct DinoGameWidget: Widget {
  // Changing |kind| or deleting this widget will cause all installed instances of this widget to
  // stop updating and show the placeholder state.
  let kind: String = "DinoGameWidget"
  var body: some WidgetConfiguration {
    StaticConfiguration(kind: kind, provider: Provider()) { entry in
      DinoGameWidgetEntryView(entry: entry)
    }
    .configurationDisplayName(
      Text("IDS_IOS_WIDGET_KIT_EXTENSION_GAME_DISPLAY_NAME")
    )
    .description(Text("IDS_IOS_WIDGET_KIT_EXTENSION_GAME_DESCRIPTION"))
    .supportedFamilies([.systemSmall])
  }
}
struct DinoGameWidgetEntryView: View {
  let background = "widget_dino_background"
  let backgroundPlaceholder = "widget_dino_background_placeholder"
  var entry: Provider.Entry
  var body: some View {
    // We wrap this widget in a link on top of using `widgetUrl` so that the voice over will treat
    // the widget as one tap target. Without the wrapping, voice over treats the content within
    // the widget as multiple tap targets.
    Link(destination: WidgetConstants.DinoGameWidget.url) {
      ZStack {
        Image(redactionReasons.isEmpty ? background : backgroundPlaceholder)
          .resizable()
          .unredacted()
        VStack(alignment: .leading, spacing: 0) {
          Spacer()
            .frame(minWidth: 0, maxWidth: .infinity)
          HStack {
            Text("IDS_IOS_WIDGET_KIT_EXTENSION_GAME_TITLE")
              .foregroundColor(Color("widget_text_color"))
              .fontWeight(.semibold)
              .font(.subheadline)
              .lineLimit(1)
            Spacer()
          }
          .padding([.leading, .bottom], 16)
        }
      }
    }
    .widgetURL(WidgetConstants.DinoGameWidget.url)
    .accessibility(
      label: Text("IDS_IOS_WIDGET_KIT_EXTENSION_GAME_A11Y_LABEL"))
  }
}


import Foundation
struct WidgetConstants {
  struct SearchWidget {
    static let url = URL(string: "chromewidgetkit://search-widget/search")!
  }
  struct QuickActionsWidget {
    static let searchUrl =
      URL(string: "chromewidgetkit://quick-actions-widget/search")!
    static let incognitoUrl =
      URL(string: "chromewidgetkit://quick-actions-widget/incognito")!
    static let voiceSearchUrl =
      URL(string: "chromewidgetkit://quick-actions-widget/voicesearch")!
    static let qrCodeUrl =
      URL(string: "chromewidgetkit://quick-actions-widget/qrreader")!
    static let lensUrl =
      URL(string: "chromewidgetkit://quick-actions-widget/lens")!
    static let isGoogleDefaultSearchEngineKey = "isGoogleDefaultSearchEngine"
    static let enableLensInWidgetKey = "enableLensInWidget"
  }
  struct DinoGameWidget {
    static let url = URL(string: "chromewidgetkit://dino-game-widget/game")!
  }
  struct LockscreenLauncherWidget {
    static let searchUrl =
      URL(string: "chromewidgetkit://lockscreen-launcher-widget/search")!
    static let incognitoUrl =
      URL(string: "chromewidgetkit://lockscreen-launcher-widget/incognito")!
    static let voiceSearchUrl =
      URL(string: "chromewidgetkit://lockscreen-launcher-widget/voicesearch")!
    static let gameUrl = URL(string: "chromewidgetkit://lockscreen-launcher-widget/game")!
  }
}


PhotoAlbumTransition

/*
 */
import Foundation
import UIKit
import MotionTransitioning
protocol PhotoAlbumTransitionForeDelegate: class {
  func foreContextView(for transition: PhotoAlbumTransition) -> UIImageView?
  func toolbar(for transition: PhotoAlbumTransition) -> UIToolbar?
}
protocol PhotoAlbumTransitionBackDelegate: class {
  func backContextView(for transition: PhotoAlbumTransition,
                       with foreViewController: UIViewController) -> UIImageView?
}
final class PhotoAlbumTransition: NSObject, Transition, TransitionWithFeasibility {
  weak var backDelegate: PhotoAlbumTransitionBackDelegate?
  weak var foreDelegate: PhotoAlbumTransitionForeDelegate?
  init(backDelegate: PhotoAlbumTransitionBackDelegate,
       foreDelegate: PhotoAlbumTransitionForeDelegate) {
    self.backDelegate = backDelegate
    self.foreDelegate = foreDelegate
  }
  func canPerformTransition(with context: TransitionContext) -> Bool {
    guard let backDelegate = backDelegate else {
      return false
    }
    return backDelegate.backContextView(for: self, with: context.foreViewController) != nil
  }
  func start(with context: TransitionContext) {
    guard let backDelegate = backDelegate, let foreDelegate = foreDelegate else {
      return
    }
    guard let contextView = backDelegate.backContextView(for: self,
                                                         with: context.foreViewController) else {
                                                          return
    }
    guard let foreImageView = foreDelegate.foreContextView(for: self) else {
      return
    }
    let snapshotter = TransitionViewSnapshotter(containerView: context.containerView)
    context.defer {
      snapshotter.removeAllSnapshots()
    }
    foreImageView.isHidden = true
    context.defer {
      foreImageView.isHidden = false
    }
    let imageSize = foreImageView.image!.size
    let fitScale = min(foreImageView.bounds.width / imageSize.width,
                       foreImageView.bounds.height / imageSize.height)
    let fitSize = CGSize(width: fitScale * imageSize.width, height: fitScale * imageSize.height)
    let snapshotContextView = snapshotter.snapshot(of: contextView,
                                                   isAppearing: context.direction == .backward)
    context.compose(with: FadeTransition(target: .foreView, style: .fadeIn))
    context.compose(with: SpringFrameTransition(target: .target(snapshotContextView),
                                                size: fitSize))
    if let toolbar = foreDelegate.toolbar(for: self) {
      context.compose(with: SlideUpTransition(target: .target(toolbar)))
    }
    // This transition doesn't directly produce any animations, so we inform the context that it is
    // complete here, otherwise the transition would never complete:
    context.transitionDidEnd()
  }
}


FadeExample

/*
 */
import UIKit
import MotionTransitioning
// This example demonstrates the minimal path to using a custom transition in Swift. See
// FadeTransition.swift for the custom transition implementation.
class FadeExampleViewController: ExampleViewController {
    let modalViewController = ModalViewController()
    // The transition controller is an associated object on all UIViewController instances that
    // allows you to customize the way the view controller is presented. The primary API on the
    // controller that you'll make use of is the `transition` property. Setting this property will
    // dictate how the view controller is presented. For this example we've built a custom
    // FadeTransition, so we'll make use of that now:
    modalViewController.mdm_transitionController.transition = FadeTransition(target: .foreView)
    // Note that once we assign the transition object to the view controller, the transition will
    // govern all subsequent presentations and dismissals of that view controller instance. If we
    // want to use a different transition (e.g. to use an edge-swipe-to-dismiss transition) then we
    // can simply change the transition object before initiating the transition.
    present(modalViewController, animated: true)
  }
  override func viewDidLoad() {
    super.viewDidLoad()
    let label = UILabel(frame: view.bounds)
    label.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    label.textColor = .white
    label.textAlignment = .center
    label.text = "Tap to start the transition"
    view.addSubview(label)
    let tap = UITapGestureRecognizer(target: self, action: #selector(didTap))
    view.addGestureRecognizer(tap)
  }
  override func exampleInformation() -> ExampleInfo {
    return .init(title: type(of: self).catalogBreadcrumbs().last!,
                 instructions: "Tap to present a modal transition.")
  }
}


PhotoAlbumExample

/*
 */
import UIKit
import MotionTransitioning
// This example demonstrates how to build a photo album contextual transition.
private let photoCellIdentifier = "photoCell"
public class PhotoAlbumExampleViewController: UICollectionViewController, PhotoAlbumTransitionBackDelegate {
  let album = PhotoAlbum()
  init() {
    super.init(collectionViewLayout: UICollectionViewFlowLayout())
  }
  public required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
  override public func viewDidLoad() {
    super.viewDidLoad()
    collectionView!.backgroundColor = .white
    collectionView!.register(PhotoCollectionViewCell.self,
                             forCellWithReuseIdentifier: photoCellIdentifier)
  }
  public override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    updateLayout()
  }
  func updateLayout() {
    let layout = collectionView!.collectionViewLayout as! UICollectionViewFlowLayout
    layout.sectionInset = .init(top: 4, left: 4, bottom: 4, right: 4)
    layout.minimumInteritemSpacing = 4
    layout.minimumLineSpacing = 4
    let numberOfColumns: CGFloat = 3
    let squareDimension = (view.bounds.width - layout.sectionInset.left - layout.sectionInset.right - (numberOfColumns - 1) * layout.minimumInteritemSpacing) / numberOfColumns
    layout.itemSize = CGSize(width: squareDimension, height: squareDimension)
  }
  public override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return album.photos.count
  }
  public override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: photoCellIdentifier,
                                                  for: indexPath) as! PhotoCollectionViewCell
    let photo = album.photos[indexPath.row]
    cell.imageView.image = photo.image
    return cell
  }
  public override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let viewController = PhotoAlbumViewController(album: album)
    viewController.currentPhoto = album.photos[indexPath.row]
    viewController.mdm_transitionController.transition = PhotoAlbumTransition(backDelegate: self,
                                                                          foreDelegate: viewController)
    viewController.modalPresentationStyle = .custom
    present(viewController, animated: true)
  }
  func backContextView(for transition: PhotoAlbumTransition,
                       with foreViewController: UIViewController) -> UIImageView? {
    let currentPhoto = (foreViewController as! PhotoAlbumViewController).currentPhoto
    guard let photoIndex = album.identifierToIndex[currentPhoto.uuid] else {
      return nil
    }
    let photoIndexPath = IndexPath(item: photoIndex, section: 0)
    if collectionView?.cellForItem(at: photoIndexPath) == nil {
      collectionView?.scrollToItem(at: photoIndexPath, at: .top, animated: false)
      collectionView?.reloadItems(at: [photoIndexPath])
    }
    guard let cell = collectionView?.cellForItem(at: photoIndexPath) as? PhotoCollectionViewCell else {
      return nil
    }
    return cell.imageView
  }
}
class PhotoAlbumViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, PhotoAlbumTransitionForeDelegate {
  var collectionView: UICollectionView!
  let toolbar = UIToolbar()
  var currentPhoto: Photo
  let album: PhotoAlbum
  init(album: PhotoAlbum) {
    self.album = album
    self.currentPhoto = self.album.photos.first!
    super.init(nibName: nil, bundle: nil)
  }
  required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
  override func viewDidLoad() {
    super.viewDidLoad()
    automaticallyAdjustsScrollViewInsets = false
    let layout = UICollectionViewFlowLayout()
    layout.itemSize = view.bounds.size
    layout.minimumInteritemSpacing = 0
    layout.minimumLineSpacing = 8
    layout.footerReferenceSize = CGSize(width: layout.minimumLineSpacing / 2,
                                        height: view.bounds.size.height)
    layout.headerReferenceSize = layout.footerReferenceSize
    layout.scrollDirection = .horizontal
    collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
    collectionView.isPagingEnabled = true
    collectionView.backgroundColor = .backgroundColor
    collectionView.showsHorizontalScrollIndicator = false
    collectionView.dataSource = self
    collectionView.delegate = self
    collectionView.register(PhotoCollectionViewCell.self,
                            forCellWithReuseIdentifier: photoCellIdentifier)
    var extendedBounds = view.bounds
    extendedBounds.size.width = extendedBounds.width + layout.minimumLineSpacing
    collectionView.bounds = extendedBounds
    view.addSubview(collectionView)
    let toolbarSize = toolbar.sizeThatFits(view.bounds.size)
    toolbar.frame = .init(x: 0, y: view.bounds.height - toolbarSize.height,
                          width: toolbarSize.width, height: toolbarSize.height)
    view.addSubview(toolbar)
  }
  override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    collectionView.center = CGPoint(x: view.bounds.midX, y: view.bounds.midY)
  }
  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    navigationController?.setNavigationBarHidden(true, animated: animated)
    let photoIndex = album.photos.firstIndex { $0.image == currentPhoto.image }!
    let indexPath = IndexPath(item: photoIndex, section: 0)
    collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: false)
  }
  override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
  }
  // MARK: PhotoAlbumTransitionForeDelegate
  func foreContextView(for transition: PhotoAlbumTransition) -> UIImageView? {
    return (collectionView.cellForItem(at: indexPathForCurrentPhoto()) as! PhotoCollectionViewCell).imageView
  }
  func toolbar(for transition: PhotoAlbumTransition) -> UIToolbar? {
    return toolbar
  }
  // MARK: UICollectionViewDataSource
  func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return album.photos.count
  }
  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: photoCellIdentifier,
                                                  for: indexPath) as! PhotoCollectionViewCell
    let photo = album.photos[indexPath.row]
    cell.imageView.image = photo.image
    cell.imageView.contentMode = .scaleAspectFit
    return cell
  }
  // MARK: UICollectionViewDelegate
  func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    dismiss(animated: true)
  }
  func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    currentPhoto = album.photos[indexPathForCurrentPhoto().item]
  }
  // MARK: Private
  private func indexPathForCurrentPhoto() -> IndexPath {
    return collectionView.indexPathsForVisibleItems.first!
  }
}


ContextualExample

/*
 */
import UIKit
import MotionTransitioning
// This example demonstrates how to build a contextual transition.
class ContextualExampleViewController: ExampleViewController {
    let controller = DestinationViewController()
    // A contextual transition is provided with information relevant to the transition, such as the
    // view that is being expanded/collapsed. This information can be provided at initialization
    // time if it is unlikely to ever change (e.g. a static view on the screen as in this example).
    //
    // If it's possible for the context to change, then a delegate pattern is a preferred solution
    // because it will allow the delegate to request the new context each time the transition
    // begins. This can be helpful in building photo album transitions, for example.
    //
    // Note that in this example we're populating the contextual transition with the tapped view.
    // Our rudimentary transition will animate the context view to the center of the screen from its
    // current location.
    controller.mdm_transitionController.transition = CompositeTransition(transitions: [
      FadeTransition(target: .foreView),
      ContextualTransition(contextView: tapGesture.view!)
    ])
    present(controller, animated: true)
  }
  override func viewDidLoad() {
    super.viewDidLoad()
    let square = UIView(frame: .init(x: 16, y: 200, width: 128, height: 128))
    square.autoresizingMask = [.flexibleLeftMargin, .flexibleTopMargin,
                               .flexibleRightMargin, .flexibleBottomMargin]
    square.backgroundColor = .blue
    view.addSubview(square)
    let circle = UIView(frame: .init(x: 64, y: 400, width: 128, height: 128))
    circle.autoresizingMask = [.flexibleLeftMargin, .flexibleTopMargin,
                               .flexibleRightMargin, .flexibleBottomMargin]
    circle.backgroundColor = .red
    view.addSubview(circle)
    square.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(didTap(_:))))
    circle.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(didTap(_:))))
  }
  override func exampleInformation() -> ExampleInfo {
    return .init(title: type(of: self).catalogBreadcrumbs().last!,
                 instructions: "Tap to present a modal transition.")
  }
}
private class ContextualTransition: NSObject, Transition {
  // Store the context for the lifetime of the transition.
  let contextView: UIView
  init(contextView: UIView) {
    self.contextView = contextView
  }
  func start(with context: TransitionContext) {
    // A small helper function for creating bi-directional animations.
    // See https://github.com/material-motion/motion-animator-objc for a more versatile
    // bidirectional Core Animation implementation.
    let addAnimationToLayer: (CABasicAnimation, CALayer) -> Void = { animation, layer in
      if context.direction == .backward {
        let swap = animation.fromValue
        animation.fromValue = animation.toValue
        animation.toValue = swap
      }
      layer.add(animation, forKey: animation.keyPath)
      layer.setValue(animation.toValue, forKeyPath: animation.keyPath!)
    }
    let snapshotter = TransitionViewSnapshotter(containerView: context.containerView)
    context.defer {
      snapshotter.removeAllSnapshots()
    }
    CATransaction.begin()
    CATransaction.setCompletionBlock {
      context.transitionDidEnd()
    }
    // We use a snapshot view to accomplish two things:
    // 1) To not affect the context view's state.
    // 2) To allow our context view to appear in front of the fore view controller's view.
    //
    // The provided view snapshotter will automatically hide the snapshotted view and remove the
    // snapshot view upon completion of the transition.
    let snapshotContextView = snapshotter.snapshot(of: contextView,
                                                   isAppearing: context.direction == .backward)
    let expand = CABasicAnimation(keyPath: "transform.scale.xy")
    expand.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
    expand.fromValue = 1
    expand.toValue = 2
    addAnimationToLayer(expand, snapshotContextView.layer)
    let shift = CASpringAnimation(keyPath: "position")
    shift.damping = 500
    shift.stiffness = 1000
    shift.mass = 3
    shift.duration = 0.5
    shift.fromValue = snapshotContextView.layer.position
    shift.toValue = CGPoint(x: context.foreViewController.view.bounds.midX,
                            y: context.foreViewController.view.bounds.midY)
    addAnimationToLayer(shift, snapshotContextView.layer)
    context.compose(with: FadeTransition(target: .target(snapshotContextView),
                                         style: .fadeOut))
    CATransaction.commit()
  }
}
private class DestinationViewController: ExampleViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = .primaryColor
    view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(didTap)))
  }
    dismiss(animated: true)
  }
}


PhotoCollectionViewCell

/*
 */
import Foundation
import UIKit
class PhotoCollectionViewCell: UICollectionViewCell {
  let imageView = UIImageView()
  override init(frame: CGRect) {
    super.init(frame: frame)
    imageView.contentMode = .scaleAspectFill
    imageView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    imageView.frame = bounds
    imageView.clipsToBounds = true
    contentView.addSubview(imageView)
  }
  required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
}