Skip to content

Commit e1cf321

Browse files
authored
Merge pull request #4334 from owncloud/feature/manual_removal_local_storage
[FEATURE REQUEST] Manual removal of local storage
2 parents 4b268fa + 762ab03 commit e1cf321

19 files changed

Lines changed: 237 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ ownCloud admins and users.
3636
* Change - Add new prefixes in commit messages of 3rd party contributors: [#4346](https://github.com/owncloud/android/pull/4346)
3737
* Enhancement - Correct "Local only" option in remove dialog: [#3936](https://github.com/owncloud/android/issues/3936)
3838
* Enhancement - Improvements in Manage Accounts view: [#4148](https://github.com/owncloud/android/issues/4148)
39+
* Enhancement - New setting for manual removal of local storage: [#4174](https://github.com/owncloud/android/issues/4174)
3940
* Enhancement - New setting for automatic removal of local files: [#4175](https://github.com/owncloud/android/issues/4175)
4041
* Enhancement - Unit tests for repository classes - Part 1: [#4232](https://github.com/owncloud/android/issues/4232)
4142
* Enhancement - Add a warning in http connections: [#4284](https://github.com/owncloud/android/issues/4284)
@@ -97,6 +98,14 @@ ownCloud admins and users.
9798
https://github.com/owncloud/android/issues/4148
9899
https://github.com/owncloud/android/pull/4330
99100

101+
* Enhancement - New setting for manual removal of local storage: [#4174](https://github.com/owncloud/android/issues/4174)
102+
103+
A new icon has been added in Manage Accounts view to delete manually local
104+
files.
105+
106+
https://github.com/owncloud/android/issues/4174
107+
https://github.com/owncloud/android/pull/4334
108+
100109
* Enhancement - New setting for automatic removal of local files: [#4175](https://github.com/owncloud/android/issues/4175)
101110

102111
A new setting has been created to delete automatically downloaded files, when

changelog/unreleased/4334

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Enhancement: New setting for manual removal of local storage
2+
3+
A new icon has been added in Manage Accounts view to delete manually local files.
4+
5+
https://github.com/owncloud/android/issues/4174
6+
https://github.com/owncloud/android/pull/4334

owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/UseCaseModule.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ import com.owncloud.android.domain.webfinger.usecases.GetOwnCloudInstanceFromWeb
109109
import com.owncloud.android.domain.webfinger.usecases.GetOwnCloudInstancesFromAuthenticatedWebFingerUseCase
110110
import com.owncloud.android.usecases.accounts.RemoveAccountUseCase
111111
import com.owncloud.android.usecases.files.FilterFileMenuOptionsUseCase
112+
import com.owncloud.android.usecases.files.RemoveLocalFilesForAccountUseCase
112113
import com.owncloud.android.usecases.files.RemoveLocallyFilesWithLastUsageOlderThanGivenTimeUseCase
113114
import com.owncloud.android.usecases.synchronization.SynchronizeFileUseCase
114115
import com.owncloud.android.usecases.synchronization.SynchronizeFolderUseCase
@@ -176,6 +177,7 @@ val useCaseModule = module {
176177
factoryOf(::ManageDeepLinkUseCase)
177178
factoryOf(::MoveFileUseCase)
178179
factoryOf(::RemoveFileUseCase)
180+
factoryOf(::RemoveLocalFilesForAccountUseCase)
179181
factoryOf(::RemoveLocallyFilesWithLastUsageOlderThanGivenTimeUseCase)
180182
factoryOf(::RenameFileUseCase)
181183
factoryOf(::SaveConflictUseCase)

owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/ViewModelModule.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ val viewModelModule = module {
101101
viewModel { MigrationViewModel(MainApp.dataFolder, get(), get(), get(), get(), get(), get(), get()) }
102102
viewModel { TransfersViewModel(get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get(), get()) }
103103
viewModel { ReceiveExternalFilesViewModel(get(), get(), get()) }
104-
viewModel { AccountsManagementViewModel(get()) }
104+
viewModel { AccountsManagementViewModel(get(), get(), get()) }
105105
viewModel { (accountName: String, showPersonalSpace: Boolean) ->
106106
SpacesListViewModel(get(), get(), get(), get(), get(), accountName, showPersonalSpace)
107107
}

owncloudApp/src/main/java/com/owncloud/android/presentation/accounts/AccountsManagementActivity.kt

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
* ownCloud Android client application
33
*
44
* @author Javier Rodríguez Pérez
5+
* @author Aitor Ballesteros Pavón
56
*
6-
* Copyright (C) 2022 ownCloud GmbH.
7+
* Copyright (C) 2024 ownCloud GmbH.
78
*
89
* This program is free software: you can redistribute it and/or modify
910
* it under the terms of the GNU General Public License version 2,
@@ -28,13 +29,17 @@ import android.accounts.OperationCanceledException
2829
import android.content.Intent
2930
import android.os.Bundle
3031
import android.view.MenuItem
32+
import androidx.appcompat.app.AlertDialog
3133
import androidx.recyclerview.widget.LinearLayoutManager
3234
import androidx.recyclerview.widget.RecyclerView
3335
import com.owncloud.android.MainApp.Companion.accountType
3436
import com.owncloud.android.MainApp.Companion.initDependencyInjection
3537
import com.owncloud.android.R
38+
import com.owncloud.android.extensions.collectLatestLifecycleFlow
39+
import com.owncloud.android.extensions.showErrorInSnackbar
3640
import com.owncloud.android.presentation.accounts.RemoveAccountDialogFragment.Companion.newInstance
3741
import com.owncloud.android.presentation.authentication.AccountUtils
42+
import com.owncloud.android.presentation.common.UIResult
3843
import com.owncloud.android.ui.activity.FileActivity
3944
import com.owncloud.android.ui.activity.FileDisplayActivity
4045
import com.owncloud.android.ui.dialog.ConfirmationDialogFragment
@@ -73,6 +78,8 @@ class AccountsManagementActivity : FileActivity(), AccountsManagementAdapter.Acc
7378
displayShowTitleEnabled = true
7479
)
7580

81+
subscribeToViewModels()
82+
7683
}
7784

7885
override fun onStart() {
@@ -196,6 +203,39 @@ class AccountsManagementActivity : FileActivity(), AccountsManagementAdapter.Acc
196203

197204
}
198205

206+
override fun cleanAccountLocalStorage(account: Account) {
207+
val dialog = AlertDialog.Builder(this)
208+
.setTitle(getString(R.string.clean_data_account_title))
209+
.setIcon(R.drawable.ic_warning)
210+
.setMessage(getString(R.string.clean_data_account_message))
211+
.setPositiveButton(getString(R.string.clean_data_account_button_yes)) { dialog, _ ->
212+
accountsManagementViewModel.cleanAccountLocalStorage(account.name)
213+
dialog.dismiss()
214+
}
215+
.setNegativeButton(R.string.drawer_close) { dialog, _ ->
216+
dialog.dismiss()
217+
}
218+
.create()
219+
dialog.show()
220+
}
221+
222+
private fun subscribeToViewModels() {
223+
collectLatestLifecycleFlow(accountsManagementViewModel.cleanAccountLocalStorageFlow) { event ->
224+
event?.peekContent()?.let { uiResult ->
225+
when (uiResult) {
226+
is UIResult.Loading -> showLoadingDialog(R.string.common_loading)
227+
is UIResult.Success -> dismissLoadingDialog()
228+
is UIResult.Error -> {
229+
dismissLoadingDialog()
230+
showErrorInSnackbar(R.string.common_error_unknown, uiResult.error)
231+
Timber.e(uiResult.error)
232+
}
233+
234+
}
235+
}
236+
}
237+
}
238+
199239
override fun run(future: AccountManagerFuture<Boolean>) {
200240
if (future.isDone) {
201241
// Create new adapter with the remaining accounts

owncloudApp/src/main/java/com/owncloud/android/presentation/accounts/AccountsManagementAdapter.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
* ownCloud Android client application
33
*
44
* @author Javier Rodríguez Pérez
5+
* @author Aitor Ballesteros Pavón
56
*
6-
* Copyright (C) 2022 ownCloud GmbH.
7+
* Copyright (C) 2024 ownCloud GmbH.
78
*
89
* This program is free software: you can redistribute it and/or modify
910
* it under the terms of the GNU General Public License version 2,
@@ -99,6 +100,11 @@ class AccountsManagementAdapter(private val accountListener: AccountAdapterListe
99100
holder.binding.ticker.visibility = View.INVISIBLE
100101
}
101102

103+
/// bind listener to clean local storage from account
104+
holder.binding.cleanAccountLocalStorageButton.apply {
105+
setImageResource(R.drawable.ic_clean_account)
106+
setOnClickListener { accountListener.cleanAccountLocalStorage(account) }
107+
}
102108
/// bind listener to remove account
103109
holder.binding.removeButton.apply {
104110
setImageResource(R.drawable.ic_action_delete_grey)
@@ -156,6 +162,7 @@ class AccountsManagementAdapter(private val accountListener: AccountAdapterListe
156162
*/
157163
interface AccountAdapterListener {
158164
fun removeAccount(account: Account)
165+
fun cleanAccountLocalStorage(account: Account)
159166
fun createAccount()
160167
fun switchAccount(position: Int)
161168
}

owncloudApp/src/main/java/com/owncloud/android/presentation/accounts/AccountsManagementViewModel.kt

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
* ownCloud Android client application
33
*
44
* @author Javier Rodríguez Pérez
5+
* @author Aitor Ballesteros Pavón
56
*
6-
* Copyright (C) 2022 ownCloud GmbH.
7+
* Copyright (C) 2024 ownCloud GmbH.
78
*
89
* This program is free software: you can redistribute it and/or modify
910
* it under the terms of the GNU General Public License version 2,
@@ -22,17 +23,39 @@ package com.owncloud.android.presentation.accounts
2223

2324
import android.accounts.Account
2425
import androidx.lifecycle.ViewModel
26+
import com.owncloud.android.domain.utils.Event
27+
import com.owncloud.android.extensions.ViewModelExt.runUseCaseWithResult
28+
import com.owncloud.android.presentation.common.UIResult
2529
import com.owncloud.android.providers.AccountProvider
30+
import com.owncloud.android.providers.CoroutinesDispatcherProvider
31+
import com.owncloud.android.usecases.files.RemoveLocalFilesForAccountUseCase
32+
import kotlinx.coroutines.flow.MutableStateFlow
33+
import kotlinx.coroutines.flow.StateFlow
2634

2735
class AccountsManagementViewModel(
28-
private val accountProvider: AccountProvider
36+
private val accountProvider: AccountProvider,
37+
private val removeLocalFilesForAccountUseCase: RemoveLocalFilesForAccountUseCase,
38+
private val coroutinesDispatcherProvider: CoroutinesDispatcherProvider,
2939
) : ViewModel() {
3040

41+
private val _cleanAccountLocalStorageFlow = MutableStateFlow<Event<UIResult<Unit>>?>(null)
42+
val cleanAccountLocalStorageFlow: StateFlow<Event<UIResult<Unit>>?> = _cleanAccountLocalStorageFlow
43+
3144
fun getLoggedAccounts(): Array<Account> {
3245
return accountProvider.getLoggedAccounts()
3346
}
3447

3548
fun getCurrentAccount(): Account? {
3649
return accountProvider.getCurrentOwnCloudAccount()
3750
}
51+
52+
fun cleanAccountLocalStorage(accountName: String) {
53+
runUseCaseWithResult(
54+
coroutineDispatcher = coroutinesDispatcherProvider.io,
55+
showLoading = true,
56+
flow = _cleanAccountLocalStorageFlow,
57+
useCase = removeLocalFilesForAccountUseCase,
58+
useCaseParams = RemoveLocalFilesForAccountUseCase.Params(accountName),
59+
)
60+
}
3861
}

owncloudApp/src/main/java/com/owncloud/android/presentation/releasenotes/ReleaseNotesViewModel.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ class ReleaseNotesViewModel(
8585
subtitle = R.string.release_notes_4_3_0_subtitle_retried_successful_uploads_delete_temporary_folder,
8686
type = ReleaseNoteType.BUGFIX,
8787
),
88+
ReleaseNote(
89+
title = R.string.release_notes_4_3_0_title_manual_removal_local_storage,
90+
subtitle = R.string.release_notes_4_3_0_subtitle_manual_removal_local_storage,
91+
type = ReleaseNoteType.ENHANCEMENT,
92+
),
8893
)
8994
}
9095
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* ownCloud Android client application
3+
*
4+
* @author Aitor Ballesteros Pavón
5+
*
6+
* Copyright (C) 2024 ownCloud GmbH.
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License version 2,
10+
* as published by the Free Software Foundation.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*/
20+
21+
package com.owncloud.android.usecases.files
22+
23+
import com.owncloud.android.domain.BaseUseCaseWithResult
24+
import com.owncloud.android.domain.files.FileRepository
25+
import com.owncloud.android.domain.files.usecases.RemoveFileUseCase
26+
27+
class RemoveLocalFilesForAccountUseCase(
28+
private val fileRepository: FileRepository,
29+
private val removeFileUseCase: RemoveFileUseCase,
30+
) : BaseUseCaseWithResult<Unit, RemoveLocalFilesForAccountUseCase.Params>() {
31+
32+
override fun run(params: Params) {
33+
val listOfFilesToDelete = fileRepository.getDownloadedFilesForAccount(params.owner)
34+
if (listOfFilesToDelete.isNotEmpty()) {
35+
removeFileUseCase(RemoveFileUseCase.Params(listOfFilesToDelete, true))
36+
}
37+
}
38+
39+
data class Params(
40+
val owner: String,
41+
)
42+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="960"
5+
android:viewportHeight="960"
6+
android:tint="?attr/colorControlNormal">
7+
<path
8+
android:fillColor="@android:color/white"
9+
android:pathData="M440,440L520,440L520,160Q520,143 508.5,131.5Q497,120 480,120Q463,120 451.5,131.5Q440,143 440,160L440,440ZM200,600L760,600L760,520Q760,520 760,520Q760,520 760,520L200,520Q200,520 200,520Q200,520 200,520L200,600ZM142,840L240,840L240,760Q240,743 251.5,731.5Q263,720 280,720Q297,720 308.5,731.5Q320,743 320,760L320,840L440,840L440,760Q440,743 451.5,731.5Q463,720 480,720Q497,720 508.5,731.5Q520,743 520,760L520,840L640,840L640,760Q640,743 651.5,731.5Q663,720 680,720Q697,720 708.5,731.5Q720,743 720,760L720,840L818,840Q818,840 818,840Q818,840 818,840L778,680L182,680L142,840Q142,840 142,840Q142,840 142,840ZM818,920L142,920Q103,920 79,889Q55,858 65,820L120,600L120,520Q120,487 143.5,463.5Q167,440 200,440L360,440L360,160Q360,110 395,75Q430,40 480,40Q530,40 565,75Q600,110 600,160L600,440L760,440Q793,440 816.5,463.5Q840,487 840,520L840,600L895,820Q908,858 883.5,889Q859,920 818,920ZM760,520L200,520L200,520Q200,520 200,520Q200,520 200,520L760,520Q760,520 760,520Q760,520 760,520L760,520ZM520,440L440,440L440,440Q440,440 451.5,440Q463,440 480,440Q497,440 508.5,440Q520,440 520,440L520,440Z" />
10+
</vector>

0 commit comments

Comments
 (0)