diff --git a/FileExplorer/FileExplorer/ActionsViewController.swift b/FileExplorer/FileExplorer/ActionsViewController.swift index aa5e46e..2a06185 100644 --- a/FileExplorer/FileExplorer/ActionsViewController.swift +++ b/FileExplorer/FileExplorer/ActionsViewController.swift @@ -35,8 +35,9 @@ final class ActionsViewController: UIViewController { private let toolbar = UIToolbar() private let contentViewController: UIViewController - - init(contentViewController: UIViewController) { + fileprivate let configuration: Configuration + init(configuration: Configuration, contentViewController: UIViewController) { + self.configuration = configuration self.contentViewController = contentViewController super.init(nibName: nil, bundle: nil) } @@ -57,11 +58,17 @@ final class ActionsViewController: UIViewController { toolbar.translatesAutoresizingMaskIntoConstraints = false toolbar.sizeToFit() toolbar.pinToBottom(of: view) - toolbar.items = [ - UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(handleShareButtonTap)), - UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil), - UIBarButtonItem(barButtonSystemItem: .trash, target: self, action: #selector(handleTrashButtonTap)) - ] + //always add the flexibleSpace + toolbar.items = [UIBarButtonItem]() + toolbar.items?.append(UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)) + if configuration.actionsConfiguration.canShareFiles + { + toolbar.items?.insert(UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(handleShareButtonTap)), at: 0) + } + if configuration.actionsConfiguration.canRemoveFiles + { + toolbar.items?.append(UIBarButtonItem(barButtonSystemItem: .trash, target: self, action: #selector(handleTrashButtonTap))) + } addContentChildViewController(contentViewController, insets: UIEdgeInsets(top: 0, left: 0, bottom: toolbar.bounds.height, right: 0)) navigationItem.title = contentViewController.navigationItem.title diff --git a/FileExplorer/FileExplorer/CheckmarkButton.swift b/FileExplorer/FileExplorer/CheckmarkButton.swift index 64cd7b7..2522149 100644 --- a/FileExplorer/FileExplorer/CheckmarkButton.swift +++ b/FileExplorer/FileExplorer/CheckmarkButton.swift @@ -51,6 +51,7 @@ final class CheckmarkButton: UIButton { borderColor = ColorPallete.gray isSelected = false addTarget(self, action: #selector(handleTouchUpInside), for: .touchUpInside) + isUserInteractionEnabled = false } required init?(coder aDecoder: NSCoder) { diff --git a/FileExplorer/FileExplorer/Configuration.swift b/FileExplorer/FileExplorer/Configuration.swift index 4d94b07..5054fe6 100644 --- a/FileExplorer/FileExplorer/Configuration.swift +++ b/FileExplorer/FileExplorer/Configuration.swift @@ -31,6 +31,7 @@ struct Configuration { } struct ActionsConfiguration { + var canShareFiles: Bool = false var canRemoveFiles: Bool = false var canRemoveDirectories: Bool = false var canChooseFiles: Bool = false diff --git a/FileExplorer/FileExplorer/DirectoryContentViewController.swift b/FileExplorer/FileExplorer/DirectoryContentViewController.swift index 30fe08c..c6c4fb6 100644 --- a/FileExplorer/FileExplorer/DirectoryContentViewController.swift +++ b/FileExplorer/FileExplorer/DirectoryContentViewController.swift @@ -111,6 +111,24 @@ final class DirectoryContentViewController: UICollectionViewController { activeNavigationItemTitle = viewModel.title view.isUserInteractionEnabled = viewModel.isUserInteractionEnabled setEditing(viewModel.isEditing, animated: true) + //get the selection states from the view model and syncronize them + let selectedCellPaths = viewModel.indexPathsOfSelectedCells + for i in 0...viewModel.numberOfItems(inSection: 0) + { + guard let collectionView = collectionView else { return } + let searchIndexPath = IndexPath(item: i, section: 0) + var selectedIndexPath = selectedCellPaths.index(of: searchIndexPath) + var selected = selectedIndexPath != nil ? true : false + if selected + { + collectionView.selectItem(at: searchIndexPath, animated: true, scrollPosition: UICollectionViewScrollPosition.left) + } + else + { + collectionView.deselectItem(at: searchIndexPath, animated: false) + } + } + } override func setEditing(_ editing: Bool, animated: Bool) { diff --git a/FileExplorer/FileExplorer/DirectoryContentViewModel.swift b/FileExplorer/FileExplorer/DirectoryContentViewModel.swift index 627d913..a02e4f3 100644 --- a/FileExplorer/FileExplorer/DirectoryContentViewModel.swift +++ b/FileExplorer/FileExplorer/DirectoryContentViewModel.swift @@ -148,9 +148,10 @@ final class DirectoryContentViewModel { } let numberOfSelectedItemsIsAllowed = configuration.actionsConfiguration.allowsMultipleSelection ? selectedItems.count > 0 : selectedItems.count == 1 + return !fileService.isDeletionInProgress && selectedItemsAreAllowedToBeSelected && numberOfSelectedItemsIsAllowed } - + var selectActionTitle: String { return NSLocalizedString("Choose", comment: "") } @@ -162,7 +163,7 @@ final class DirectoryContentViewModel { private let configuration: Configuration private let fileSpecifications: FileSpecifications private let fileService: FileService - + init(item: LoadedDirectoryItem, fileSpecifications: FileSpecifications, configuration: Configuration, fileService: FileService = LocalStorageFileService()) { self.url = item.url self.fileSpecifications = fileSpecifications @@ -181,7 +182,14 @@ final class DirectoryContentViewModel { func select(at indexPath: IndexPath) { let item = self.item(for: indexPath) if isEditing { - selectedItems.append(item) + if(configuration.actionsConfiguration.allowsMultipleSelection) + { + selectedItems.append(item) + } + else{ + selectedItems.removeAll() + selectedItems.append(item) + } } else { delegate?.directoryViewModel(self, didSelectItem: item) } diff --git a/FileExplorer/FileExplorer/FileExplorerViewController.swift b/FileExplorer/FileExplorer/FileExplorerViewController.swift index 13b3691..9f21b83 100644 --- a/FileExplorer/FileExplorer/FileExplorerViewController.swift +++ b/FileExplorer/FileExplorer/FileExplorerViewController.swift @@ -48,6 +48,9 @@ public final class FileExplorerViewController: UIViewController { /// The URL of directory which is initialy presented by file explorer view controller. public var initialDirectoryURL: URL = URL.documentDirectory + /// A Boolean value indicating whether the user is allowed to remove files. + public var canShareFiles: Bool = true + /// A Boolean value indicating whether the user is allowed to remove files. public var canRemoveFiles: Bool = true @@ -113,7 +116,8 @@ public final class FileExplorerViewController: UIViewController { super.viewWillAppear(animated) let fileSpecifications = FileSpecifications(providers: fileSpecificationProviders) - let actionsConfiguration = ActionsConfiguration(canRemoveFiles: canRemoveFiles, + let actionsConfiguration = ActionsConfiguration(canShareFiles: canShareFiles, + canRemoveFiles: canRemoveFiles, canRemoveDirectories: canRemoveDirectories, canChooseFiles: canChooseFiles, canChooseDirectories: canChooseDirectories, diff --git a/FileExplorer/FileExplorer/FileItemPresentationCoordinator.swift b/FileExplorer/FileExplorer/FileItemPresentationCoordinator.swift index d4721bc..da57725 100644 --- a/FileExplorer/FileExplorer/FileItemPresentationCoordinator.swift +++ b/FileExplorer/FileExplorer/FileItemPresentationCoordinator.swift @@ -32,9 +32,11 @@ final class FileItemPresentationCoordinator { fileprivate weak var navigationController: UINavigationController? fileprivate let fileService: FileService fileprivate let fileSpecifications: FileSpecifications + fileprivate let configuration: Configuration fileprivate let item: Item - init(navigationController: UINavigationController, item: Item, fileSpecifications: FileSpecifications, fileService: FileService = LocalStorageFileService()) { + init(configuration: Configuration, navigationController: UINavigationController, item: Item, fileSpecifications: FileSpecifications, fileService: FileService = LocalStorageFileService()) { + self.configuration = configuration self.navigationController = navigationController self.item = item self.fileSpecifications = fileSpecifications @@ -69,7 +71,7 @@ final class FileItemPresentationCoordinator { private func makePresentingViewController(item: Item, builder: @escaping (LoadedItem) -> UIViewController) -> UIViewController { let viewController = LoadingViewController.make(item: item) { [weak self] loadedItem in let contentViewController = builder(loadedItem) - let actionsViewController = ActionsViewController(contentViewController: contentViewController) + let actionsViewController = ActionsViewController(configuration: self!.configuration, contentViewController: contentViewController) actionsViewController.delegate = self return actionsViewController } diff --git a/FileExplorer/FileExplorer/ItemPresentationCoordinator.swift b/FileExplorer/FileExplorer/ItemPresentationCoordinator.swift index 2750dc2..c08e0db 100644 --- a/FileExplorer/FileExplorer/ItemPresentationCoordinator.swift +++ b/FileExplorer/FileExplorer/ItemPresentationCoordinator.swift @@ -51,7 +51,7 @@ final class ItemPresentationCoordinator { switch item.type { case .file: - let coordinator = FileItemPresentationCoordinator(navigationController: navigationController, item: item, fileSpecifications: fileSpecifications) + let coordinator = FileItemPresentationCoordinator(configuration: configuration, navigationController: navigationController, item: item, fileSpecifications: fileSpecifications) coordinator.start(animated) childCoordinators.append(coordinator) case .directory: @@ -75,7 +75,7 @@ extension ItemPresentationCoordinator: DirectoryItemPresentationCoordinatorDeleg func directoryItemPresentationCoordinator(_ coordinator: DirectoryItemPresentationCoordinator, didSelectItemDetails item: Item) { guard let navigationController = navigationController else { fatalError() } - let coordinator = FileItemPresentationCoordinator(navigationController: navigationController, item: item, fileSpecifications: fileSpecifications) + let coordinator = FileItemPresentationCoordinator(configuration: configuration, navigationController: navigationController, item: item, fileSpecifications: fileSpecifications) childCoordinators.append(coordinator) coordinator.startDetailsPreview(true) }