diff --git a/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/UseCaseModule.kt b/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/UseCaseModule.kt index 968a21e3bb8..86443915eb7 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/UseCaseModule.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/UseCaseModule.kt @@ -60,6 +60,7 @@ import com.owncloud.android.domain.files.usecases.GetFileByRemotePathUseCase import com.owncloud.android.domain.files.usecases.GetFileWithSyncInfoByIdUseCase import com.owncloud.android.domain.files.usecases.GetFolderContentAsStreamUseCase import com.owncloud.android.domain.files.usecases.GetFolderContentUseCase +import com.owncloud.android.domain.files.usecases.GetIfFileFolderLocalUseCase import com.owncloud.android.domain.files.usecases.GetFolderImagesUseCase import com.owncloud.android.domain.files.usecases.GetPersonalRootFolderForAccountUseCase import com.owncloud.android.domain.files.usecases.GetSearchFolderContentUseCase @@ -166,6 +167,7 @@ val useCaseModule = module { factoryOf(::GetFolderContentAsStreamUseCase) factoryOf(::GetFolderContentUseCase) factoryOf(::GetFolderImagesUseCase) + factoryOf(::GetIfFileFolderLocalUseCase) factoryOf(::GetPersonalRootFolderForAccountUseCase) factoryOf(::GetSearchFolderContentUseCase) factoryOf(::GetSharedByLinkForAccountAsStreamUseCase) diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainFileListFragment.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainFileListFragment.kt index e2c1c3a05ae..31934c22373 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainFileListFragment.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainFileListFragment.kt @@ -474,8 +474,7 @@ class MainFileListFragment : Fragment(), } FileMenuOption.REMOVE -> { - val dialogRemove = RemoveFilesDialogFragment.newInstance(file, file.isAvailableLocally) - dialogRemove.show(requireActivity().supportFragmentManager, ConfirmationDialogFragment.FTAG_CONFIRMATION) + fileOperationsViewModel.showRemoveDialog(arrayListOf(file)) } FileMenuOption.OPEN_WITH -> { @@ -621,6 +620,22 @@ class MainFileListFragment : Fragment(), } } + fileOperationsViewModel.checkIfFileLocalLiveData.observe(viewLifecycleOwner, Event.EventObserver { + val fileActivity = (requireActivity() as FileActivity) + when (it) { + is UIResult.Loading -> fileActivity.showLoadingDialog(R.string.common_loading) + is UIResult.Success -> { + fileActivity.dismissLoadingDialog() + it.data?.let { result -> onShowRemoveDialog(result.first as ArrayList, result.second) } + } + + is UIResult.Error -> { + fileActivity.dismissLoadingDialog() + showMessageInSnackbar(resources.getString(R.string.common_error_unknown)) + } + } + }) + /* TransfersViewModel observables */ observeTransfers() @@ -938,6 +953,13 @@ class MainFileListFragment : Fragment(), } } + private fun onShowRemoveDialog(filesToRemove: ArrayList, isLocal: Boolean) { + val dialog = RemoveFilesDialogFragment.newInstance(filesToRemove, isLocal) + dialog.show(requireActivity().supportFragmentManager, ConfirmationDialogFragment.FTAG_CONFIRMATION) + fileListAdapter.clearSelection() + updateActionModeAfterTogglingSelected() + } + override fun onFolderNameSet(newFolderName: String, parentFolder: OCFile) { fileOperationsViewModel.performOperation(FileOperation.CreateFolder(newFolderName, parentFolder)) fileOperationsViewModel.createFolder.observe(viewLifecycleOwner, Event.EventObserver { uiResult: UIResult -> @@ -1099,11 +1121,7 @@ class MainFileListFragment : Fragment(), } R.id.action_remove_file -> { - // to handle using usecase - val dialog = RemoveFilesDialogFragment.newInstance(checkedFiles, false) - dialog.show(requireActivity().supportFragmentManager, ConfirmationDialogFragment.FTAG_CONFIRMATION) - fileListAdapter.clearSelection() - updateActionModeAfterTogglingSelected() + fileOperationsViewModel.showRemoveDialog(checkedFiles) return true } diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/operations/FileOperationsViewModel.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/operations/FileOperationsViewModel.kt index 3fd471a7f9f..756ed37d16a 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/operations/FileOperationsViewModel.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/operations/FileOperationsViewModel.kt @@ -36,6 +36,7 @@ import com.owncloud.android.domain.exceptions.NoNetworkConnectionException import com.owncloud.android.domain.files.model.OCFile import com.owncloud.android.domain.files.usecases.CopyFileUseCase import com.owncloud.android.domain.files.usecases.CreateFolderAsyncUseCase +import com.owncloud.android.domain.files.usecases.GetIfFileFolderLocalUseCase import com.owncloud.android.domain.files.usecases.ManageDeepLinkUseCase import com.owncloud.android.domain.files.usecases.MoveFileUseCase import com.owncloud.android.domain.files.usecases.RemoveFileUseCase @@ -68,6 +69,7 @@ class FileOperationsViewModel( private val unsetFilesAsAvailableOfflineUseCase: UnsetFilesAsAvailableOfflineUseCase, private val manageDeepLinkUseCase: ManageDeepLinkUseCase, private val setLastUsageFileUseCase: SetLastUsageFileUseCase, + private val getIfFileFolderLocalUseCase: GetIfFileFolderLocalUseCase, private val contextProvider: ContextProvider, private val coroutinesDispatcherProvider: CoroutinesDispatcherProvider, ) : ViewModel() { @@ -102,6 +104,9 @@ class FileOperationsViewModel( private val _deepLinkFlow = MutableStateFlow>?>(null) val deepLinkFlow: StateFlow>?> = _deepLinkFlow + private val _checkIfFileLocalLiveData = MediatorLiveData, Boolean>>>>() + val checkIfFileLocalLiveData: LiveData, Boolean>>>> = _checkIfFileLocalLiveData + val openDialogs = mutableListOf() // Used to save the last operation folder @@ -123,6 +128,17 @@ class FileOperationsViewModel( } } + fun showRemoveDialog(filesToRemove: List) { + runUseCaseWithResult( + coroutineDispatcher = coroutinesDispatcherProvider.io, + showLoading = true, + liveData = _checkIfFileLocalLiveData, + useCase = getIfFileFolderLocalUseCase, + useCaseParams = GetIfFileFolderLocalUseCase.Params(filesToRemove), + requiresConnection = false + ) + } + fun setLastUsageFile(file: OCFile) { viewModelScope.launch(coroutinesDispatcherProvider.io) { setLastUsageFileUseCase( diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/removefile/RemoveFilesDialogFragment.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/removefile/RemoveFilesDialogFragment.kt index dc197ec8cce..8619950b7c6 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/removefile/RemoveFilesDialogFragment.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/removefile/RemoveFilesDialogFragment.kt @@ -77,22 +77,19 @@ class RemoveFilesDialogFragment : ConfirmationDialogFragment(), ConfirmationDial * @return Dialog ready to show. */ @JvmStatic - fun newInstance(files: ArrayList): RemoveFilesDialogFragment { + fun newInstance(files: ArrayList, isLocal: Boolean): RemoveFilesDialogFragment { val messageStringId: Int var containsFolder = false - var containsDown = false var containsAvailableOffline = false for (file in files) { if (file.isFolder) { containsFolder = true } - if (file.isAvailableLocally) { - containsDown = true - } if (file.isAvailableOffline) { containsAvailableOffline = true } } + messageStringId = if (files.size == 1) { // choose message for a single file val file = files.first() @@ -109,7 +106,7 @@ class RemoveFilesDialogFragment : ConfirmationDialogFragment(), ConfirmationDial R.string.confirmation_remove_files_alert } } - val localRemoveButton = if (!containsAvailableOffline && (containsFolder || containsDown)) { + val localRemoveButton = if (!containsAvailableOffline && isLocal) { R.string.confirmation_remove_local } else { -1 @@ -139,8 +136,8 @@ class RemoveFilesDialogFragment : ConfirmationDialogFragment(), ConfirmationDial */ @JvmStatic @JvmName("newInstanceForSingleFile") - fun newInstance(file: OCFile): RemoveFilesDialogFragment { - return newInstance(arrayListOf(file)) + fun newInstance(file: OCFile, isLocal: Boolean): RemoveFilesDialogFragment { + return newInstance(arrayListOf(file), isLocal) } } } diff --git a/owncloudDomain/src/main/java/com/owncloud/android/domain/files/usecases/GetIfFileFolderLocalUseCase.kt b/owncloudDomain/src/main/java/com/owncloud/android/domain/files/usecases/GetIfFileFolderLocalUseCase.kt index 277944f1040..efb645a9b72 100644 --- a/owncloudDomain/src/main/java/com/owncloud/android/domain/files/usecases/GetIfFileFolderLocalUseCase.kt +++ b/owncloudDomain/src/main/java/com/owncloud/android/domain/files/usecases/GetIfFileFolderLocalUseCase.kt @@ -22,21 +22,24 @@ import com.owncloud.android.domain.BaseUseCaseWithResult import com.owncloud.android.domain.files.FileRepository import com.owncloud.android.domain.files.model.OCFile -class GetIfFileFolderLocalUseCase(private val fileRepository: FileRepository) : BaseUseCaseWithResult() { +class GetIfFileFolderLocalUseCase(private val fileRepository: FileRepository) : + BaseUseCaseWithResult, Boolean>, GetIfFileFolderLocalUseCase.Params>() { - override fun run(params: Params): Boolean = getIfFileFolderLocal(params.listOfFiles) + override fun run(params: Params): Pair, Boolean> = getIfFileFolderLocal(params.filesToRemove) + private fun getIfFileFolderLocal(filesToRemove: List): Pair, Boolean> { - private fun getIfFileFolderLocal(listOfFiles: List): Boolean { - listOfFiles.forEach { file -> - if (file.isFolder) { - if (getIfFileFolderLocal(fileRepository.getFolderContent(file.id!!))) return true - } else { - if (file.isAvailableLocally) return true + if (filesToRemove.any { it.isAvailableLocally }) { + return Pair(filesToRemove, true) + } else { + filesToRemove.filter { it.isFolder }.forEach { folder -> + if (getIfFileFolderLocal(fileRepository.getFolderContent(folder.id!!)).second) { + return Pair(filesToRemove, true) + } } } - return false + return Pair(filesToRemove, false) } - data class Params(val listOfFiles: List) + data class Params(val filesToRemove: List) }