Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SPACES] Copy and move operations #3887

Merged
merged 12 commits into from
Feb 13, 2023
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ import com.owncloud.android.domain.sharing.shares.usecases.GetShareAsLiveDataUse
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.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
Expand Down Expand Up @@ -179,6 +180,7 @@ val useCaseModule = module {

// Spaces
factory { GetPersonalAndProjectSpacesForAccountUseCase(get()) }
factory { GetPersonalAndProjectSpacesWithSpecialsForAccountAsStreamUseCase(get()) }
factory { GetProjectSpacesWithSpecialsForAccountAsStreamUseCase(get()) }
factory { GetSpaceWithSpecialsByIdForAccountUseCase(get()) }
factory { RefreshSpacesFromServerAsyncUseCase(get()) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,5 +113,7 @@ val viewModelModule = module {
viewModel { (ocFile: OCFile) -> ConflictsResolveViewModel(get(), get(), get(), get(), get(), ocFile) }
viewModel { ReceiveExternalFilesViewModel(get(), get()) }
viewModel { AccountsManagementViewModel(get()) }
viewModel { SpacesListViewModel(get(), get(), get(), get(), get()) }
viewModel { (showPersonalSpace: Boolean) ->
SpacesListViewModel(get(), get(), get(), get(), get(), get(), showPersonalSpace)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ protected RemoteOperationResult<Account> run(OwnCloudClient client) {
return new RemoteOperationResult<>(new IllegalStateException(
"Account to validate is not the account connected to!"));
} else {
RemoteOperation checkPathExistenceOperation = new CheckPathExistenceRemoteOperation(OCFile.ROOT_PATH, false);
RemoteOperation checkPathExistenceOperation = new CheckPathExistenceRemoteOperation(OCFile.ROOT_PATH, false, null);
final RemoteOperationResult existenceCheckResult = checkPathExistenceOperation.execute(client);
final RemoteOperationResult<Account> result
= new RemoteOperationResult<>(existenceCheckResult.getCode());
result.setData(mAccount);
return result;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import com.owncloud.android.domain.files.model.OCFile
import com.owncloud.android.providers.AccountProvider
import com.owncloud.android.providers.CoroutinesDispatcherProvider
import com.owncloud.android.providers.WorkManagerProvider
import com.owncloud.android.ui.activity.UploadPathActivity
import com.owncloud.android.ui.activity.FolderPickerActivity
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
Expand Down Expand Up @@ -111,7 +111,7 @@ class SettingsPictureUploadsViewModel(
fun getPictureUploadsSourcePath(): String? = _pictureUploads.value?.sourcePath

fun handleSelectPictureUploadsPath(data: Intent?) {
val folderToUpload = data?.getParcelableExtra<OCFile>(UploadPathActivity.EXTRA_FOLDER)
val folderToUpload = data?.getParcelableExtra<OCFile>(FolderPickerActivity.EXTRA_FOLDER)
folderToUpload?.remotePath?.let {
viewModelScope.launch(coroutinesDispatcherProvider.io) {
savePictureUploadsConfigurationUseCase.execute(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import com.owncloud.android.domain.files.model.OCFile
import com.owncloud.android.providers.AccountProvider
import com.owncloud.android.providers.CoroutinesDispatcherProvider
import com.owncloud.android.providers.WorkManagerProvider
import com.owncloud.android.ui.activity.UploadPathActivity
import com.owncloud.android.ui.activity.FolderPickerActivity
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
Expand Down Expand Up @@ -110,7 +110,7 @@ class SettingsVideoUploadsViewModel(
fun getVideoUploadsSourcePath(): String? = _videoUploads.value?.sourcePath

fun handleSelectVideoUploadsPath(data: Intent?) {
val folderToUpload = data?.getParcelableExtra<OCFile>(UploadPathActivity.EXTRA_FOLDER)
val folderToUpload = data?.getParcelableExtra<OCFile>(FolderPickerActivity.EXTRA_FOLDER)
folderToUpload?.remotePath?.let {
viewModelScope.launch(coroutinesDispatcherProvider.io) {
saveVideoUploadsConfigurationUseCase.execute(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* @author Juan Carlos Garrote Gascón
*
* Copyright (C) 2022 ownCloud GmbH.
* Copyright (C) 2023 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,
Expand Down Expand Up @@ -54,36 +54,42 @@ class SpacesListAdapter(
listener.onItemClick(space)
}

spacesListItemName.text = space.name
spacesListItemSubtitle.text = space.description
if (space.isPersonal) {
spacesListItemName.text = holder.itemView.context.getString(R.string.bottom_nav_personal)

val spaceSpecialImage = space.getSpaceSpecialImage()
spacesListItemImage.tag = spaceSpecialImage?.id
spacesListItemImage.setImageResource(R.drawable.ic_folder)
} else {
spacesListItemName.text = space.name
spacesListItemSubtitle.text = space.description

if (spaceSpecialImage != null) {
val thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(spaceSpecialImage.id)
if (thumbnail != null) {
spacesListItemImage.run {
setImageBitmap(thumbnail)
scaleType = ImageView.ScaleType.CENTER_CROP
}
}
if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(spaceSpecialImage, spacesListItemImage)) {
val account = AccountUtils.getOwnCloudAccountByName(spacesViewHolder.itemView.context, space.accountName)
val task = ThumbnailsCacheManager.ThumbnailGenerationTask(spacesListItemImage, account)
val asyncDrawable = ThumbnailsCacheManager.AsyncThumbnailDrawable(spacesViewHolder.itemView.resources, thumbnail, task)
val spaceSpecialImage = space.getSpaceSpecialImage()
spacesListItemImage.tag = spaceSpecialImage?.id

// If drawable is not visible, do not update it.
if (asyncDrawable.minimumHeight > 0 && asyncDrawable.minimumWidth > 0) {
if (spaceSpecialImage != null) {
val thumbnail = ThumbnailsCacheManager.getBitmapFromDiskCache(spaceSpecialImage.id)
if (thumbnail != null) {
spacesListItemImage.run {
spacesListItemImage.setImageDrawable(asyncDrawable)
setImageBitmap(thumbnail)
scaleType = ImageView.ScaleType.CENTER_CROP
}
}
task.execute(spaceSpecialImage)
}
if (spaceSpecialImage.file.mimeType == "image/png") {
spacesListItemImage.setBackgroundColor(ContextCompat.getColor(spacesViewHolder.itemView.context, R.color.background_color))
if (ThumbnailsCacheManager.cancelPotentialThumbnailWork(spaceSpecialImage, spacesListItemImage)) {
val account = AccountUtils.getOwnCloudAccountByName(spacesViewHolder.itemView.context, space.accountName)
val task = ThumbnailsCacheManager.ThumbnailGenerationTask(spacesListItemImage, account)
val asyncDrawable = ThumbnailsCacheManager.AsyncThumbnailDrawable(spacesViewHolder.itemView.resources, thumbnail, task)

// If drawable is not visible, do not update it.
if (asyncDrawable.minimumHeight > 0 && asyncDrawable.minimumWidth > 0) {
spacesListItemImage.run {
spacesListItemImage.setImageDrawable(asyncDrawable)
scaleType = ImageView.ScaleType.CENTER_CROP
}
}
task.execute(spaceSpecialImage)
}
if (spaceSpecialImage.file.mimeType == "image/png") {
spacesListItemImage.setBackgroundColor(ContextCompat.getColor(spacesViewHolder.itemView.context, R.color.background_color))
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* @author Juan Carlos Garrote Gascón
*
* Copyright (C) 2022 ownCloud GmbH.
* Copyright (C) 2023 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,
Expand All @@ -30,23 +30,32 @@ import androidx.recyclerview.widget.GridLayoutManager
import com.owncloud.android.R
import com.owncloud.android.databinding.SpacesListFragmentBinding
import com.owncloud.android.domain.files.model.FileListOption
import com.owncloud.android.domain.files.model.OCFile
import com.owncloud.android.domain.spaces.model.OCSpace
import com.owncloud.android.extensions.collectLatestLifecycleFlow
import com.owncloud.android.extensions.showErrorInSnackbar
import com.owncloud.android.extensions.toDrawableRes
import com.owncloud.android.extensions.toSubtitleStringRes
import com.owncloud.android.extensions.toTitleStringRes
import com.owncloud.android.ui.activity.FileDisplayActivity
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf

class SpacesListFragment : SpacesListAdapter.SpacesListAdapterListener, Fragment() {
class SpacesListFragment(
val showPersonalSpace: Boolean = false,
) : SpacesListAdapter.SpacesListAdapterListener, Fragment() {
private var _binding: SpacesListFragmentBinding? = null
private val binding get() = _binding!!

private val spacesListViewModel: SpacesListViewModel by viewModel()
private val spacesListViewModel: SpacesListViewModel by viewModel() {
parametersOf(
showPersonalSpace
)
}

private lateinit var spacesListAdapter: SpacesListAdapter

var spacesActions: SpacesActions? = null

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
Expand Down Expand Up @@ -83,9 +92,7 @@ class SpacesListFragment : SpacesListAdapter.SpacesListAdapterListener, Fragment
uiState.error?.let { showErrorInSnackbar(R.string.spaces_sync_failed, it) }

uiState.rootFolderFromSelectedSpace?.let {
val parentActivity = requireActivity() as FileDisplayActivity
parentActivity.file = it
parentActivity.initAndShowListOfFiles()
spacesActions?.onSpaceClicked(it)
}
}
}
Expand All @@ -104,4 +111,8 @@ class SpacesListFragment : SpacesListAdapter.SpacesListAdapterListener, Fragment
override fun onItemClick(ocSpace: OCSpace) {
spacesListViewModel.getRootFileForSpace(ocSpace)
}

interface SpacesActions {
fun onSpaceClicked(rootFolder: OCFile)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* @author Juan Carlos Garrote Gascón
*
* Copyright (C) 2022 ownCloud GmbH.
* Copyright (C) 2023 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,
Expand All @@ -28,6 +28,7 @@ import com.owncloud.android.domain.files.model.OCFile
import com.owncloud.android.domain.files.model.OCFile.Companion.ROOT_PATH
import com.owncloud.android.domain.files.usecases.GetFileByRemotePathUseCase
import com.owncloud.android.domain.spaces.model.OCSpace
import com.owncloud.android.domain.spaces.usecases.GetPersonalAndProjectSpacesWithSpecialsForAccountAsStreamUseCase
import com.owncloud.android.domain.spaces.usecases.GetProjectSpacesWithSpecialsForAccountAsStreamUseCase
import com.owncloud.android.domain.spaces.usecases.RefreshSpacesFromServerAsyncUseCase
import com.owncloud.android.providers.CoroutinesDispatcherProvider
Expand All @@ -38,10 +39,12 @@ import kotlinx.coroutines.launch

class SpacesListViewModel(
private val refreshSpacesFromServerAsyncUseCase: RefreshSpacesFromServerAsyncUseCase,
private val getPersonalAndProjectSpacesWithSpecialsForAccountAsStreamUseCase: GetPersonalAndProjectSpacesWithSpecialsForAccountAsStreamUseCase,
private val getProjectSpacesWithSpecialsForAccountAsStreamUseCase: GetProjectSpacesWithSpecialsForAccountAsStreamUseCase,
private val getFileByRemotePathUseCase: GetFileByRemotePathUseCase,
private val coroutinesDispatcherProvider: CoroutinesDispatcherProvider,
private val account: Account,
private val showPersonalSpace: Boolean,
) : ViewModel() {

private val _spacesList: MutableStateFlow<SpacesListUiState> =
Expand All @@ -51,9 +54,12 @@ class SpacesListViewModel(
init {
viewModelScope.launch(coroutinesDispatcherProvider.io) {
refreshSpacesFromServer()
getProjectSpacesWithSpecialsForAccountAsStreamUseCase.execute(
val spacesListFlow = if (showPersonalSpace) getPersonalAndProjectSpacesWithSpecialsForAccountAsStreamUseCase.execute(
GetPersonalAndProjectSpacesWithSpecialsForAccountAsStreamUseCase.Params(accountName = account.name)
) else getProjectSpacesWithSpecialsForAccountAsStreamUseCase.execute(
GetProjectSpacesWithSpecialsForAccountAsStreamUseCase.Params(accountName = account.name)
).collect { spaces ->
)
spacesListFlow.collect { spaces ->
_spacesList.update { it.copy(spaces = spaces) }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ class FileDisplayActivity : FileActivity(),
FileFragment.ContainerActivity,
SecurityEnforced,
MainFileListFragment.FileActions,
MainFileListFragment.UploadActions {
MainFileListFragment.UploadActions,
SpacesListFragment.SpacesActions {

private val job = Job()
override val coroutineContext: CoroutineContext
Expand Down Expand Up @@ -324,7 +325,7 @@ class FileDisplayActivity : FileActivity(),
}
}

fun initAndShowListOfFiles(fileListOption: FileListOption = FileListOption.ALL_FILES) {
private fun initAndShowListOfFiles(fileListOption: FileListOption = FileListOption.ALL_FILES) {
val mainListOfFiles = MainFileListFragment.newInstance(
initialFolderToDisplay = file,
fileListOption = fileListOption,
Expand All @@ -340,7 +341,9 @@ class FileDisplayActivity : FileActivity(),
}

private fun initAndShowListOfSpaces() {
val listOfSpaces = SpacesListFragment()
val listOfSpaces = SpacesListFragment().apply {
spacesActions = this@FileDisplayActivity
}
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.left_fragment_container, listOfSpaces, TAG_LIST_OF_SPACES)
transaction.commit()
Expand Down Expand Up @@ -700,6 +703,7 @@ class FileDisplayActivity : FileActivity(),

if (listMainFileFragment?.getCurrentSpace()?.isProject == true) {
setCheckedItemAtBottomBar(getMenuItemForFileListOption(FileListOption.SPACES_LIST))
updateToolbar(null, listMainFileFragment?.getCurrentSpace())
} else {
setCheckedItemAtBottomBar(getMenuItemForFileListOption(fileListOption))
}
Expand Down Expand Up @@ -1484,6 +1488,11 @@ class FileDisplayActivity : FileActivity(),
)
}

override fun onSpaceClicked(rootFolder: OCFile) {
file = rootFolder
initAndShowListOfFiles()
}

companion object {
private const val TAG_LIST_OF_FILES = "LIST_OF_FILES"
private const val TAG_LIST_OF_SPACES = "LIST_OF_SPACES"
Expand Down
Loading