// 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/incognito/incognito_grid_view_controller.h"
#import "ios/chrome/browser/incognito_reauth/ui_bundled/incognito_reauth_commands.h"
#import "ios/chrome/browser/incognito_reauth/ui_bundled/incognito_reauth_view.h"
#import "ios/chrome/browser/tabs/model/inactive_tabs/features.h"
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/base_grid_view_controller+subclassing.h"
#import "ios/chrome/common/material_timing.h"
#import "ios/chrome/common/ui/util/constraints_ui_util.h"
@implementation IncognitoGridViewController {
// A view to obscure incognito content when the user isn't authorized to
// see it.
IncognitoReauthView* _blockingView;
}
#pragma mark - Parent's functions
// Returns a configured header for the given index path.
- (UICollectionReusableView*)headerForSectionAtIndexPath:
(NSIndexPath*)indexPath {
if (IsInactiveTabButtonRefactoringEnabled()) {
// With the refactoring, the base class does the right thing.
return [super headerForSectionAtIndexPath:indexPath];
}
if (self.mode == TabGridMode::kNormal) {
return nil;
}
return [super headerForSectionAtIndexPath:indexPath];
}
- (UIContextMenuConfiguration*)collectionView:(UICollectionView*)collectionView
contextMenuConfigurationForItemAtIndexPaths:
(NSArray<NSIndexPath*>*)indexPaths
point:(CGPoint)point
API_AVAILABLE(ios(16)) {
// Don't allow long-press previews when the incognito reauth view is blocking
// the content.
if (self.contentNeedsAuthentication) {
return nil;
}
return [super collectionView:collectionView
contextMenuConfigurationForItemsAtIndexPaths:indexPaths
point:point];
}
#if !defined(__IPHONE_16_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_16_0
- (UIContextMenuConfiguration*)collectionView:(UICollectionView*)collectionView
contextMenuConfigurationForItemAtIndexPath:(NSIndexPath*)indexPath
point:(CGPoint)point {
// Don't allow long-press previews when the incognito reauth view is blocking
// the content.
if (self.contentNeedsAuthentication) {
return nil;
}
return [super collectionView:collectionView
contextMenuConfigurationForItemAtIndexPath:indexPath
point:point];
}
#endif
- (NSArray<UIDragItem*>*)collectionView:(UICollectionView*)collectionView
itemsForBeginningDragSession:(id<UIDragSession>)session
atIndexPath:(NSIndexPath*)indexPath {
if (self.contentNeedsAuthentication) {
// Don't support dragging items if the drag&drop handler is not set.
return @[];
}
return [super collectionView:collectionView
itemsForBeginningDragSession:session
atIndexPath:indexPath];
}
#pragma mark - IncognitoReauthConsumer
- (void)setItemsRequireAuthentication:(BOOL)require {
self.contentNeedsAuthentication = require;
if (require) {
if (!_blockingView) {
_blockingView = [[IncognitoReauthView alloc] init];
_blockingView.translatesAutoresizingMaskIntoConstraints = NO;
_blockingView.layer.zPosition = FLT_MAX;
// No need to show tab switcher button when already in the tab switcher.
_blockingView.tabSwitcherButton.hidden = YES;
// Hide the logo.
_blockingView.logoView.hidden = YES;
[_blockingView.authenticateButton
addTarget:self.reauthHandler
action:@selector(authenticateIncognitoContent)
forControlEvents:UIControlEventTouchUpInside];
}
[self.view addSubview:_blockingView];
_blockingView.alpha = 1;
AddSameConstraints(self.collectionView.frameLayoutGuide, _blockingView);
} else {
__weak IncognitoGridViewController* weakSelf = self;
[UIView animateWithDuration:kMaterialDuration1
animations:^{
[weakSelf hideBlockingView];
}
completion:^(BOOL finished) {
[weakSelf blockingViewDidHide:finished];
}];
}
}
#pragma mark - Private
// Sets properties that should be animated to remove the blocking view.
- (void)hideBlockingView {
_blockingView.alpha = 0;
}
// Cleans up after blocking view animation completed.
- (void)blockingViewDidHide:(BOOL)finished {
if (self.contentNeedsAuthentication) {
_blockingView.alpha = 1;
} else {
[_blockingView removeFromSuperview];
}
}
@end