// Copyright 2024 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/drive_file_picker/coordinator/drive_file_picker_mediator.h"
#import "ios/chrome/browser/drive/model/drive_list.h"
#import "ios/chrome/browser/drive/model/drive_service.h"
#import "ios/chrome/browser/drive_file_picker/coordinator/drive_file_picker_mediator_delegate.h"
#import "ios/chrome/browser/drive_file_picker/ui/drive_file_picker_consumer.h"
#import "ios/chrome/browser/drive_file_picker/ui/drive_item_identifier.h"
#import "ios/chrome/browser/shared/public/commands/command_dispatcher.h"
#import "ios/chrome/browser/shared/public/commands/drive_file_picker_commands.h"
#import "ios/chrome/browser/signin/model/chrome_account_manager_service.h"
#import "ios/chrome/browser/signin/model/system_identity.h"
#import "ios/chrome/browser/ui/menu/browser_action_factory.h"
#import "ios/chrome/browser/web/model/choose_file/choose_file_tab_helper.h"
#import "ios/web/public/web_state.h"
namespace {
// A param to add to the default query to order the drive items as folders
// first, modification time as the second criteria.
NSString* orderByParam = @"folder,modifiedTime desc";
} // namespace
@implementation DriveFilePickerMediator {
base::WeakPtr<web::WebState> _webState;
id<SystemIdentity> _identity;
// The folder associated to the current `BrowseDriveFilePickerCoordinator`.
DriveItemIdentifier* _driveFolderID;
raw_ptr<drive::DriveService> _driveService;
std::unique_ptr<DriveList> _driveList;
DriveListQuery _lastQuery;
std::vector<DriveItem> _fetchedDriveItems;
raw_ptr<ChromeAccountManagerService> _accountManagerService;
}
- (instancetype)initWithWebState:(web::WebState*)webState
identity:(id<SystemIdentity>)identity
driveFolderID:(DriveItemIdentifier*)driveFolderID
driveService:(drive::DriveService*)driveService
accountManagerService:
(ChromeAccountManagerService*)accountManagerService {
self = [super init];
if (self) {
CHECK(webState);
CHECK(identity);
CHECK(accountManagerService);
_webState = webState->GetWeakPtr();
_identity = identity;
_driveFolderID = driveFolderID;
_driveService = driveService;
_accountManagerService = accountManagerService;
_fetchedDriveItems = {};
}
return self;
}
- (void)disconnect {
if (_webState) {
ChooseFileTabHelper* tab_helper =
ChooseFileTabHelper::GetOrCreateForWebState(_webState.get());
if (tab_helper->IsChoosingFiles()) {
tab_helper->StopChoosingFiles();
}
_webState = nullptr;
_driveService = nullptr;
_driveList = nullptr;
_accountManagerService = nullptr;
}
}
- (void)setConsumer:(id<DriveFilePickerConsumer>)consumer {
_consumer = consumer;
[_consumer setSelectedUserIdentityEmail:_identity.userEmail];
[self configureConsumerIdentitiesMenu];
if (_driveFolderID) {
[_consumer setCurrentDriveFolderTitle:_driveFolderID.title];
}
}
- (void)updateSelectedIdentity:(id<SystemIdentity>)selectedIdentity {
if (_identity == selectedIdentity) {
return;
}
_identity = selectedIdentity;
[_consumer setSelectedUserIdentityEmail:_identity.userEmail];
[self configureConsumerIdentitiesMenu];
}
#pragma mark - DriveFilePickerMutator
- (void)selectDriveItem:(DriveItemIdentifier*)driveItem {
switch (driveItem.type) {
case DriveItemType::kFile:
case DriveItemType::kFolder:
[self.delegate browseDriveFolderWithMediator:self
driveFolderID:driveItem];
}
}
- (void)fetchDriveItemsForFolderID {
_driveList = _driveService->CreateList(_identity);
DriveListQuery query;
query.folder_identifier = _driveFolderID.identifier;
query.order_by = orderByParam;
_lastQuery = query;
__weak __typeof(self) weakSelf = self;
_driveList->ListItems(query, base::BindOnce(^(const DriveListResult& result) {
[weakSelf handleListItemsResponse:result];
}));
}
#pragma mark - Private
- (void)handleListItemsResponse:(const DriveListResult&)result {
_fetchedDriveItems.insert(_fetchedDriveItems.end(), result.items.begin(),
result.items.end());
NSMutableArray* res = [[NSMutableArray alloc] init];
for (auto item : _fetchedDriveItems) {
DriveItemIdentifier* driveItem = [[DriveItemIdentifier alloc]
initWithIdentifier:item.identifier
title:item.name
icon:nil
creationDate:[item.modified_time description]
type:(item.is_folder) ? DriveItemType::kFolder
: DriveItemType::kFile];
[res addObject:driveItem];
}
[self.consumer populateItems:res];
}
- (void)identityUpdatedWithSelectedIdentity:
(id<SystemIdentity>)selectedIdentity {
if (_identity == selectedIdentity) {
return;
}
[self.driveFilePickerHandler
setDriveFilePickerSelectedIdentity:selectedIdentity];
}
- (void)configureConsumerIdentitiesMenu {
ActionFactory* actionFactory = [[ActionFactory alloc]
initWithScenario:kMenuScenarioHistogramSelectDriveIdentityEntry];
__weak __typeof(self) weakSelf = self;
auto actionResult = ^(id<SystemIdentity> identity) {
[weakSelf identityUpdatedWithSelectedIdentity:identity];
};
// TODO(crbug.com/344812396): Add the identites block.
UIMenuElement* identitiesMenu = [actionFactory
menuToSelectDriveIdentityWithIdentities:_accountManagerService
->GetAllIdentities()
currentIdentity:_identity
block:actionResult];
// TODO(crbug.com/344812396): Add the new account block.
UIAction* addAccountAction =
[actionFactory actionToAddAccountForDriveWithBlock:nil];
[_consumer setEmailsMenu:[UIMenu menuWithChildren:@[
addAccountAction, identitiesMenu
]]];
}
@end