Skip to content

Commit 84f0a32

Browse files
authored
Merge pull request #3973 from owncloud/spaces/space_in_ocfile
Add space to OCFileWithSyncInfo
2 parents 1e565db + 5636453 commit 84f0a32

File tree

28 files changed

+173
-188
lines changed

28 files changed

+173
-188
lines changed

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

+4-4
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,14 @@ import com.owncloud.android.domain.sharing.shares.usecases.EditPublicShareAsyncU
8080
import com.owncloud.android.domain.sharing.shares.usecases.GetShareAsLiveDataUseCase
8181
import com.owncloud.android.domain.sharing.shares.usecases.GetSharesAsLiveDataUseCase
8282
import com.owncloud.android.domain.sharing.shares.usecases.RefreshSharesFromServerAsyncUseCase
83-
import com.owncloud.android.domain.spaces.usecases.GetSpacesFromEveryAccountUseCase
83+
import com.owncloud.android.domain.spaces.usecases.GetSpacesFromEveryAccountUseCaseAsStream
8484
import com.owncloud.android.domain.spaces.usecases.GetPersonalAndProjectSpacesForAccountUseCase
8585
import com.owncloud.android.domain.spaces.usecases.GetPersonalAndProjectSpacesWithSpecialsForAccountAsStreamUseCase
8686
import com.owncloud.android.domain.spaces.usecases.GetProjectSpacesWithSpecialsForAccountAsStreamUseCase
8787
import com.owncloud.android.domain.spaces.usecases.GetSpaceWithSpecialsByIdForAccountUseCase
8888
import com.owncloud.android.domain.spaces.usecases.RefreshSpacesFromServerAsyncUseCase
8989
import com.owncloud.android.domain.transfers.usecases.ClearSuccessfulTransfersUseCase
90-
import com.owncloud.android.domain.transfers.usecases.GetAllTransfersAsLiveDataUseCase
90+
import com.owncloud.android.domain.transfers.usecases.GetAllTransfersAsStreamUseCase
9191
import com.owncloud.android.domain.transfers.usecases.GetAllTransfersUseCase
9292
import com.owncloud.android.domain.transfers.usecases.UpdatePendingUploadsPathUseCase
9393
import com.owncloud.android.domain.user.usecases.GetStoredQuotaUseCase
@@ -186,7 +186,7 @@ val useCaseModule = module {
186186
factory { RefreshSharesFromServerAsyncUseCase(get()) }
187187

188188
// Spaces
189-
factory { GetSpacesFromEveryAccountUseCase(get()) }
189+
factory { GetSpacesFromEveryAccountUseCaseAsStream(get()) }
190190
factory { GetPersonalAndProjectSpacesForAccountUseCase(get()) }
191191
factory { GetPersonalAndProjectSpacesWithSpecialsForAccountAsStreamUseCase(get()) }
192192
factory { GetProjectSpacesWithSpecialsForAccountAsStreamUseCase(get()) }
@@ -209,7 +209,7 @@ val useCaseModule = module {
209209
factory { CancelUploadsRecursivelyUseCase(get(), get(), get(), get()) }
210210
factory { RetryUploadFromSystemUseCase(get(), get(), get()) }
211211
factory { RetryUploadFromContentUriUseCase(get(), get(), get()) }
212-
factory { GetAllTransfersAsLiveDataUseCase(get()) }
212+
factory { GetAllTransfersAsStreamUseCase(get()) }
213213
factory { GetAllTransfersUseCase(get()) }
214214
factory { CancelUploadUseCase(get(), get(), get()) }
215215
factory { ClearFailedTransfersUseCase(get(), get(), get()) }

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

-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ val viewModelModule = module {
106106
get(),
107107
get(),
108108
get(),
109-
get(),
110109
initialFolderToDisplay,
111110
fileListOption,
112111
)

owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/FileListAdapter.kt

+6-14
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ import com.owncloud.android.datamodel.ThumbnailsCacheManager
4242
import com.owncloud.android.domain.files.model.FileListOption
4343
import com.owncloud.android.domain.files.model.OCFileWithSyncInfo
4444
import com.owncloud.android.domain.files.model.OCFooterFile
45-
import com.owncloud.android.domain.spaces.model.OCSpace
4645
import com.owncloud.android.presentation.authentication.AccountUtils
4746
import com.owncloud.android.utils.DisplayUtils
4847
import com.owncloud.android.utils.MimetypeIconUtil
@@ -59,14 +58,10 @@ class FileListAdapter(
5958
private var account: Account? = AccountUtils.getCurrentOwnCloudAccount(context)
6059
private var fileListOption: FileListOption = FileListOption.ALL_FILES
6160

62-
fun updateFileList(filesToAdd: List<OCFileWithSyncInfo>, fileListOption: FileListOption, spaces: List<OCSpace>) {
63-
val fileItems = filesToAdd.map { fileWithSyncInfo ->
64-
val space = spaces.firstOrNull { it.id == fileWithSyncInfo.file.spaceId && it.accountName == fileWithSyncInfo.file.owner }
65-
FileItem(fileWithSyncInfo, space)
66-
}
61+
fun updateFileList(filesToAdd: List<OCFileWithSyncInfo>, fileListOption: FileListOption) {
6762

6863
val listWithFooter = mutableListOf<Any>()
69-
listWithFooter.addAll(fileItems)
64+
listWithFooter.addAll(filesToAdd)
7065

7166
if (listWithFooter.isNotEmpty()) {
7267
listWithFooter.add(OCFooterFile(manageListOfFilesAndGenerateText(filesToAdd)))
@@ -139,7 +134,7 @@ class FileListAdapter(
139134
layoutManager.spanCount == 1 -> {
140135
ViewType.LIST_ITEM.ordinal
141136
}
142-
(files[position] as FileItem).fileWithSyncInfo.file.isImage -> {
137+
(files[position] as OCFileWithSyncInfo).file.isImage -> {
143138
ViewType.GRID_IMAGE.ordinal
144139
}
145140
else -> {
@@ -179,8 +174,7 @@ class FileListAdapter(
179174

180175
if (viewType != ViewType.FOOTER.ordinal) { // Is Item
181176

182-
val fileItem = files[position] as FileItem
183-
val fileWithSyncInfo = fileItem.fileWithSyncInfo
177+
val fileWithSyncInfo = files[position] as OCFileWithSyncInfo
184178
val file = fileWithSyncInfo.file
185179
val name = file.fileName
186180
val fileIcon = holder.itemView.findViewById<ImageView>(R.id.thumbnail).apply {
@@ -211,12 +205,12 @@ class FileListAdapter(
211205
it.Filename.text = file.fileName
212206
it.fileListSize.text = DisplayUtils.bytesToHumanReadable(file.length, context)
213207
it.fileListLastMod.text = DisplayUtils.getRelativeTimestamp(context, file.modificationTimestamp)
214-
if (fileListOption.isAvailableOffline() || (fileListOption.isSharedByLink() && fileItem.space == null)) {
208+
if (fileListOption.isAvailableOffline() || (fileListOption.isSharedByLink() && fileWithSyncInfo.space == null)) {
215209
it.spacePathLine.path.apply {
216210
text = file.getParentRemotePath()
217211
isVisible = true
218212
}
219-
fileItem.space?.let { space ->
213+
fileWithSyncInfo.space?.let { space ->
220214
it.spacePathLine.spaceIcon.isVisible = true
221215
it.spacePathLine.spaceName.isVisible = true
222216
if (space.isPersonal) {
@@ -406,8 +400,6 @@ class FileListAdapter(
406400
fun onLongItemClick(position: Int): Boolean = true
407401
}
408402

409-
data class FileItem(val fileWithSyncInfo: OCFileWithSyncInfo, val space: OCSpace?)
410-
411403
inner class GridViewHolder(val binding: GridItemBinding) : RecyclerView.ViewHolder(binding.root)
412404
inner class GridImageViewHolder(val binding: GridItemBinding) : RecyclerView.ViewHolder(binding.root)
413405
inner class ListViewHolder(val binding: ItemFileListBinding) : RecyclerView.ViewHolder(binding.root)

owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/FileListDiffCallback.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ package com.owncloud.android.presentation.files.filelist
2323

2424
import androidx.recyclerview.widget.DiffUtil
2525
import com.owncloud.android.domain.files.model.FileListOption
26+
import com.owncloud.android.domain.files.model.OCFileWithSyncInfo
2627
import com.owncloud.android.domain.files.model.OCFooterFile
2728

2829
class FileListDiffCallback(
@@ -48,8 +49,8 @@ class FileListDiffCallback(
4849
return true
4950
}
5051

51-
if (oldItem is FileListAdapter.FileItem && newItem is FileListAdapter.FileItem) {
52-
return oldItem.fileWithSyncInfo.file.id == newItem.fileWithSyncInfo.file.id
52+
if (oldItem is OCFileWithSyncInfo && newItem is OCFileWithSyncInfo) {
53+
return oldItem.file.id == newItem.file.id
5354
}
5455

5556
if (oldItem is OCFooterFile && newItem is OCFooterFile) {

owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainFileListFragment.kt

-1
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,6 @@ class MainFileListFragment : Fragment(),
240240
fileListAdapter.updateFileList(
241241
filesToAdd = fileListUiState.folderContent,
242242
fileListOption = fileListUiState.fileListOption,
243-
spaces = mainFileListViewModel.spaces.value,
244243
)
245244
showOrHideEmptyView(fileListUiState)
246245

owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainFileListViewModel.kt

-10
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ import com.owncloud.android.domain.files.usecases.GetSharedByLinkForAccountAsStr
3838
import com.owncloud.android.domain.files.usecases.SortFilesWithSyncInfoUseCase
3939
import com.owncloud.android.domain.spaces.model.OCSpace
4040
import com.owncloud.android.domain.spaces.usecases.GetSpaceWithSpecialsByIdForAccountUseCase
41-
import com.owncloud.android.domain.spaces.usecases.GetSpacesFromEveryAccountUseCase
4241
import com.owncloud.android.presentation.files.SortOrder
4342
import com.owncloud.android.presentation.files.SortOrder.Companion.PREF_FILE_LIST_SORT_ORDER
4443
import com.owncloud.android.presentation.files.SortType
@@ -68,7 +67,6 @@ class MainFileListViewModel(
6867
private val getSpaceWithSpecialsByIdForAccountUseCase: GetSpaceWithSpecialsByIdForAccountUseCase,
6968
private val sortFilesWithSyncInfoUseCase: SortFilesWithSyncInfoUseCase,
7069
private val synchronizeFolderUseCase: SynchronizeFolderUseCase,
71-
private val getSpacesFromEveryAccountUseCase: GetSpacesFromEveryAccountUseCase, // TODO: To be deleted when adding the space to the file entity
7270
private val coroutinesDispatcherProvider: CoroutinesDispatcherProvider,
7371
private val sharedPreferencesProvider: SharedPreferencesProvider,
7472
initialFolderToDisplay: OCFile,
@@ -83,10 +81,6 @@ class MainFileListViewModel(
8381
private val sortTypeAndOrder = MutableStateFlow(Pair(SortType.SORT_TYPE_BY_NAME, SortOrder.SORT_ORDER_ASCENDING))
8482
val space: MutableStateFlow<OCSpace?> = MutableStateFlow(null)
8583

86-
private val _spaces: MutableStateFlow<List<OCSpace>> = MutableStateFlow(emptyList())
87-
val spaces: StateFlow<List<OCSpace>>
88-
get() = _spaces
89-
9084
/** File list ui state combines the other fields and generate a new state whenever any of them changes */
9185
val fileListUiState: StateFlow<FileListUiState> =
9286
combine(
@@ -127,10 +121,6 @@ class MainFileListViewModel(
127121
)
128122
)
129123
}
130-
viewModelScope.launch(coroutinesDispatcherProvider.io) {
131-
val spacesList = getSpacesFromEveryAccountUseCase.execute(Unit)
132-
_spaces.update { spacesList }
133-
}
134124
}
135125

136126
fun navigateToFolderId(folderId: Long) {

owncloudApp/src/main/java/com/owncloud/android/presentation/transfers/TransferListFragment.kt

+6-9
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
3434
import com.google.android.material.snackbar.Snackbar
3535
import com.owncloud.android.R
3636
import com.owncloud.android.databinding.FragmentTransferListBinding
37+
import com.owncloud.android.domain.spaces.model.OCSpace
3738
import com.owncloud.android.domain.transfers.model.OCTransfer
3839
import com.owncloud.android.domain.transfers.model.TransferResult
3940
import com.owncloud.android.extensions.collectLatestLifecycleFlow
@@ -99,7 +100,7 @@ class TransferListFragment : Fragment() {
99100
addItemDecoration(DividerItemDecoration(context, DividerItemDecoration.VERTICAL))
100101
}
101102

102-
transfersViewModel.transfersListLiveData.observe(viewLifecycleOwner) { transfers ->
103+
collectLatestLifecycleFlow(transfersViewModel.transfersWithSpaceStateFlow) { transfers ->
103104
val recyclerViewState = binding.transfersRecyclerView.layoutManager?.onSaveInstanceState()
104105
setData(transfers)
105106
binding.transfersRecyclerView.layoutManager?.onRestoreInstanceState(recyclerViewState)
@@ -111,25 +112,21 @@ class TransferListFragment : Fragment() {
111112
}
112113
}
113114

114-
collectLatestLifecycleFlow(transfersViewModel.spaces) {
115-
transfersViewModel.transfersListLiveData.value?.let { transfers -> setData(transfers) }
116-
}
117-
118115
}
119116

120117
override fun onDestroy() {
121118
super.onDestroy()
122119
_binding = null
123120
}
124121

125-
private fun setData(items: List<OCTransfer>) {
126-
binding.transfersRecyclerView.isVisible = items.isNotEmpty()
122+
private fun setData(transfersWithSpace: List<Pair<OCTransfer, OCSpace?>>) {
123+
binding.transfersRecyclerView.isVisible = transfersWithSpace.isNotEmpty()
127124
binding.transfersListEmpty.apply {
128-
root.isVisible = items.isEmpty()
125+
root.isVisible = transfersWithSpace.isEmpty()
129126
listEmptyDatasetIcon.setImageResource(R.drawable.ic_uploads)
130127
listEmptyDatasetTitle.setText(R.string.upload_list_empty)
131128
listEmptyDatasetSubTitle.setText(R.string.upload_list_empty_subtitle)
132129
}
133-
transfersAdapter.setData(items, transfersViewModel.spaces.value)
130+
transfersAdapter.setData(transfersWithSpace)
134131
}
135132
}

owncloudApp/src/main/java/com/owncloud/android/presentation/transfers/TransfersAdapter.kt

+5-5
Original file line numberDiff line numberDiff line change
@@ -235,15 +235,14 @@ class TransfersAdapter(
235235
}
236236
}
237237

238-
fun setData(transfers: List<OCTransfer>, spaces: List<OCSpace>) {
239-
val transfersGroupedByStatus = transfers.groupBy { it.status }
238+
fun setData(transfersWithSpace: List<Pair<OCTransfer, OCSpace?>>) {
239+
val transfersGroupedByStatus = transfersWithSpace.groupBy { it.first.status }
240240
val newTransferItemsList = mutableListOf<TransferRecyclerItem>()
241241
transfersGroupedByStatus.forEach { transferMap ->
242242
val headerItem = HeaderItem(transferMap.key, transferMap.value.size)
243243
newTransferItemsList.add(headerItem)
244-
val transferItems = transferMap.value.sortedByDescending { it.transferEndTimestamp ?: it.id }.map { transfer ->
245-
val space = spaces.firstOrNull { it.id == transfer.spaceId && it.accountName == transfer.accountName }
246-
TransferItem(transfer, space)
244+
val transferItems = transferMap.value.sortedByDescending { it.first.transferEndTimestamp ?: it.first.id }.map { transfersWithSpace ->
245+
TransferItem(transfersWithSpace.first, transfersWithSpace.second)
247246
}
248247
newTransferItemsList.addAll(transferItems)
249248
}
@@ -283,6 +282,7 @@ class TransfersAdapter(
283282
val transfer: OCTransfer,
284283
val space: OCSpace?,
285284
) : TransferRecyclerItem
285+
286286
data class HeaderItem(
287287
val status: TransferStatus,
288288
val numberTransfers: Int,

owncloudApp/src/main/java/com/owncloud/android/presentation/transfers/TransfersViewModel.kt

+20-23
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ import androidx.lifecycle.viewModelScope
2828
import androidx.work.WorkInfo
2929
import com.owncloud.android.domain.files.model.OCFile
3030
import com.owncloud.android.domain.spaces.model.OCSpace
31-
import com.owncloud.android.domain.spaces.usecases.GetSpacesFromEveryAccountUseCase
31+
import com.owncloud.android.domain.spaces.usecases.GetSpacesFromEveryAccountUseCaseAsStream
3232
import com.owncloud.android.domain.transfers.model.OCTransfer
3333
import com.owncloud.android.domain.transfers.usecases.ClearSuccessfulTransfersUseCase
34-
import com.owncloud.android.domain.transfers.usecases.GetAllTransfersAsLiveDataUseCase
34+
import com.owncloud.android.domain.transfers.usecases.GetAllTransfersAsStreamUseCase
3535
import com.owncloud.android.providers.CoroutinesDispatcherProvider
3636
import com.owncloud.android.providers.WorkManagerProvider
3737
import com.owncloud.android.usecases.transfers.downloads.CancelDownloadForFileUseCase
@@ -46,9 +46,10 @@ import com.owncloud.android.usecases.transfers.uploads.RetryUploadFromContentUri
4646
import com.owncloud.android.usecases.transfers.uploads.RetryUploadFromSystemUseCase
4747
import com.owncloud.android.usecases.transfers.uploads.UploadFilesFromContentUriUseCase
4848
import com.owncloud.android.usecases.transfers.uploads.UploadFilesFromSystemUseCase
49-
import kotlinx.coroutines.flow.MutableStateFlow
49+
import kotlinx.coroutines.flow.SharingStarted
5050
import kotlinx.coroutines.flow.StateFlow
51-
import kotlinx.coroutines.flow.update
51+
import kotlinx.coroutines.flow.combine
52+
import kotlinx.coroutines.flow.stateIn
5253
import kotlinx.coroutines.launch
5354

5455
class TransfersViewModel(
@@ -61,43 +62,39 @@ class TransfersViewModel(
6162
private val clearFailedTransfersUseCase: ClearFailedTransfersUseCase,
6263
private val retryFailedUploadsUseCase: RetryFailedUploadsUseCase,
6364
private val clearSuccessfulTransfersUseCase: ClearSuccessfulTransfersUseCase,
64-
getAllTransfersAsLiveDataUseCase: GetAllTransfersAsLiveDataUseCase,
65+
getAllTransfersAsStreamUseCase: GetAllTransfersAsStreamUseCase,
6566
private val cancelDownloadForFileUseCase: CancelDownloadForFileUseCase,
6667
private val cancelUploadForFileUseCase: CancelUploadForFileUseCase,
6768
private val cancelUploadsRecursivelyUseCase: CancelUploadsRecursivelyUseCase,
6869
private val cancelDownloadsRecursivelyUseCase: CancelDownloadsRecursivelyUseCase,
69-
private val getSpacesFromEveryAccountUseCase: GetSpacesFromEveryAccountUseCase,
70+
getSpacesFromEveryAccountUseCaseAsStream: GetSpacesFromEveryAccountUseCaseAsStream,
7071
private val coroutinesDispatcherProvider: CoroutinesDispatcherProvider,
7172
workManagerProvider: WorkManagerProvider,
7273
) : ViewModel() {
73-
74-
private val _transfersListLiveData = MediatorLiveData<List<OCTransfer>>()
75-
val transfersListLiveData: LiveData<List<OCTransfer>>
76-
get() = _transfersListLiveData
77-
7874
private val _workInfosListLiveData = MediatorLiveData<List<WorkInfo>>()
7975
val workInfosListLiveData: LiveData<List<WorkInfo>>
8076
get() = _workInfosListLiveData
8177

82-
private var transfersLiveData = getAllTransfersAsLiveDataUseCase.execute(Unit)
78+
val transfersWithSpaceStateFlow: StateFlow<List<Pair<OCTransfer, OCSpace?>>> = combine(
79+
getAllTransfersAsStreamUseCase.execute(Unit),
80+
getSpacesFromEveryAccountUseCaseAsStream.execute(Unit)
81+
) { transfers: List<OCTransfer>, spaces: List<OCSpace> ->
82+
transfers.map { transfer ->
83+
val spaceForTransfer = spaces.firstOrNull { space -> transfer.spaceId == space.id && transfer.accountName == space.accountName }
84+
Pair(transfer, spaceForTransfer)
85+
}
86+
}.stateIn(
87+
scope = viewModelScope,
88+
started = SharingStarted.WhileSubscribed(5_000),
89+
initialValue = emptyList()
90+
)
8391

8492
private var workInfosLiveData = workManagerProvider.getRunningUploadsWorkInfosLiveData()
8593

86-
private val _spaces: MutableStateFlow<List<OCSpace>> = MutableStateFlow(emptyList())
87-
val spaces: StateFlow<List<OCSpace>>
88-
get() = _spaces
89-
9094
init {
91-
_transfersListLiveData.addSource(transfersLiveData) { transfers ->
92-
_transfersListLiveData.postValue(transfers)
93-
}
9495
_workInfosListLiveData.addSource(workInfosLiveData) { workInfos ->
9596
_workInfosListLiveData.postValue(workInfos)
9697
}
97-
viewModelScope.launch(coroutinesDispatcherProvider.io) {
98-
val spacesList = getSpacesFromEveryAccountUseCase.execute(Unit)
99-
_spaces.update { spacesList }
100-
}
10198
}
10299

103100
fun uploadFilesFromContentUri(

owncloudData/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ dependencies {
7171

7272
// Dependencies for instrumented tests
7373
androidTestImplementation project(":owncloudTestUtil")
74+
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$orgJetbrainsKotlinx"
7475
androidTestImplementation "androidx.test:runner:$androidxTest"
7576
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxTestEspresso"
7677
androidTestImplementation "androidx.test.ext:junit:$androidxTestExt"

0 commit comments

Comments
 (0)