diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ceb339f057..809b8c57094 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ ownCloud admins and users. * Change - Add new prefixes in commit messages of 3rd party contributors: [#4346](https://github.com/owncloud/android/pull/4346) * Enhancement - Correct "Local only" option in remove dialog: [#3936](https://github.com/owncloud/android/issues/3936) * Enhancement - Improvements in Manage Accounts view: [#4148](https://github.com/owncloud/android/issues/4148) +* Enhancement - New setting for manual removal of local storage: [#4174](https://github.com/owncloud/android/issues/4174) * Enhancement - New setting for automatic removal of local files: [#4175](https://github.com/owncloud/android/issues/4175) * Enhancement - Unit tests for repository classes - Part 1: [#4232](https://github.com/owncloud/android/issues/4232) * Enhancement - Add a warning in http connections: [#4284](https://github.com/owncloud/android/issues/4284) @@ -97,6 +98,14 @@ ownCloud admins and users. https://github.com/owncloud/android/issues/4148 https://github.com/owncloud/android/pull/4330 +* Enhancement - New setting for manual removal of local storage: [#4174](https://github.com/owncloud/android/issues/4174) + + A new icon has been added in Manage Accounts view to delete manually local + files. + + https://github.com/owncloud/android/issues/4174 + https://github.com/owncloud/android/pull/4334 + * Enhancement - New setting for automatic removal of local files: [#4175](https://github.com/owncloud/android/issues/4175) A new setting has been created to delete automatically downloaded files, when diff --git a/changelog/unreleased/4334 b/changelog/unreleased/4334 new file mode 100644 index 00000000000..89be1a9a3dd --- /dev/null +++ b/changelog/unreleased/4334 @@ -0,0 +1,6 @@ +Enhancement: New setting for manual removal of local storage + +A new icon has been added in Manage Accounts view to delete manually local files. + +https://github.com/owncloud/android/issues/4174 +https://github.com/owncloud/android/pull/4334 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 4fe51ca8d14..675526e1fdf 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/UseCaseModule.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/UseCaseModule.kt @@ -109,6 +109,7 @@ import com.owncloud.android.domain.webfinger.usecases.GetOwnCloudInstanceFromWeb import com.owncloud.android.domain.webfinger.usecases.GetOwnCloudInstancesFromAuthenticatedWebFingerUseCase import com.owncloud.android.usecases.accounts.RemoveAccountUseCase import com.owncloud.android.usecases.files.FilterFileMenuOptionsUseCase +import com.owncloud.android.usecases.files.RemoveLocalFilesForAccountUseCase import com.owncloud.android.usecases.files.RemoveLocallyFilesWithLastUsageOlderThanGivenTimeUseCase import com.owncloud.android.usecases.synchronization.SynchronizeFileUseCase import com.owncloud.android.usecases.synchronization.SynchronizeFolderUseCase @@ -176,6 +177,7 @@ val useCaseModule = module { factoryOf(::ManageDeepLinkUseCase) factoryOf(::MoveFileUseCase) factoryOf(::RemoveFileUseCase) + factoryOf(::RemoveLocalFilesForAccountUseCase) factoryOf(::RemoveLocallyFilesWithLastUsageOlderThanGivenTimeUseCase) factoryOf(::RenameFileUseCase) factoryOf(::SaveConflictUseCase) diff --git a/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/ViewModelModule.kt b/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/ViewModelModule.kt index f6b2f6177d4..76447ebfb55 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/ViewModelModule.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/ViewModelModule.kt @@ -101,7 +101,7 @@ val viewModelModule = module { viewModel { MigrationViewModel(MainApp.dataFolder, get(), get(), get(), get(), get(), get(), get()) } viewModel { TransfersViewModel(get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get()) } viewModel { ReceiveExternalFilesViewModel(get(), get(), get()) } - viewModel { AccountsManagementViewModel(get()) } + viewModel { AccountsManagementViewModel(get(), get(), get()) } viewModel { (accountName: String, showPersonalSpace: Boolean) -> SpacesListViewModel(get(), get(), get(), get(), get(), accountName, showPersonalSpace) } diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/accounts/AccountsManagementActivity.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/accounts/AccountsManagementActivity.kt index 3e8a1236303..18136c1392c 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/accounts/AccountsManagementActivity.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/accounts/AccountsManagementActivity.kt @@ -2,8 +2,9 @@ * ownCloud Android client application * * @author Javier Rodríguez Pérez + * @author Aitor Ballesteros Pavón * - * Copyright (C) 2022 ownCloud GmbH. + * Copyright (C) 2024 ownCloud GmbH. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -28,13 +29,17 @@ import android.accounts.OperationCanceledException import android.content.Intent import android.os.Bundle import android.view.MenuItem +import androidx.appcompat.app.AlertDialog import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.owncloud.android.MainApp.Companion.accountType import com.owncloud.android.MainApp.Companion.initDependencyInjection import com.owncloud.android.R +import com.owncloud.android.extensions.collectLatestLifecycleFlow +import com.owncloud.android.extensions.showErrorInSnackbar import com.owncloud.android.presentation.accounts.RemoveAccountDialogFragment.Companion.newInstance import com.owncloud.android.presentation.authentication.AccountUtils +import com.owncloud.android.presentation.common.UIResult import com.owncloud.android.ui.activity.FileActivity import com.owncloud.android.ui.activity.FileDisplayActivity import com.owncloud.android.ui.dialog.ConfirmationDialogFragment @@ -73,6 +78,8 @@ class AccountsManagementActivity : FileActivity(), AccountsManagementAdapter.Acc displayShowTitleEnabled = true ) + subscribeToViewModels() + } override fun onStart() { @@ -196,6 +203,39 @@ class AccountsManagementActivity : FileActivity(), AccountsManagementAdapter.Acc } + override fun cleanAccountLocalStorage(account: Account) { + val dialog = AlertDialog.Builder(this) + .setTitle(getString(R.string.clean_data_account_title)) + .setIcon(R.drawable.ic_warning) + .setMessage(getString(R.string.clean_data_account_message)) + .setPositiveButton(getString(R.string.clean_data_account_button_yes)) { dialog, _ -> + accountsManagementViewModel.cleanAccountLocalStorage(account.name) + dialog.dismiss() + } + .setNegativeButton(R.string.drawer_close) { dialog, _ -> + dialog.dismiss() + } + .create() + dialog.show() + } + + private fun subscribeToViewModels() { + collectLatestLifecycleFlow(accountsManagementViewModel.cleanAccountLocalStorageFlow) { event -> + event?.peekContent()?.let { uiResult -> + when (uiResult) { + is UIResult.Loading -> showLoadingDialog(R.string.common_loading) + is UIResult.Success -> dismissLoadingDialog() + is UIResult.Error -> { + dismissLoadingDialog() + showErrorInSnackbar(R.string.common_error_unknown, uiResult.error) + Timber.e(uiResult.error) + } + + } + } + } + } + override fun run(future: AccountManagerFuture) { if (future.isDone) { // Create new adapter with the remaining accounts diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/accounts/AccountsManagementAdapter.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/accounts/AccountsManagementAdapter.kt index d7d945ec53f..f621d84e689 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/accounts/AccountsManagementAdapter.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/accounts/AccountsManagementAdapter.kt @@ -2,8 +2,9 @@ * ownCloud Android client application * * @author Javier Rodríguez Pérez + * @author Aitor Ballesteros Pavón * - * Copyright (C) 2022 ownCloud GmbH. + * Copyright (C) 2024 ownCloud GmbH. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -99,6 +100,11 @@ class AccountsManagementAdapter(private val accountListener: AccountAdapterListe holder.binding.ticker.visibility = View.INVISIBLE } + /// bind listener to clean local storage from account + holder.binding.cleanAccountLocalStorageButton.apply { + setImageResource(R.drawable.ic_clean_account) + setOnClickListener { accountListener.cleanAccountLocalStorage(account) } + } /// bind listener to remove account holder.binding.removeButton.apply { setImageResource(R.drawable.ic_action_delete_grey) @@ -156,6 +162,7 @@ class AccountsManagementAdapter(private val accountListener: AccountAdapterListe */ interface AccountAdapterListener { fun removeAccount(account: Account) + fun cleanAccountLocalStorage(account: Account) fun createAccount() fun switchAccount(position: Int) } diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/accounts/AccountsManagementViewModel.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/accounts/AccountsManagementViewModel.kt index be4b0caccaa..57896048b27 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/accounts/AccountsManagementViewModel.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/accounts/AccountsManagementViewModel.kt @@ -2,8 +2,9 @@ * ownCloud Android client application * * @author Javier Rodríguez Pérez + * @author Aitor Ballesteros Pavón * - * Copyright (C) 2022 ownCloud GmbH. + * Copyright (C) 2024 ownCloud GmbH. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -22,12 +23,24 @@ package com.owncloud.android.presentation.accounts import android.accounts.Account import androidx.lifecycle.ViewModel +import com.owncloud.android.domain.utils.Event +import com.owncloud.android.extensions.ViewModelExt.runUseCaseWithResult +import com.owncloud.android.presentation.common.UIResult import com.owncloud.android.providers.AccountProvider +import com.owncloud.android.providers.CoroutinesDispatcherProvider +import com.owncloud.android.usecases.files.RemoveLocalFilesForAccountUseCase +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow class AccountsManagementViewModel( - private val accountProvider: AccountProvider + private val accountProvider: AccountProvider, + private val removeLocalFilesForAccountUseCase: RemoveLocalFilesForAccountUseCase, + private val coroutinesDispatcherProvider: CoroutinesDispatcherProvider, ) : ViewModel() { + private val _cleanAccountLocalStorageFlow = MutableStateFlow>?>(null) + val cleanAccountLocalStorageFlow: StateFlow>?> = _cleanAccountLocalStorageFlow + fun getLoggedAccounts(): Array { return accountProvider.getLoggedAccounts() } @@ -35,4 +48,14 @@ class AccountsManagementViewModel( fun getCurrentAccount(): Account? { return accountProvider.getCurrentOwnCloudAccount() } + + fun cleanAccountLocalStorage(accountName: String) { + runUseCaseWithResult( + coroutineDispatcher = coroutinesDispatcherProvider.io, + showLoading = true, + flow = _cleanAccountLocalStorageFlow, + useCase = removeLocalFilesForAccountUseCase, + useCaseParams = RemoveLocalFilesForAccountUseCase.Params(accountName), + ) + } } diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/releasenotes/ReleaseNotesViewModel.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/releasenotes/ReleaseNotesViewModel.kt index 64d9e6d7475..70b396a8ba1 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/releasenotes/ReleaseNotesViewModel.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/releasenotes/ReleaseNotesViewModel.kt @@ -85,6 +85,11 @@ class ReleaseNotesViewModel( subtitle = R.string.release_notes_4_3_0_subtitle_retried_successful_uploads_delete_temporary_folder, type = ReleaseNoteType.BUGFIX, ), + ReleaseNote( + title = R.string.release_notes_4_3_0_title_manual_removal_local_storage, + subtitle = R.string.release_notes_4_3_0_subtitle_manual_removal_local_storage, + type = ReleaseNoteType.ENHANCEMENT, + ), ) } } diff --git a/owncloudApp/src/main/java/com/owncloud/android/usecases/files/RemoveLocalFilesForAccountUseCase.kt b/owncloudApp/src/main/java/com/owncloud/android/usecases/files/RemoveLocalFilesForAccountUseCase.kt new file mode 100644 index 00000000000..c9d9f963370 --- /dev/null +++ b/owncloudApp/src/main/java/com/owncloud/android/usecases/files/RemoveLocalFilesForAccountUseCase.kt @@ -0,0 +1,42 @@ +/** + * ownCloud Android client application + * + * @author Aitor Ballesteros Pavón + * + * Copyright (C) 2024 ownCloud GmbH. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.usecases.files + +import com.owncloud.android.domain.BaseUseCaseWithResult +import com.owncloud.android.domain.files.FileRepository +import com.owncloud.android.domain.files.usecases.RemoveFileUseCase + +class RemoveLocalFilesForAccountUseCase( + private val fileRepository: FileRepository, + private val removeFileUseCase: RemoveFileUseCase, +) : BaseUseCaseWithResult() { + + override fun run(params: Params) { + val listOfFilesToDelete = fileRepository.getDownloadedFilesForAccount(params.owner) + if (listOfFilesToDelete.isNotEmpty()) { + removeFileUseCase(RemoveFileUseCase.Params(listOfFilesToDelete, true)) + } + } + + data class Params( + val owner: String, + ) +} diff --git a/owncloudApp/src/main/res/drawable/ic_clean_account.xml b/owncloudApp/src/main/res/drawable/ic_clean_account.xml new file mode 100644 index 00000000000..9640798b1ed --- /dev/null +++ b/owncloudApp/src/main/res/drawable/ic_clean_account.xml @@ -0,0 +1,10 @@ + + + diff --git a/owncloudApp/src/main/res/layout/account_item.xml b/owncloudApp/src/main/res/layout/account_item.xml index 9de0aa8d799..9b459e4a7e0 100644 --- a/owncloudApp/src/main/res/layout/account_item.xml +++ b/owncloudApp/src/main/res/layout/account_item.xml @@ -76,10 +76,27 @@ android:textColor="@color/textColor" android:textSize="14sp" android:lines="1" - app:layout_constraintEnd_toStartOf="@+id/removeButton" + app:layout_constraintEnd_toStartOf="@+id/clean_account_local_storage_button" app:layout_constraintStart_toEndOf="@id/ticker" app:layout_constraintTop_toBottomOf="@id/name" /> + + \"Local only\" option in remove dialog will only be shown if checking selected files and folders recursively, at least one file is available locally Retried successful uploads are cleaned up from the temporary folder Temporary files related to an upload are deleted after the retried successful uploads is finished + New setting to removal manually local storage + A new icon has been added in Manage Accounts view to delete manually local and temporary files Open in web @@ -793,4 +795,8 @@ The URL you provided uses HTTP rather than the encrypted HTTPS protocol. If you continue, your communication will not be encrypted. Continue + All downloaded files that are not available offline will be cleaned up for this account + Remove local storage + Clean data + diff --git a/owncloudData/src/main/java/com/owncloud/android/data/files/datasources/LocalFileDataSource.kt b/owncloudData/src/main/java/com/owncloud/android/data/files/datasources/LocalFileDataSource.kt index d6473503ec0..4cc9cd764d9 100644 --- a/owncloudData/src/main/java/com/owncloud/android/data/files/datasources/LocalFileDataSource.kt +++ b/owncloudData/src/main/java/com/owncloud/android/data/files/datasources/LocalFileDataSource.kt @@ -44,6 +44,7 @@ interface LocalFileDataSource { fun getFilesWithSyncInfoAvailableOfflineFromAccountAsFlow(owner: String): Flow> fun getFilesAvailableOfflineFromAccount(owner: String): List fun getFilesAvailableOfflineFromEveryAccount(): List + fun getDownloadedFilesForAccount(owner: String): List fun getFileWithSyncInfoByIdAsFlow(id: Long): Flow fun getFilesWithLastUsageOlderThanGivenTime(milliseconds: Long): List fun moveFile(sourceFile: OCFile, targetFolder: OCFile, finalRemotePath: String, finalStoragePath: String) diff --git a/owncloudData/src/main/java/com/owncloud/android/data/files/datasources/implementation/OCLocalFileDataSource.kt b/owncloudData/src/main/java/com/owncloud/android/data/files/datasources/implementation/OCLocalFileDataSource.kt index f88bd2c0e21..77eb83d269a 100644 --- a/owncloudData/src/main/java/com/owncloud/android/data/files/datasources/implementation/OCLocalFileDataSource.kt +++ b/owncloudData/src/main/java/com/owncloud/android/data/files/datasources/implementation/OCLocalFileDataSource.kt @@ -125,6 +125,11 @@ class OCLocalFileDataSource( it.toModel() } + override fun getDownloadedFilesForAccount(owner: String): List = + fileDao.getDownloadedFilesForAccount(accountOwner = owner).map { + it.toModel() + } + override fun getFilesWithLastUsageOlderThanGivenTime(milliseconds: Long): List = fileDao.getFilesWithLastUsageOlderThanGivenTime(milliseconds).map { it.toModel() diff --git a/owncloudData/src/main/java/com/owncloud/android/data/files/db/FileDao.kt b/owncloudData/src/main/java/com/owncloud/android/data/files/db/FileDao.kt index 8ffa11f7597..a1a0d0daef8 100644 --- a/owncloudData/src/main/java/com/owncloud/android/data/files/db/FileDao.kt +++ b/owncloudData/src/main/java/com/owncloud/android/data/files/db/FileDao.kt @@ -137,6 +137,11 @@ interface FileDao { @Query(SELECT_FILES_AVAILABLE_OFFLINE_FROM_EVERY_ACCOUNT) fun getFilesAvailableOfflineFromEveryAccount(): List + @Query(SELECT_DOWNLOADED_FILES_FOR_ACCOUNT) + fun getDownloadedFilesForAccount( + accountOwner: String + ): List + @Query(SELECT_FILES_WHERE_LAST_USAGE_IS_OLDER_THAN_GIVEN_TIME) fun getFilesWithLastUsageOlderThanGivenTime(milliseconds: Long): List @@ -538,6 +543,12 @@ interface FileDao { WHERE parentId = :folderId AND mimeType LIKE :mimeType || '%' """ + private const val SELECT_DOWNLOADED_FILES_FOR_ACCOUNT = """ + SELECT * + FROM ${ProviderMeta.ProviderTableMeta.FILES_TABLE_NAME} + WHERE owner = :accountOwner AND storagePath IS NOT NULL AND keepInSync = '0' + """ + private const val SELECT_FILES_SHARED_BY_LINK = """ SELECT * FROM ${ProviderMeta.ProviderTableMeta.FILES_TABLE_NAME} diff --git a/owncloudData/src/main/java/com/owncloud/android/data/files/repository/OCFileRepository.kt b/owncloudData/src/main/java/com/owncloud/android/data/files/repository/OCFileRepository.kt index 4b1b6257d7e..c0fd90a45c0 100644 --- a/owncloudData/src/main/java/com/owncloud/android/data/files/repository/OCFileRepository.kt +++ b/owncloudData/src/main/java/com/owncloud/android/data/files/repository/OCFileRepository.kt @@ -244,6 +244,8 @@ class OCFileRepository( override fun getFilesAvailableOfflineFromEveryAccount(): List = localFileDataSource.getFilesAvailableOfflineFromEveryAccount() + override fun getDownloadedFilesForAccount(owner: String): List = localFileDataSource.getDownloadedFilesForAccount(owner) + override fun getFilesWithLastUsageOlderThanGivenTime(milliseconds: Long): List = localFileDataSource.getFilesWithLastUsageOlderThanGivenTime(milliseconds) diff --git a/owncloudData/src/test/java/com/owncloud/android/data/files/datasources/implementation/OCLocalFileDataSourceTest.kt b/owncloudData/src/test/java/com/owncloud/android/data/files/datasources/implementation/OCLocalFileDataSourceTest.kt index e2c3400ef10..d9b932c020c 100644 --- a/owncloudData/src/test/java/com/owncloud/android/data/files/datasources/implementation/OCLocalFileDataSourceTest.kt +++ b/owncloudData/src/test/java/com/owncloud/android/data/files/datasources/implementation/OCLocalFileDataSourceTest.kt @@ -112,6 +112,28 @@ class OCLocalFileDataSourceTest { verify(exactly = 1) { fileDao.getFileByIdAsFlow(OC_FILE_ENTITY.id) } } + @Test + fun `getDownloadedFilesForAccount returns a list of OCFile`() { + every { fileDao.getDownloadedFilesForAccount(OC_ACCOUNT_NAME) } returns listOf(OC_FILE_ENTITY) + + val result = ocLocalFileDataSource.getDownloadedFilesForAccount(OC_ACCOUNT_NAME) + + assertEquals(listOf(OC_FILE), result) + + verify(exactly = 1) { fileDao.getDownloadedFilesForAccount(OC_ACCOUNT_NAME) } + } + + @Test + fun `getDownloadedFilesForAccount returns an empty list when DAO returns an empty list`() { + every { fileDao.getDownloadedFilesForAccount(OC_ACCOUNT_NAME) } returns emptyList() + + val result = ocLocalFileDataSource.getDownloadedFilesForAccount(OC_ACCOUNT_NAME) + + assertEquals(emptyList(), result) + + verify(exactly = 1) { fileDao.getDownloadedFilesForAccount(OC_ACCOUNT_NAME) } + } + @Test fun `getFileWithSyncInfoByIdAsFlow returns a Flow with an OCFileWithSyncInfo`() = runTest { every { fileDao.getFileWithSyncInfoByIdAsFlow(OC_FILE_ENTITY.id) } returns flowOf(OC_FILE_AND_FILE_SYNC) diff --git a/owncloudData/src/test/java/com/owncloud/android/data/files/repository/OCFileRepositoryTest.kt b/owncloudData/src/test/java/com/owncloud/android/data/files/repository/OCFileRepositoryTest.kt index f3c5ecd0ef1..4b67bbd5404 100644 --- a/owncloudData/src/test/java/com/owncloud/android/data/files/repository/OCFileRepositoryTest.kt +++ b/owncloudData/src/test/java/com/owncloud/android/data/files/repository/OCFileRepositoryTest.kt @@ -51,7 +51,8 @@ class OCFileRepositoryTest { private val localFileDataSource = mockk(relaxed = true) private val localSpacesDataSource = mockk(relaxed = true) private val localStorageProvider = mockk() - private val ocFileRepository: OCFileRepository = OCFileRepository(localFileDataSource, remoteFileDataSource, localSpacesDataSource, localStorageProvider) + private val ocFileRepository: OCFileRepository = + OCFileRepository(localFileDataSource, remoteFileDataSource, localSpacesDataSource, localStorageProvider) private val folderToFetch = OC_FOLDER private val listOfFilesRetrieved = listOf( @@ -110,7 +111,7 @@ class OCFileRepositoryTest { } @Test - fun `getFileWithSyncInfoByIdAsFlow returns OCFileWithSyncInfo`() = runTest { + fun `getFileWithSyncInfoByIdAsFlow returns OCFileWithSyncInfo`() = runTest { every { localFileDataSource.getFileWithSyncInfoByIdAsFlow(OC_FILE.id!!) } returns flowOf(OC_FILE_WITH_SYNC_INFO_AND_SPACE) val ocFile = ocFileRepository.getFileWithSyncInfoByIdAsFlow(OC_FILE.id!!) @@ -125,7 +126,7 @@ class OCFileRepositoryTest { } @Test - fun `getFileWithSyncInfoByIdAsFlow returns null`() = runTest { + fun `getFileWithSyncInfoByIdAsFlow returns null`() = runTest { every { localFileDataSource.getFileWithSyncInfoByIdAsFlow(OC_FILE.id!!) } returns flowOf(null) val ocFile = ocFileRepository.getFileWithSyncInfoByIdAsFlow(OC_FILE.id!!) @@ -139,10 +140,9 @@ class OCFileRepositoryTest { } } - @Test(expected = Exception::class) - fun `getFileWithSyncInfoByIdAsFlow returns an exception`() = runTest { - every { localFileDataSource.getFileWithSyncInfoByIdAsFlow(OC_FILE.id!!) } throws Exception() + fun `getFileWithSyncInfoByIdAsFlow returns an exception`() = runTest { + every { localFileDataSource.getFileWithSyncInfoByIdAsFlow(OC_FILE.id!!) } throws Exception() ocFileRepository.getFileWithSyncInfoByIdAsFlow(OC_FILE.id!!) @@ -150,6 +150,7 @@ class OCFileRepositoryTest { localFileDataSource.getFileWithSyncInfoByIdAsFlow(OC_FILE.id!!) } } + @Test fun `get file by id - ok - null`() { every { localFileDataSource.getFileById(OC_FOLDER.id!!) } returns null @@ -198,6 +199,21 @@ class OCFileRepositoryTest { } } + @Test + fun `getDownloadedFilesForAccount returns a list of OCFile`() { + every { + localFileDataSource.getDownloadedFilesForAccount(OC_ACCOUNT_NAME) + } returns listOf(OC_FILE) + + val result = ocFileRepository.getDownloadedFilesForAccount(OC_ACCOUNT_NAME) + + assertEquals(listOf(OC_FILE), result) + + verify(exactly = 1) { + localFileDataSource.getDownloadedFilesForAccount(OC_ACCOUNT_NAME) + } + } + @Test fun `get folder content - ok`() { every { localFileDataSource.getFolderContent(OC_FOLDER.parentId!!) } returns listOf(OC_FOLDER) diff --git a/owncloudDomain/src/main/java/com/owncloud/android/domain/files/FileRepository.kt b/owncloudDomain/src/main/java/com/owncloud/android/domain/files/FileRepository.kt index 36c96a76ece..b9fbbe24a05 100644 --- a/owncloudDomain/src/main/java/com/owncloud/android/domain/files/FileRepository.kt +++ b/owncloudDomain/src/main/java/com/owncloud/android/domain/files/FileRepository.kt @@ -51,6 +51,7 @@ interface FileRepository { fun getFilesWithSyncInfoAvailableOfflineFromAccountAsFlow(owner: String): Flow> fun getFilesAvailableOfflineFromAccount(owner: String): List fun getFilesAvailableOfflineFromEveryAccount(): List + fun getDownloadedFilesForAccount(owner: String): List fun getFilesWithLastUsageOlderThanGivenTime(milliseconds: Long): List // Returns files in conflict