Skip to content

Commit

Permalink
Merge pull request #3973 from owncloud/spaces/space_in_ocfile
Browse files Browse the repository at this point in the history
Add space to OCFileWithSyncInfo
  • Loading branch information
abelgardep authored Mar 22, 2023
2 parents 1e565db + 5636453 commit 84f0a32
Show file tree
Hide file tree
Showing 28 changed files with 173 additions and 188 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,14 @@ import com.owncloud.android.domain.sharing.shares.usecases.EditPublicShareAsyncU
import com.owncloud.android.domain.sharing.shares.usecases.GetShareAsLiveDataUseCase
import com.owncloud.android.domain.sharing.shares.usecases.GetSharesAsLiveDataUseCase
import com.owncloud.android.domain.sharing.shares.usecases.RefreshSharesFromServerAsyncUseCase
import com.owncloud.android.domain.spaces.usecases.GetSpacesFromEveryAccountUseCase
import com.owncloud.android.domain.spaces.usecases.GetSpacesFromEveryAccountUseCaseAsStream
import com.owncloud.android.domain.spaces.usecases.GetPersonalAndProjectSpacesForAccountUseCase
import com.owncloud.android.domain.spaces.usecases.GetPersonalAndProjectSpacesWithSpecialsForAccountAsStreamUseCase
import com.owncloud.android.domain.spaces.usecases.GetProjectSpacesWithSpecialsForAccountAsStreamUseCase
import com.owncloud.android.domain.spaces.usecases.GetSpaceWithSpecialsByIdForAccountUseCase
import com.owncloud.android.domain.spaces.usecases.RefreshSpacesFromServerAsyncUseCase
import com.owncloud.android.domain.transfers.usecases.ClearSuccessfulTransfersUseCase
import com.owncloud.android.domain.transfers.usecases.GetAllTransfersAsLiveDataUseCase
import com.owncloud.android.domain.transfers.usecases.GetAllTransfersAsStreamUseCase
import com.owncloud.android.domain.transfers.usecases.GetAllTransfersUseCase
import com.owncloud.android.domain.transfers.usecases.UpdatePendingUploadsPathUseCase
import com.owncloud.android.domain.user.usecases.GetStoredQuotaUseCase
Expand Down Expand Up @@ -186,7 +186,7 @@ val useCaseModule = module {
factory { RefreshSharesFromServerAsyncUseCase(get()) }

// Spaces
factory { GetSpacesFromEveryAccountUseCase(get()) }
factory { GetSpacesFromEveryAccountUseCaseAsStream(get()) }
factory { GetPersonalAndProjectSpacesForAccountUseCase(get()) }
factory { GetPersonalAndProjectSpacesWithSpecialsForAccountAsStreamUseCase(get()) }
factory { GetProjectSpacesWithSpecialsForAccountAsStreamUseCase(get()) }
Expand All @@ -209,7 +209,7 @@ val useCaseModule = module {
factory { CancelUploadsRecursivelyUseCase(get(), get(), get(), get()) }
factory { RetryUploadFromSystemUseCase(get(), get(), get()) }
factory { RetryUploadFromContentUriUseCase(get(), get(), get()) }
factory { GetAllTransfersAsLiveDataUseCase(get()) }
factory { GetAllTransfersAsStreamUseCase(get()) }
factory { GetAllTransfersUseCase(get()) }
factory { CancelUploadUseCase(get(), get(), get()) }
factory { ClearFailedTransfersUseCase(get(), get(), get()) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ val viewModelModule = module {
get(),
get(),
get(),
get(),
initialFolderToDisplay,
fileListOption,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ import com.owncloud.android.datamodel.ThumbnailsCacheManager
import com.owncloud.android.domain.files.model.FileListOption
import com.owncloud.android.domain.files.model.OCFileWithSyncInfo
import com.owncloud.android.domain.files.model.OCFooterFile
import com.owncloud.android.domain.spaces.model.OCSpace
import com.owncloud.android.presentation.authentication.AccountUtils
import com.owncloud.android.utils.DisplayUtils
import com.owncloud.android.utils.MimetypeIconUtil
Expand All @@ -59,14 +58,10 @@ class FileListAdapter(
private var account: Account? = AccountUtils.getCurrentOwnCloudAccount(context)
private var fileListOption: FileListOption = FileListOption.ALL_FILES

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

val listWithFooter = mutableListOf<Any>()
listWithFooter.addAll(fileItems)
listWithFooter.addAll(filesToAdd)

if (listWithFooter.isNotEmpty()) {
listWithFooter.add(OCFooterFile(manageListOfFilesAndGenerateText(filesToAdd)))
Expand Down Expand Up @@ -139,7 +134,7 @@ class FileListAdapter(
layoutManager.spanCount == 1 -> {
ViewType.LIST_ITEM.ordinal
}
(files[position] as FileItem).fileWithSyncInfo.file.isImage -> {
(files[position] as OCFileWithSyncInfo).file.isImage -> {
ViewType.GRID_IMAGE.ordinal
}
else -> {
Expand Down Expand Up @@ -179,8 +174,7 @@ class FileListAdapter(

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

val fileItem = files[position] as FileItem
val fileWithSyncInfo = fileItem.fileWithSyncInfo
val fileWithSyncInfo = files[position] as OCFileWithSyncInfo
val file = fileWithSyncInfo.file
val name = file.fileName
val fileIcon = holder.itemView.findViewById<ImageView>(R.id.thumbnail).apply {
Expand Down Expand Up @@ -211,12 +205,12 @@ class FileListAdapter(
it.Filename.text = file.fileName
it.fileListSize.text = DisplayUtils.bytesToHumanReadable(file.length, context)
it.fileListLastMod.text = DisplayUtils.getRelativeTimestamp(context, file.modificationTimestamp)
if (fileListOption.isAvailableOffline() || (fileListOption.isSharedByLink() && fileItem.space == null)) {
if (fileListOption.isAvailableOffline() || (fileListOption.isSharedByLink() && fileWithSyncInfo.space == null)) {
it.spacePathLine.path.apply {
text = file.getParentRemotePath()
isVisible = true
}
fileItem.space?.let { space ->
fileWithSyncInfo.space?.let { space ->
it.spacePathLine.spaceIcon.isVisible = true
it.spacePathLine.spaceName.isVisible = true
if (space.isPersonal) {
Expand Down Expand Up @@ -406,8 +400,6 @@ class FileListAdapter(
fun onLongItemClick(position: Int): Boolean = true
}

data class FileItem(val fileWithSyncInfo: OCFileWithSyncInfo, val space: OCSpace?)

inner class GridViewHolder(val binding: GridItemBinding) : RecyclerView.ViewHolder(binding.root)
inner class GridImageViewHolder(val binding: GridItemBinding) : RecyclerView.ViewHolder(binding.root)
inner class ListViewHolder(val binding: ItemFileListBinding) : RecyclerView.ViewHolder(binding.root)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ package com.owncloud.android.presentation.files.filelist

import androidx.recyclerview.widget.DiffUtil
import com.owncloud.android.domain.files.model.FileListOption
import com.owncloud.android.domain.files.model.OCFileWithSyncInfo
import com.owncloud.android.domain.files.model.OCFooterFile

class FileListDiffCallback(
Expand All @@ -48,8 +49,8 @@ class FileListDiffCallback(
return true
}

if (oldItem is FileListAdapter.FileItem && newItem is FileListAdapter.FileItem) {
return oldItem.fileWithSyncInfo.file.id == newItem.fileWithSyncInfo.file.id
if (oldItem is OCFileWithSyncInfo && newItem is OCFileWithSyncInfo) {
return oldItem.file.id == newItem.file.id
}

if (oldItem is OCFooterFile && newItem is OCFooterFile) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,6 @@ class MainFileListFragment : Fragment(),
fileListAdapter.updateFileList(
filesToAdd = fileListUiState.folderContent,
fileListOption = fileListUiState.fileListOption,
spaces = mainFileListViewModel.spaces.value,
)
showOrHideEmptyView(fileListUiState)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import com.owncloud.android.domain.files.usecases.GetSharedByLinkForAccountAsStr
import com.owncloud.android.domain.files.usecases.SortFilesWithSyncInfoUseCase
import com.owncloud.android.domain.spaces.model.OCSpace
import com.owncloud.android.domain.spaces.usecases.GetSpaceWithSpecialsByIdForAccountUseCase
import com.owncloud.android.domain.spaces.usecases.GetSpacesFromEveryAccountUseCase
import com.owncloud.android.presentation.files.SortOrder
import com.owncloud.android.presentation.files.SortOrder.Companion.PREF_FILE_LIST_SORT_ORDER
import com.owncloud.android.presentation.files.SortType
Expand Down Expand Up @@ -68,7 +67,6 @@ class MainFileListViewModel(
private val getSpaceWithSpecialsByIdForAccountUseCase: GetSpaceWithSpecialsByIdForAccountUseCase,
private val sortFilesWithSyncInfoUseCase: SortFilesWithSyncInfoUseCase,
private val synchronizeFolderUseCase: SynchronizeFolderUseCase,
private val getSpacesFromEveryAccountUseCase: GetSpacesFromEveryAccountUseCase, // TODO: To be deleted when adding the space to the file entity
private val coroutinesDispatcherProvider: CoroutinesDispatcherProvider,
private val sharedPreferencesProvider: SharedPreferencesProvider,
initialFolderToDisplay: OCFile,
Expand All @@ -83,10 +81,6 @@ class MainFileListViewModel(
private val sortTypeAndOrder = MutableStateFlow(Pair(SortType.SORT_TYPE_BY_NAME, SortOrder.SORT_ORDER_ASCENDING))
val space: MutableStateFlow<OCSpace?> = MutableStateFlow(null)

private val _spaces: MutableStateFlow<List<OCSpace>> = MutableStateFlow(emptyList())
val spaces: StateFlow<List<OCSpace>>
get() = _spaces

/** File list ui state combines the other fields and generate a new state whenever any of them changes */
val fileListUiState: StateFlow<FileListUiState> =
combine(
Expand Down Expand Up @@ -127,10 +121,6 @@ class MainFileListViewModel(
)
)
}
viewModelScope.launch(coroutinesDispatcherProvider.io) {
val spacesList = getSpacesFromEveryAccountUseCase.execute(Unit)
_spaces.update { spacesList }
}
}

fun navigateToFolderId(folderId: Long) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.snackbar.Snackbar
import com.owncloud.android.R
import com.owncloud.android.databinding.FragmentTransferListBinding
import com.owncloud.android.domain.spaces.model.OCSpace
import com.owncloud.android.domain.transfers.model.OCTransfer
import com.owncloud.android.domain.transfers.model.TransferResult
import com.owncloud.android.extensions.collectLatestLifecycleFlow
Expand Down Expand Up @@ -99,7 +100,7 @@ class TransferListFragment : Fragment() {
addItemDecoration(DividerItemDecoration(context, DividerItemDecoration.VERTICAL))
}

transfersViewModel.transfersListLiveData.observe(viewLifecycleOwner) { transfers ->
collectLatestLifecycleFlow(transfersViewModel.transfersWithSpaceStateFlow) { transfers ->
val recyclerViewState = binding.transfersRecyclerView.layoutManager?.onSaveInstanceState()
setData(transfers)
binding.transfersRecyclerView.layoutManager?.onRestoreInstanceState(recyclerViewState)
Expand All @@ -111,25 +112,21 @@ class TransferListFragment : Fragment() {
}
}

collectLatestLifecycleFlow(transfersViewModel.spaces) {
transfersViewModel.transfersListLiveData.value?.let { transfers -> setData(transfers) }
}

}

override fun onDestroy() {
super.onDestroy()
_binding = null
}

private fun setData(items: List<OCTransfer>) {
binding.transfersRecyclerView.isVisible = items.isNotEmpty()
private fun setData(transfersWithSpace: List<Pair<OCTransfer, OCSpace?>>) {
binding.transfersRecyclerView.isVisible = transfersWithSpace.isNotEmpty()
binding.transfersListEmpty.apply {
root.isVisible = items.isEmpty()
root.isVisible = transfersWithSpace.isEmpty()
listEmptyDatasetIcon.setImageResource(R.drawable.ic_uploads)
listEmptyDatasetTitle.setText(R.string.upload_list_empty)
listEmptyDatasetSubTitle.setText(R.string.upload_list_empty_subtitle)
}
transfersAdapter.setData(items, transfersViewModel.spaces.value)
transfersAdapter.setData(transfersWithSpace)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -235,15 +235,14 @@ class TransfersAdapter(
}
}

fun setData(transfers: List<OCTransfer>, spaces: List<OCSpace>) {
val transfersGroupedByStatus = transfers.groupBy { it.status }
fun setData(transfersWithSpace: List<Pair<OCTransfer, OCSpace?>>) {
val transfersGroupedByStatus = transfersWithSpace.groupBy { it.first.status }
val newTransferItemsList = mutableListOf<TransferRecyclerItem>()
transfersGroupedByStatus.forEach { transferMap ->
val headerItem = HeaderItem(transferMap.key, transferMap.value.size)
newTransferItemsList.add(headerItem)
val transferItems = transferMap.value.sortedByDescending { it.transferEndTimestamp ?: it.id }.map { transfer ->
val space = spaces.firstOrNull { it.id == transfer.spaceId && it.accountName == transfer.accountName }
TransferItem(transfer, space)
val transferItems = transferMap.value.sortedByDescending { it.first.transferEndTimestamp ?: it.first.id }.map { transfersWithSpace ->
TransferItem(transfersWithSpace.first, transfersWithSpace.second)
}
newTransferItemsList.addAll(transferItems)
}
Expand Down Expand Up @@ -283,6 +282,7 @@ class TransfersAdapter(
val transfer: OCTransfer,
val space: OCSpace?,
) : TransferRecyclerItem

data class HeaderItem(
val status: TransferStatus,
val numberTransfers: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ import androidx.lifecycle.viewModelScope
import androidx.work.WorkInfo
import com.owncloud.android.domain.files.model.OCFile
import com.owncloud.android.domain.spaces.model.OCSpace
import com.owncloud.android.domain.spaces.usecases.GetSpacesFromEveryAccountUseCase
import com.owncloud.android.domain.spaces.usecases.GetSpacesFromEveryAccountUseCaseAsStream
import com.owncloud.android.domain.transfers.model.OCTransfer
import com.owncloud.android.domain.transfers.usecases.ClearSuccessfulTransfersUseCase
import com.owncloud.android.domain.transfers.usecases.GetAllTransfersAsLiveDataUseCase
import com.owncloud.android.domain.transfers.usecases.GetAllTransfersAsStreamUseCase
import com.owncloud.android.providers.CoroutinesDispatcherProvider
import com.owncloud.android.providers.WorkManagerProvider
import com.owncloud.android.usecases.transfers.downloads.CancelDownloadForFileUseCase
Expand All @@ -46,9 +46,10 @@ import com.owncloud.android.usecases.transfers.uploads.RetryUploadFromContentUri
import com.owncloud.android.usecases.transfers.uploads.RetryUploadFromSystemUseCase
import com.owncloud.android.usecases.transfers.uploads.UploadFilesFromContentUriUseCase
import com.owncloud.android.usecases.transfers.uploads.UploadFilesFromSystemUseCase
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch

class TransfersViewModel(
Expand All @@ -61,43 +62,39 @@ class TransfersViewModel(
private val clearFailedTransfersUseCase: ClearFailedTransfersUseCase,
private val retryFailedUploadsUseCase: RetryFailedUploadsUseCase,
private val clearSuccessfulTransfersUseCase: ClearSuccessfulTransfersUseCase,
getAllTransfersAsLiveDataUseCase: GetAllTransfersAsLiveDataUseCase,
getAllTransfersAsStreamUseCase: GetAllTransfersAsStreamUseCase,
private val cancelDownloadForFileUseCase: CancelDownloadForFileUseCase,
private val cancelUploadForFileUseCase: CancelUploadForFileUseCase,
private val cancelUploadsRecursivelyUseCase: CancelUploadsRecursivelyUseCase,
private val cancelDownloadsRecursivelyUseCase: CancelDownloadsRecursivelyUseCase,
private val getSpacesFromEveryAccountUseCase: GetSpacesFromEveryAccountUseCase,
getSpacesFromEveryAccountUseCaseAsStream: GetSpacesFromEveryAccountUseCaseAsStream,
private val coroutinesDispatcherProvider: CoroutinesDispatcherProvider,
workManagerProvider: WorkManagerProvider,
) : ViewModel() {

private val _transfersListLiveData = MediatorLiveData<List<OCTransfer>>()
val transfersListLiveData: LiveData<List<OCTransfer>>
get() = _transfersListLiveData

private val _workInfosListLiveData = MediatorLiveData<List<WorkInfo>>()
val workInfosListLiveData: LiveData<List<WorkInfo>>
get() = _workInfosListLiveData

private var transfersLiveData = getAllTransfersAsLiveDataUseCase.execute(Unit)
val transfersWithSpaceStateFlow: StateFlow<List<Pair<OCTransfer, OCSpace?>>> = combine(
getAllTransfersAsStreamUseCase.execute(Unit),
getSpacesFromEveryAccountUseCaseAsStream.execute(Unit)
) { transfers: List<OCTransfer>, spaces: List<OCSpace> ->
transfers.map { transfer ->
val spaceForTransfer = spaces.firstOrNull { space -> transfer.spaceId == space.id && transfer.accountName == space.accountName }
Pair(transfer, spaceForTransfer)
}
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = emptyList()
)

private var workInfosLiveData = workManagerProvider.getRunningUploadsWorkInfosLiveData()

private val _spaces: MutableStateFlow<List<OCSpace>> = MutableStateFlow(emptyList())
val spaces: StateFlow<List<OCSpace>>
get() = _spaces

init {
_transfersListLiveData.addSource(transfersLiveData) { transfers ->
_transfersListLiveData.postValue(transfers)
}
_workInfosListLiveData.addSource(workInfosLiveData) { workInfos ->
_workInfosListLiveData.postValue(workInfos)
}
viewModelScope.launch(coroutinesDispatcherProvider.io) {
val spacesList = getSpacesFromEveryAccountUseCase.execute(Unit)
_spaces.update { spacesList }
}
}

fun uploadFilesFromContentUri(
Expand Down
1 change: 1 addition & 0 deletions owncloudData/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ dependencies {

// Dependencies for instrumented tests
androidTestImplementation project(":owncloudTestUtil")
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$orgJetbrainsKotlinx"
androidTestImplementation "androidx.test:runner:$androidxTest"
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxTestEspresso"
androidTestImplementation "androidx.test.ext:junit:$androidxTestExt"
Expand Down
Loading

0 comments on commit 84f0a32

Please sign in to comment.