chromium/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/regular/regular_grid_coordinator.mm

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/regular/regular_grid_coordinator.h"

#import "ios/chrome/browser/policy/model/policy_util.h"
#import "ios/chrome/browser/shared/model/browser/browser.h"
#import "ios/chrome/browser/shared/model/profile/profile_ios.h"
#import "ios/chrome/browser/shared/public/commands/command_dispatcher.h"
#import "ios/chrome/browser/shared/public/features/features.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/disabled_grid_view_controller.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_container_view_controller.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_empty_state_view.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_theme.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/regular/regular_grid_mediator.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/regular/regular_grid_view_controller.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/tab_group_grid_view_controller.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_mediator.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_view_controller.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/tab_context_menu/tab_context_menu_helper.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_constants.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/tab_groups/tab_group_coordinator.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/tab_groups/tab_group_view_controller.h"

@interface RegularGridCoordinator ()

// Redefined as readwrite.
@property(nonatomic, readwrite, strong)
    RegularGridViewController* gridViewController;

@end

@implementation RegularGridCoordinator {
  // Mediator for pinned Tabs.
  PinnedTabsMediator* _pinnedTabsMediator;
  // Context menu provider.
  TabContextMenuHelper* _contextMenuProvider;
  // Mediator of regular grid.
  RegularGridMediator* _mediator;
}

#pragma mark - Property Implementation.

- (RegularGridMediator*)mediator {
  CHECK(_mediator)
      << "RegularGridCoordinator's -start should be called before.";
  return _mediator;
}

- (RegularGridMediator*)regularGridMediator {
  CHECK(_mediator)
      << "RegularGridCoordinator's -start should be called before.";
  return _mediator;
}

- (PinnedTabsMediator*)pinnedTabsMediator {
  CHECK(_pinnedTabsMediator)
      << "RegularGridCoordinator's -start should be called before.";
  return _pinnedTabsMediator;
}

- (id<GridCommands>)gridHandler {
  CHECK(_mediator);
  return _mediator;
}

#pragma mark - Superclass overrides

- (LegacyGridTransitionLayout*)transitionLayout {
  if (IsTabGroupInGridEnabled()) {
    if (self.tabGroupCoordinator) {
      return [self.tabGroupCoordinator.viewController
                  .gridViewController transitionLayout];
    }
  }

  LegacyGridTransitionLayout* transitionLayout =
      [_gridViewController transitionLayout];

  if (IsPinnedTabsEnabled()) {
    LegacyGridTransitionLayout* pinnedTabsTransitionLayout =
        [self.pinnedTabsViewController transitionLayout];

    return [self combineTransitionLayout:transitionLayout
                    withTransitionLayout:pinnedTabsTransitionLayout];
  }

  return transitionLayout;
}

- (BOOL)isSelectedCellVisible {
  BOOL isSelectedCellVisible = [super isSelectedCellVisible];

  if (IsPinnedTabsEnabled() &&
      !(IsTabGroupInGridEnabled() && self.tabGroupCoordinator)) {
    isSelectedCellVisible |= self.pinnedTabsViewController.selectedCellVisible;
  }

  return isSelectedCellVisible;
}

#pragma mark - ChromeCoordinator

- (void)start {
  [self.browser->GetCommandDispatcher()
      startDispatchingToTarget:self
                   forProtocol:@protocol(TabsAnimationCommands)];

  BOOL regularModeEnabled =
      !IsIncognitoModeForced(self.browser->GetBrowserState()->GetPrefs());

  _contextMenuProvider = [[TabContextMenuHelper alloc]
        initWithBrowserState:self.browser->GetBrowserState()
      tabContextMenuDelegate:self.tabContextMenuDelegate];

  GridContainerViewController* container =
      [[GridContainerViewController alloc] init];
  self.gridContainerViewController = container;

  RegularGridViewController* gridViewController;
  if (regularModeEnabled) {
    gridViewController = [[RegularGridViewController alloc] init];
    container.containedViewController = gridViewController;
  } else {
    DisabledGridViewController* disabledViewController =
        [[DisabledGridViewController alloc]
            initWithPage:TabGridPageRegularTabs];
    disabledViewController.delegate = self.disabledTabViewControllerDelegate;
    self.disabledViewController = disabledViewController;
    container.containedViewController = self.disabledViewController;
  }

  self.gridViewController = gridViewController;

  _mediator = [[RegularGridMediator alloc] initWithModeHolder:self.modeHolder];
  _mediator.consumer = gridViewController;

  gridViewController.dragDropHandler = _mediator;
  gridViewController.mutator = _mediator;
  gridViewController.gridProvider = _mediator;
  gridViewController.menuProvider = _contextMenuProvider;

  // If regular is enabled then the grid exists and it is not disabled.
  // TODO(crbug.com/40273478): Get disabled status from the mediator.
  if (gridViewController) {
    gridViewController.dragDropHandler = _mediator;
    // TODO(crbug.com/40273478): Move the following lines to the grid itself
    // when specific grid file will be created.
    gridViewController.view.accessibilityIdentifier = kRegularTabGridIdentifier;
    gridViewController.emptyStateView =
        [[TabGridEmptyStateView alloc] initWithPage:TabGridPageRegularTabs];
    gridViewController.emptyStateView.accessibilityIdentifier =
        kTabGridRegularTabsEmptyStateIdentifier;
    gridViewController.theme = GridThemeLight;
    gridViewController.suggestedActionsDelegate = _mediator;

    self.gridContainerViewController.containedViewController =
        gridViewController;
  }

  if (IsPinnedTabsEnabled()) {
    PinnedTabsViewController* pinnedTabsViewController =
        [[PinnedTabsViewController alloc] init];
    self.pinnedTabsViewController = pinnedTabsViewController;

    _pinnedTabsMediator =
        [[PinnedTabsMediator alloc] initWithConsumer:pinnedTabsViewController];

    _pinnedTabsMediator.browser = self.browser;
    pinnedTabsViewController.menuProvider = _contextMenuProvider;
    pinnedTabsViewController.dragDropHandler = _pinnedTabsMediator;
  }

  [super start];
}

- (void)stop {
  [self.browser->GetCommandDispatcher() stopDispatchingToTarget:self];

  _pinnedTabsMediator = nil;
  _contextMenuProvider = nil;

  [super stop];
}

#pragma mark - TabsAnimationCommands

- (void)animateTabsClosureForTabs:(std::set<web::WebStateID>)tabsToClose
                           groups:
                               (std::map<tab_groups::TabGroupId, std::set<int>>)
                                   groupsWithTabsToClose
                  allInactiveTabs:(BOOL)animateAllInactiveTabs
                completionHandler:(ProceduralBlock)completionHandler {
  [self hideTabGroup];  // Make sure that no tab group is being displayed.
  [_gridViewController animateTabsClosureForTabs:tabsToClose
                                          groups:groupsWithTabsToClose
                                 allInactiveTabs:animateAllInactiveTabs
                               completionHandler:completionHandler];
}

#pragma mark - Public

- (void)stopChildCoordinators {
  [super stopChildCoordinators];
  [self.pinnedTabsViewController dismissModals];
}

@end