Skip to content

Commit

Permalink
Merge pull request #3887 from owncloud/spaces/copy_and_move
Browse files Browse the repository at this point in the history
[SPACES] Copy and move operations
  • Loading branch information
abelgardep authored Feb 13, 2023
2 parents d8ed3a4 + ce094e3 commit 618c39c
Show file tree
Hide file tree
Showing 31 changed files with 576 additions and 418 deletions.
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 @@ -596,7 +596,7 @@ class MainFileListFragment : Fragment(),
R.id.action_move -> {
val action = Intent(activity, FolderPickerActivity::class.java)
action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, checkedFiles)
action.putExtra(FolderPickerActivity.EXTRA_PICKER_OPTION, FolderPickerActivity.PickerMode.MOVE)
action.putExtra(FolderPickerActivity.EXTRA_PICKER_MODE, FolderPickerActivity.PickerMode.MOVE)
requireActivity().startActivityForResult(action, FileDisplayActivity.REQUEST_CODE__MOVE_FILES)
fileListAdapter.clearSelection()
updateActionModeAfterTogglingSelected()
Expand All @@ -605,7 +605,7 @@ class MainFileListFragment : Fragment(),
R.id.action_copy -> {
val action = Intent(activity, FolderPickerActivity::class.java)
action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, checkedFiles)
action.putExtra(FolderPickerActivity.EXTRA_PICKER_OPTION, FolderPickerActivity.PickerMode.COPY)
action.putExtra(FolderPickerActivity.EXTRA_PICKER_MODE, FolderPickerActivity.PickerMode.COPY)
requireActivity().startActivityForResult(action, FileDisplayActivity.REQUEST_CODE__COPY_FILES)
fileListAdapter.clearSelection()
updateActionModeAfterTogglingSelected()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ class SettingsPictureUploadsFragment : PreferenceFragmentCompat() {
}
val intent = Intent(activity, UploadPathActivity::class.java).apply {
putExtra(UploadPathActivity.KEY_CAMERA_UPLOAD_PATH, uploadPath)
putExtra(FolderPickerActivity.EXTRA_PICKER_OPTION, FolderPickerActivity.PickerMode.CAMERA_FOLDER)
putExtra(FolderPickerActivity.EXTRA_PICKER_MODE, FolderPickerActivity.PickerMode.CAMERA_FOLDER)
putExtra(UploadPathActivity.KEY_CAMERA_UPLOAD_ACCOUNT, picturesViewModel.getPictureUploadsAccount())
}
selectPictureUploadsPathLauncher.launch(intent)
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 @@ -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 @@ -167,7 +167,7 @@ class SettingsVideoUploadsFragment : PreferenceFragmentCompat() {
}
val intent = Intent(activity, UploadPathActivity::class.java).apply {
putExtra(UploadPathActivity.KEY_CAMERA_UPLOAD_PATH, uploadPath)
putExtra(FolderPickerActivity.EXTRA_PICKER_OPTION, FolderPickerActivity.PickerMode.CAMERA_FOLDER)
putExtra(FolderPickerActivity.EXTRA_PICKER_MODE, FolderPickerActivity.PickerMode.CAMERA_FOLDER)
putExtra(UploadPathActivity.KEY_CAMERA_UPLOAD_ACCOUNT, videosViewModel.getVideoUploadsAccount())
}
selectVideoUploadsPathLauncher.launch(intent)
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 @@ -24,8 +24,10 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.os.bundleOf
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.setFragmentResult
import androidx.recyclerview.widget.GridLayoutManager
import com.owncloud.android.R
import com.owncloud.android.databinding.SpacesListFragmentBinding
Expand All @@ -36,14 +38,20 @@ 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

Expand Down Expand Up @@ -83,9 +91,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()
setFragmentResult(REQUEST_KEY_CLICK_SPACE, bundleOf(BUNDLE_KEY_CLICK_SPACE to it))
}
}
}
Expand All @@ -104,4 +110,9 @@ class SpacesListFragment : SpacesListAdapter.SpacesListAdapterListener, Fragment
override fun onItemClick(ocSpace: OCSpace) {
spacesListViewModel.getRootFileForSpace(ocSpace)
}

companion object {
const val REQUEST_KEY_CLICK_SPACE = "REQUEST_KEY_CLICK_SPACE"
const val BUNDLE_KEY_CLICK_SPACE = "BUNDLE_KEY_CLICK_SPACE"
}
}
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
Loading

0 comments on commit 618c39c

Please sign in to comment.