[go: nahoru, domu]

blob: c290fa8d8d7e29806f460a96cfff243a8e7d3d0b [file] [log] [blame]
// Copyright 2022 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/bookmarks/folder_editor/bookmarks_folder_editor_coordinator.h"
#import "base/apple/foundation_util.h"
#import "base/check.h"
#import "base/check_op.h"
#import "base/metrics/user_metrics.h"
#import "base/metrics/user_metrics_action.h"
#import "components/bookmarks/browser/bookmark_node.h"
#import "ios/chrome/browser/bookmarks/account_bookmark_model_factory.h"
#import "ios/chrome/browser/bookmarks/local_or_syncable_bookmark_model_factory.h"
#import "ios/chrome/browser/shared/model/browser/browser.h"
#import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h"
#import "ios/chrome/browser/shared/public/commands/command_dispatcher.h"
#import "ios/chrome/browser/shared/public/commands/snackbar_commands.h"
#import "ios/chrome/browser/signin/authentication_service_factory.h"
#import "ios/chrome/browser/sync/sync_service_factory.h"
#import "ios/chrome/browser/ui/bookmarks/bookmark_navigation_controller.h"
#import "ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_coordinator.h"
#import "ios/chrome/browser/ui/bookmarks/folder_chooser/bookmarks_folder_chooser_coordinator_delegate.h"
#import "ios/chrome/browser/ui/bookmarks/folder_editor/bookmarks_folder_editor_view_controller.h"
@interface BookmarksFolderEditorCoordinator () <
BookmarksFolderEditorViewControllerDelegate,
BookmarksFolderChooserCoordinatorDelegate,
UIAdaptivePresentationControllerDelegate> {
// The navigation controller is `nullptr` if the folder chooser view
// controller is pushed into the base navigation controller.
// Otherwise, the navigation controller is presented in the base view
// controller.
UINavigationController* _navigationController;
BookmarksFolderEditorViewController* _viewController;
// Coordinator to show the folder chooser UI.
BookmarksFolderChooserCoordinator* _folderChooserCoordinator;
// Parent folder to `_folderNode`. Should never be `nullptr`.
const bookmarks::BookmarkNode* _parentFolderNode;
// If `_folderNode` is `nullptr`, the user is adding a new folder. Otherwise
// the user is editing an existing folder.
const bookmarks::BookmarkNode* _folderNode;
}
@end
@implementation BookmarksFolderEditorCoordinator
@synthesize baseNavigationController = _baseNavigationController;
- (instancetype)initWithBaseNavigationController:
(UINavigationController*)navigationController
browser:(Browser*)browser
parentFolderNode:
(const bookmarks::BookmarkNode*)
parentFolder {
DCHECK(parentFolder);
self = [super initWithBaseViewController:navigationController
browser:browser];
if (self) {
_baseNavigationController = navigationController;
_parentFolderNode = parentFolder;
}
return self;
}
- (instancetype)initWithBaseViewController:(UIViewController*)baseViewController
browser:(Browser*)browser
folderNode:
(const bookmarks::BookmarkNode*)folder {
DCHECK(folder);
DCHECK(folder->parent());
self = [super initWithBaseViewController:baseViewController browser:browser];
if (self) {
_folderNode = folder;
_parentFolderNode = folder->parent();
}
return self;
}
- (void)start {
[super start];
// TODO(crbug.com/1402758): Create a mediator.
ChromeBrowserState* browserState =
self.browser->GetBrowserState()->GetOriginalChromeBrowserState();
bookmarks::BookmarkModel* localOrSyncableBookmarkModel =
ios::LocalOrSyncableBookmarkModelFactory::GetForBrowserState(
browserState);
bookmarks::BookmarkModel* accountBookmarkModel =
ios::AccountBookmarkModelFactory::GetForBrowserState(browserState);
AuthenticationService* authService =
AuthenticationServiceFactory::GetForBrowserState(browserState);
syncer::SyncService* syncService =
SyncServiceFactory::GetForBrowserState(browserState);
_viewController = [[BookmarksFolderEditorViewController alloc]
initWithLocalOrSyncableBookmarkModel:localOrSyncableBookmarkModel
accountBookmarkModel:accountBookmarkModel
folderNode:_folderNode
parentFolderNode:_parentFolderNode
authenticationService:authService
syncService:syncService
browser:self.browser];
_viewController.delegate = self;
_viewController.snackbarCommandsHandler = HandlerForProtocol(
self.browser->GetCommandDispatcher(), SnackbarCommands);
if (_baseNavigationController) {
[_baseNavigationController pushViewController:_viewController animated:YES];
} else {
DCHECK(!_navigationController);
_navigationController = [[BookmarkNavigationController alloc]
initWithRootViewController:_viewController];
_navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
_navigationController.presentationController.delegate = self;
[self.baseViewController presentViewController:_navigationController
animated:YES
completion:nil];
}
}
- (void)stop {
[super stop];
// Stop child coordinator before stopping `self`.
[self stopBookmarksFolderChooserCoordinator];
DCHECK(_viewController);
if (_navigationController) {
[self.baseViewController dismissViewControllerAnimated:YES completion:nil];
_navigationController.presentationController.delegate = nil;
_navigationController = nil;
} else if (_baseNavigationController &&
_baseNavigationController.presentingViewController) {
// If `_baseNavigationController.presentingViewController` is `nil` then
// the parent coordinator (who owns the `_baseNavigationController`) has
// already been dismissed. In this case `_baseNavigationController` itself
// is no longer being presented and this coordinator was dismissed as well.
DCHECK_EQ(_baseNavigationController.topViewController, _viewController);
[_baseNavigationController popViewControllerAnimated:YES];
} else if (!_baseNavigationController) {
// If there is no `_baseNavigationController` and `_navigationController`,
// the view controller has been already dismissed. See
// `presentationControllerDidDismiss:` and
// `bookmarksFolderEditorDidDismiss:`.
// Therefore `self.baseViewController.presentedViewController` must be
// `nil`.
DCHECK(!self.baseViewController.presentedViewController);
}
[_viewController disconnect];
_viewController = nil;
}
- (void)dealloc {
DCHECK(!_viewController);
}
- (BOOL)canDismiss {
DCHECK(_viewController);
return [_viewController canDismiss];
}
#pragma mark - BookmarksFolderEditorViewControllerDelegate
- (void)showBookmarksFolderChooserWithParentFolder:
(const bookmarks::BookmarkNode*)parent
hiddenNodes:
(const std::set<
const bookmarks::BookmarkNode*>&)
hiddenNodes {
DCHECK(!_folderChooserCoordinator);
_folderChooserCoordinator = [[BookmarksFolderChooserCoordinator alloc]
initWithBaseNavigationController:(_baseNavigationController
? _baseNavigationController
: _navigationController)
browser:self.browser
hiddenNodes:hiddenNodes];
_folderChooserCoordinator.allowsNewFolders = NO;
[_folderChooserCoordinator setSelectedFolder:parent];
_folderChooserCoordinator.delegate = self;
[_folderChooserCoordinator start];
}
- (void)bookmarksFolderEditor:(BookmarksFolderEditorViewController*)folderEditor
didFinishEditingFolder:(const bookmarks::BookmarkNode*)folder {
[_delegate bookmarksFolderEditorCoordinator:self
didFinishEditingFolderNode:folder];
}
- (void)bookmarksFolderEditorDidDeleteEditedFolder:
(BookmarksFolderEditorViewController*)folderEditor {
// Deleting the folder is only allowed when the user is editing an existing
// folder.
DCHECK(_folderNode);
[_delegate bookmarksFolderEditorCoordinatorShouldStop:self];
}
- (void)bookmarksFolderEditorDidCancel:
(BookmarksFolderEditorViewController*)folderEditor {
[_delegate bookmarksFolderEditorCoordinatorShouldStop:self];
}
- (void)bookmarksFolderEditorDidDismiss:
(BookmarksFolderEditorViewController*)folderEditor {
DCHECK(_baseNavigationController);
_baseNavigationController = nil;
[_delegate bookmarksFolderEditorCoordinatorShouldStop:self];
}
- (void)bookmarksFolderEditorWillCommitTitleChange:
(BookmarksFolderEditorViewController*)controller {
[_delegate bookmarksFolderEditorWillCommitTitleChange:self];
}
#pragma mark - BookmarksFolderChooserCoordinatorDelegate
- (void)bookmarksFolderChooserCoordinatorDidConfirm:
(BookmarksFolderChooserCoordinator*)coordinator
withSelectedFolder:
(const bookmarks::BookmarkNode*)folder {
DCHECK(_folderChooserCoordinator);
DCHECK(folder);
[self stopBookmarksFolderChooserCoordinator];
[_viewController updateParentFolder:folder];
}
- (void)bookmarksFolderChooserCoordinatorDidCancel:
(BookmarksFolderChooserCoordinator*)coordinator {
DCHECK(_folderChooserCoordinator);
[self stopBookmarksFolderChooserCoordinator];
}
#pragma mark - UIAdaptivePresentationControllerDelegate
- (void)presentationControllerDidAttemptToDismiss:
(UIPresentationController*)presentationController {
base::RecordAction(
base::UserMetricsAction("IOSBookmarksFolderEditorClosedWithSwipeDown"));
[_viewController presentationControllerDidAttemptToDismiss];
}
- (void)presentationControllerWillDismiss:
(UIPresentationController*)presentationController {
// Resign first responder if trying to dismiss the VC so the keyboard doesn't
// linger until the VC dismissal has completed.
[_viewController.view endEditing:YES];
}
- (void)presentationControllerDidDismiss:
(UIPresentationController*)presentationController {
DCHECK(_navigationController);
_navigationController.presentationController.delegate = nil;
_navigationController = nil;
[_delegate bookmarksFolderEditorCoordinatorShouldStop:self];
}
- (BOOL)presentationControllerShouldDismiss:
(UIPresentationController*)presentationController {
return [self canDismiss];
}
#pragma mark - Private
- (void)stopBookmarksFolderChooserCoordinator {
[_folderChooserCoordinator stop];
_folderChooserCoordinator.delegate = nil;
_folderChooserCoordinator = nil;
}
@end