diff --git a/owncloud-android-library b/owncloud-android-library index f3c08bf2eb3..77e96a293e4 160000 --- a/owncloud-android-library +++ b/owncloud-android-library @@ -1 +1 @@ -Subproject commit f3c08bf2eb348b7c98831759d9d75a6833f7e29c +Subproject commit 77e96a293e4f26c36a7a554875635a530dacb4fb diff --git a/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/UseCaseModule.kt b/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/UseCaseModule.kt index 6ecf38d4e47..9a5756b59f6 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/UseCaseModule.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/UseCaseModule.kt @@ -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 @@ -179,6 +180,7 @@ val useCaseModule = module { // Spaces factory { GetPersonalAndProjectSpacesForAccountUseCase(get()) } + factory { GetPersonalAndProjectSpacesWithSpecialsForAccountAsStreamUseCase(get()) } factory { GetProjectSpacesWithSpecialsForAccountAsStreamUseCase(get()) } factory { GetSpaceWithSpecialsByIdForAccountUseCase(get()) } factory { RefreshSpacesFromServerAsyncUseCase(get()) } diff --git a/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/ViewModelModule.kt b/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/ViewModelModule.kt index e084fdc30d0..56660a2e945 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/ViewModelModule.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/ViewModelModule.kt @@ -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) + } } diff --git a/owncloudApp/src/main/java/com/owncloud/android/operations/CheckCurrentCredentialsOperation.java b/owncloudApp/src/main/java/com/owncloud/android/operations/CheckCurrentCredentialsOperation.java index da2e9a6cc89..6bb5d4cd1a5 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/operations/CheckCurrentCredentialsOperation.java +++ b/owncloudApp/src/main/java/com/owncloud/android/operations/CheckCurrentCredentialsOperation.java @@ -50,7 +50,7 @@ protected RemoteOperationResult 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 result = new RemoteOperationResult<>(existenceCheckResult.getCode()); @@ -58,4 +58,4 @@ protected RemoteOperationResult run(OwnCloudClient client) { return result; } } -} \ No newline at end of file +} diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainFileListFragment.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainFileListFragment.kt index c7138c023b5..2b33cf34e18 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainFileListFragment.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/MainFileListFragment.kt @@ -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() @@ -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() diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/autouploads/SettingsPictureUploadsFragment.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/autouploads/SettingsPictureUploadsFragment.kt index 425a9c6e75d..743a97d27a3 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/autouploads/SettingsPictureUploadsFragment.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/autouploads/SettingsPictureUploadsFragment.kt @@ -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) diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/autouploads/SettingsPictureUploadsViewModel.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/autouploads/SettingsPictureUploadsViewModel.kt index 55cdec32675..e3f3f394856 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/autouploads/SettingsPictureUploadsViewModel.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/autouploads/SettingsPictureUploadsViewModel.kt @@ -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 @@ -111,7 +111,7 @@ class SettingsPictureUploadsViewModel( fun getPictureUploadsSourcePath(): String? = _pictureUploads.value?.sourcePath fun handleSelectPictureUploadsPath(data: Intent?) { - val folderToUpload = data?.getParcelableExtra(UploadPathActivity.EXTRA_FOLDER) + val folderToUpload = data?.getParcelableExtra(FolderPickerActivity.EXTRA_FOLDER) folderToUpload?.remotePath?.let { viewModelScope.launch(coroutinesDispatcherProvider.io) { savePictureUploadsConfigurationUseCase.execute( diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/autouploads/SettingsVideoUploadsFragment.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/autouploads/SettingsVideoUploadsFragment.kt index 84c9988818c..91fa5e5e664 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/autouploads/SettingsVideoUploadsFragment.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/autouploads/SettingsVideoUploadsFragment.kt @@ -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) diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/autouploads/SettingsVideoUploadsViewModel.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/autouploads/SettingsVideoUploadsViewModel.kt index 4a0c9d0664e..66a8e870f5f 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/autouploads/SettingsVideoUploadsViewModel.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/autouploads/SettingsVideoUploadsViewModel.kt @@ -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 @@ -110,7 +110,7 @@ class SettingsVideoUploadsViewModel( fun getVideoUploadsSourcePath(): String? = _videoUploads.value?.sourcePath fun handleSelectVideoUploadsPath(data: Intent?) { - val folderToUpload = data?.getParcelableExtra(UploadPathActivity.EXTRA_FOLDER) + val folderToUpload = data?.getParcelableExtra(FolderPickerActivity.EXTRA_FOLDER) folderToUpload?.remotePath?.let { viewModelScope.launch(coroutinesDispatcherProvider.io) { saveVideoUploadsConfigurationUseCase.execute( diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/SpacesListAdapter.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/SpacesListAdapter.kt index 43260858d26..c4a507834bd 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/SpacesListAdapter.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/SpacesListAdapter.kt @@ -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, @@ -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)) + } } } } diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/SpacesListFragment.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/SpacesListFragment.kt index 5a6b5959e7f..a743dfdc567 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/SpacesListFragment.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/SpacesListFragment.kt @@ -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, @@ -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 @@ -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 @@ -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)) } } } @@ -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" + } } diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/SpacesListViewModel.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/SpacesListViewModel.kt index 4d1a611d3e0..22d3d642d09 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/SpacesListViewModel.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/spaces/SpacesListViewModel.kt @@ -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, @@ -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 @@ -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 = @@ -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) } } } diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt index 6aba1a821c7..93546256037 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt @@ -84,6 +84,8 @@ import com.owncloud.android.presentation.files.operations.FileOperationsViewMode import com.owncloud.android.presentation.security.bayPassUnlockOnce import com.owncloud.android.presentation.capabilities.CapabilityViewModel import com.owncloud.android.presentation.spaces.SpacesListFragment +import com.owncloud.android.presentation.spaces.SpacesListFragment.Companion.BUNDLE_KEY_CLICK_SPACE +import com.owncloud.android.presentation.spaces.SpacesListFragment.Companion.REQUEST_KEY_CLICK_SPACE import com.owncloud.android.presentation.transfers.TransfersViewModel import com.owncloud.android.providers.WorkManagerProvider import com.owncloud.android.syncadapter.FileSyncAdapter @@ -129,7 +131,7 @@ class FileDisplayActivity : FileActivity(), /** * FileDisplayActivity is based on those two containers. - * Left one is used for showing a list of files - [listMainFileFragment] + * Left one is used for showing a list of files - [mainFileListFragment] * Right one is used for showing previews, details... - [secondFragment] * * We should rename them to a more accurate names. @@ -139,7 +141,7 @@ class FileDisplayActivity : FileActivity(), private var leftFragmentContainer: FrameLayout? = null private var rightFragmentContainer: FrameLayout? = null - private val listMainFileFragment: MainFileListFragment? + private val mainFileListFragment: MainFileListFragment? get() = supportFragmentManager.findFragmentByTag(TAG_LIST_OF_FILES) as MainFileListFragment? private val spacesListFragment: SpacesListFragment? @@ -236,11 +238,17 @@ class FileDisplayActivity : FileActivity(), .add(taskRetainerFragment, TaskRetainerFragment.FTAG_TASK_RETAINER_FRAGMENT).commit() } // else, Fragment already created and retained across configuration change - Timber.v("onCreate() end") + supportFragmentManager.setFragmentResultListener(REQUEST_KEY_CLICK_SPACE, this) { _, bundle -> + val rootSpaceFolder = bundle.getParcelable(BUNDLE_KEY_CLICK_SPACE) + file = rootSpaceFolder + initAndShowListOfFiles() + } if (resources.getBoolean(R.bool.enable_rate_me_feature) && !BuildConfig.DEBUG) { AppRater.appLaunched(this, packageName) } + + Timber.v("onCreate() end") } override fun onPostCreate(savedInstanceState: Bundle?) { @@ -324,7 +332,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, @@ -349,7 +357,7 @@ class FileDisplayActivity : FileActivity(), private fun initFragmentsWithFile() { if (account != null && file != null) { /// First fragment - listMainFileFragment?.navigateToFolder(currentDir) + mainFileListFragment?.navigateToFolder(currentDir) ?: Timber.e("Still have a chance to lose the initialization of list fragment >(") /// Second fragment @@ -467,8 +475,8 @@ class FileDisplayActivity : FileActivity(), /*val fileListFragment = listOfFilesFragment fileListFragment?.listDirectory(reloadData)*/ if (file != null) { - val fileListFragment = listMainFileFragment - listMainFileFragment?.fileActions = this + val fileListFragment = mainFileListFragment + mainFileListFragment?.fileActions = this fileListFragment?.navigateToFolder(file) } } @@ -628,7 +636,7 @@ class FileDisplayActivity : FileActivity(), } override fun onBackPressed() { - val isFabOpen = listMainFileFragment?.isFabExpanded() ?: false + val isFabOpen = mainFileListFragment?.isFabExpanded() ?: false /* * BackPressed priority/hierarchy: @@ -644,17 +652,17 @@ class FileDisplayActivity : FileActivity(), super.onBackPressed() } else if (!isDrawerOpen() && isFabOpen) { // close fab - listMainFileFragment?.collapseFab() + mainFileListFragment?.collapseFab() } else { // Every single menu is collapsed. We can navigate up. if (secondFragment != null) { // If secondFragment was shown, we need to navigate to the parent of the displayed file // Need a cleanup - listMainFileFragment?.navigateToFolderId(secondFragment!!.file!!.parentId!!) + mainFileListFragment?.navigateToFolderId(secondFragment!!.file!!.parentId!!) cleanSecondFragment() - updateToolbar(listMainFileFragment?.getCurrentFile()) + updateToolbar(mainFileListFragment?.getCurrentFile()) } else { - val currentDirDisplayed = listMainFileFragment?.getCurrentFile() + val currentDirDisplayed = mainFileListFragment?.getCurrentFile() // If current file is null (we are in the spaces list, for example), close the app if (currentDirDisplayed == null) { finish() @@ -663,7 +671,7 @@ class FileDisplayActivity : FileActivity(), // If current file is root folder else if (currentDirDisplayed.parentId == FileDataStorageManager.ROOT_PARENT_ID.toLong()) { // If current space is a project space (not personal, not shares), navigate back to the spaces list - if (listMainFileFragment?.getCurrentSpace()?.isProject == true) { + if (mainFileListFragment?.getCurrentSpace()?.isProject == true) { navigateTo(FileListOption.SPACES_LIST) } // If current space is not a project space (personal or shares) or it is null ("Files" in oC10), close the app @@ -672,7 +680,7 @@ class FileDisplayActivity : FileActivity(), return } } else { - listMainFileFragment?.onBrowseUp() + mainFileListFragment?.onBrowseUp() } } } @@ -698,13 +706,14 @@ class FileDisplayActivity : FileActivity(), Timber.v("onResume() start") super.onResume() - if (listMainFileFragment?.getCurrentSpace()?.isProject == true) { + if (mainFileListFragment?.getCurrentSpace()?.isProject == true) { setCheckedItemAtBottomBar(getMenuItemForFileListOption(FileListOption.SPACES_LIST)) + updateToolbar(null, mainFileListFragment?.getCurrentSpace()) } else { setCheckedItemAtBottomBar(getMenuItemForFileListOption(fileListOption)) } - listMainFileFragment?.updateFileListOption(fileListOption, file) + mainFileListFragment?.updateFileListOption(fileListOption, file) // refresh list of files refreshListOfFilesFragment() @@ -786,7 +795,7 @@ class FileDisplayActivity : FileActivity(), } if (synchFolderRemotePath != null && currentDir.remotePath == synchFolderRemotePath) { - listMainFileFragment?.navigateToFolder(currentDir) + mainFileListFragment?.navigateToFolder(currentDir) } file = currentFile } @@ -795,7 +804,7 @@ class FileDisplayActivity : FileActivity(), FileSyncAdapter.EVENT_FULL_SYNC_END != event } - listMainFileFragment?.setProgressBarAsIndeterminate(syncInProgress) + mainFileListFragment?.setProgressBarAsIndeterminate(syncInProgress) Timber.d("Setting progress visibility to $syncInProgress") } @@ -816,7 +825,7 @@ class FileDisplayActivity : FileActivity(), } fun browseToRoot() { - val listOfFiles = listMainFileFragment + val listOfFiles = mainFileListFragment if (listOfFiles != null) { // should never be null, indeed val root = storageManager.getFileByPath(OCFile.ROOT_PATH) listOfFiles.navigateToFolder(root!!) @@ -866,7 +875,7 @@ class FileDisplayActivity : FileActivity(), FileListOption.SPACES_LIST -> getString(R.string.drawer_item_spaces) } setupRootToolbar(title, isSearchEnabled = fileListOption != FileListOption.SPACES_LIST) - listMainFileFragment?.setSearchListener(findViewById(R.id.root_toolbar_search_view)) + mainFileListFragment?.setSearchListener(findViewById(R.id.root_toolbar_search_view)) } else if (space?.isProject == true && chosenFile.remotePath == OCFile.ROOT_PATH) { updateStandardToolbar(title = space.name, displayHomeAsUpEnabled = true, homeButtonEnabled = true) } else { @@ -1353,10 +1362,10 @@ class FileDisplayActivity : FileActivity(), file = null initAndShowListOfSpaces() updateToolbar(null) - } else if (listMainFileFragment != null) { + } else if (mainFileListFragment != null) { fileListOption = newFileListOption file = storageManager.getFileByPath(OCFile.ROOT_PATH) - listMainFileFragment?.updateFileListOption(newFileListOption, file) + mainFileListFragment?.updateFileListOption(newFileListOption, file) updateToolbar(null) } else if (spacesListFragment != null) { fileListOption = newFileListOption diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FolderPickerActivity.java b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FolderPickerActivity.java deleted file mode 100644 index 8bf51fde775..00000000000 --- a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FolderPickerActivity.java +++ /dev/null @@ -1,324 +0,0 @@ -/** - * ownCloud Android client application - * - * @author Shashvat Kedia - * @author David González Verdugo - * @author Abel García de Prada - * Copyright (C) 2020 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, - * as published by the Free Software Foundation. - *

- * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - *

- * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.owncloud.android.ui.activity; - -import android.accounts.Account; -import android.content.Intent; -import android.os.Bundle; -import android.os.Parcelable; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.LinearLayout; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentTransaction; -import com.owncloud.android.R; -import com.owncloud.android.datamodel.FileDataStorageManager; -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.presentation.files.filelist.MainFileListFragment; -import com.owncloud.android.ui.fragment.FileFragment; -import com.owncloud.android.utils.PreferenceUtils; -import timber.log.Timber; - -import java.util.ArrayList; - -public class FolderPickerActivity extends FileActivity implements FileFragment.ContainerActivity, - OnClickListener, MainFileListFragment.FileActions { - - public static final String EXTRA_FOLDER = FolderPickerActivity.class.getCanonicalName() - + ".EXTRA_FOLDER"; - public static final String EXTRA_FILES = FolderPickerActivity.class.getCanonicalName() - + ".EXTRA_FILES"; - - private static final String TAG_LIST_OF_FOLDERS = "LIST_OF_FOLDERS"; - - public static final String EXTRA_PICKER_OPTION = "EXTRA_PICKER_OPTION"; - - protected Button mCancelBtn; - protected Button mChooseBtn; - - @Override - protected void onCreate(Bundle savedInstanceState) { - Timber.d("onCreate() start"); - - super.onCreate(savedInstanceState); - - setContentView(R.layout.files_folder_picker); // beware - inflated in other activities too - - // Allow or disallow touches with other visible windows - LinearLayout filesFolderPickerLayout = findViewById(R.id.filesFolderPickerLayout); - filesFolderPickerLayout.setFilterTouchesWhenObscured( - PreferenceUtils.shouldDisallowTouchesWithOtherVisibleWindows(this) - ); - - if (savedInstanceState == null) { - initAndShowListOfFilesFragment(); - } - - // sets callback listeners for UI elements - initPickerListeners(); - - // Action bar setup - setupStandardToolbar(null, false, false, true); - - // Set action button text - setActionButtonText(); - - Timber.d("onCreate() end"); - } - - /** - * Called when the ownCloud {@link Account} associated to the Activity was just updated. - */ - @Override - protected void onAccountSet(boolean stateWasRecovered) { - super.onAccountSet(stateWasRecovered); - if (getAccount() != null) { - - updateFileFromDB(); - - OCFile folder = getFile(); - if (folder == null || !folder.isFolder()) { - // fall back to root folder - setFile(getStorageManager().getFileByPath(OCFile.ROOT_PATH, null)); - folder = getFile(); - } - - if (!stateWasRecovered) { - MainFileListFragment listOfFolders = getListOfFilesFragment(); - listOfFolders.navigateToFolder(folder); - } - - updateNavigationElementsInActionBar(); - } - } - - private void initAndShowListOfFilesFragment() { - OCFile safeInitialFolder; - if (getFile() == null) { - FileDataStorageManager fileDataStorageManager = new FileDataStorageManager(this, getAccount(), getContentResolver()); - safeInitialFolder = fileDataStorageManager.getFileByPath(OCFile.ROOT_PATH, null); - } else { - safeInitialFolder = getFile(); - } - - MainFileListFragment mainListOfFiles = MainFileListFragment.newInstance(safeInitialFolder, true, FileListOption.ALL_FILES); - mainListOfFiles.setFileActions(this); - FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); - transaction.add(R.id.fragment_container, mainListOfFiles, TAG_LIST_OF_FOLDERS); - transaction.commit(); - } - - private void setActionButtonText() { - PickerMode actionButton = (PickerMode) getIntent().getSerializableExtra(EXTRA_PICKER_OPTION); - Button chooseButton = findViewById(R.id.folder_picker_btn_choose); - chooseButton.setText(getString(actionButton.getButtonString())); - } - - protected MainFileListFragment getListOfFilesFragment() { - Fragment listOfFiles = getSupportFragmentManager().findFragmentByTag(FolderPickerActivity.TAG_LIST_OF_FOLDERS); - if (listOfFiles != null) { - return (MainFileListFragment) listOfFiles; - } - Timber.e("Access to unexisting list of files fragment!!"); - return null; - } - - @Override - public void onSavedCertificate() { - - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.main_menu, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - boolean retval = true; - switch (item.getItemId()) { - case android.R.id.home: { - OCFile currentDir = getCurrentFolder(); - if (currentDir != null && currentDir.getParentId() != 0) { - onBackPressed(); - } - break; - } - default: - retval = super.onOptionsItemSelected(item); - } - return retval; - } - - protected OCFile getCurrentFolder() { - MainFileListFragment listOfFiles = getListOfFilesFragment(); - if (listOfFiles != null) { // should never be null, indeed - return listOfFiles.getCurrentFile(); - } - return null; - } - - @Override - public void onBackPressed() { - MainFileListFragment listOfFiles = getListOfFilesFragment(); - if (listOfFiles != null) { // should never be null, indeed - OCFile fileBeforeBrowsingUp = listOfFiles.getCurrentFile(); - if (fileBeforeBrowsingUp.getParentId() != null && - fileBeforeBrowsingUp.getParentId() == OCFile.ROOT_PARENT_ID - ) { - // If we are already at root, let's finish the picker. No sense to keep browsing up. - finish(); - return; - } - listOfFiles.onBrowseUp(); - setFile(listOfFiles.getCurrentFile()); - updateNavigationElementsInActionBar(); - } - } - - protected void updateNavigationElementsInActionBar() { - OCFile currentDir; - - try { - currentDir = getCurrentFolder(); - } catch (NullPointerException e) { - currentDir = getFile(); - } - - boolean atRoot = (currentDir == null || currentDir.getParentId() == 0); - updateStandardToolbar( - atRoot ? getString(R.string.default_display_name_for_root_folder) : currentDir.getFileName(), - !atRoot, - !atRoot - ); - } - - /** - * Set per-view controllers - */ - private void initPickerListeners() { - mCancelBtn = findViewById(R.id.folder_picker_btn_cancel); - mCancelBtn.setOnClickListener(this); - mChooseBtn = findViewById(R.id.folder_picker_btn_choose); - mChooseBtn.setOnClickListener(this); - } - - @Override - public void onClick(View v) { - if (v == mCancelBtn) { - finish(); - } else if (v == mChooseBtn) { - Intent i = getIntent(); - ArrayList targetFiles = i.getParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES); - - Intent data = new Intent(); - data.putExtra(EXTRA_FOLDER, getCurrentFolder()); - data.putParcelableArrayListExtra(EXTRA_FILES, targetFiles); - setResult(RESULT_OK, data); - - finish(); - } - } - - @Override - public void onCurrentFolderUpdated(@NonNull OCFile newCurrentFolder, @Nullable OCSpace currentSpace) { - updateNavigationElementsInActionBar(); - setFile(newCurrentFolder); - } - - @Override - public void initDownloadForSending(@NonNull OCFile file) { - - } - - @Override - public void cancelFileTransference(@NonNull ArrayList files) { - - } - - @Override - public void setBottomBarVisibility(boolean isVisible) { - - } - - @Override - public void onFileClicked(@NonNull OCFile file) { - // Nothing to do. Clicking on files is not allowed. - } - - @Override - public void onShareFileClicked(@NonNull OCFile file) { - // Nothing to do. Clicking on files is not allowed. - } - - @Override - public void syncFile(@NonNull OCFile file) { - // Nothing to do. Clicking on files is not allowed. - } - - @Override - public void openFile(@NonNull OCFile file) { - // Nothing to do. Clicking on files is not allowed. - } - - @Override - public void sendDownloadedFile(@NonNull OCFile file) { - // Nothing to do. Clicking on files is not allowed. - - } - - /** - * Nothing to do. Details can't be opened from {@link FolderPickerActivity} - * - * @param file {@link OCFile} whose details will be shown - */ - @Override - public void showDetails(OCFile file) { - - } - - public enum PickerMode { - MOVE, COPY, CAMERA_FOLDER; - - public Integer getButtonString() { - switch (this) { - case MOVE: - return R.string.folder_picker_move_here_button_text; - case COPY: - return R.string.folder_picker_copy_here_button_text; - default: - return R.string.folder_picker_choose_button_text; - } - } - } -} diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FolderPickerActivity.kt b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FolderPickerActivity.kt new file mode 100644 index 00000000000..130f9cd0120 --- /dev/null +++ b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FolderPickerActivity.kt @@ -0,0 +1,325 @@ +/** + * ownCloud Android client application + * + * @author Shashvat Kedia + * @author David González Verdugo + * @author Abel García de Prada + * @author Juan Carlos Garrote Gascón + * + * 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, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.ui.activity + +import android.content.Intent +import android.os.Bundle +import android.view.Menu +import android.view.MenuItem +import android.widget.Button +import android.widget.LinearLayout +import androidx.annotation.StringRes +import com.owncloud.android.R +import com.owncloud.android.datamodel.FileDataStorageManager +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.presentation.files.filelist.MainFileListFragment +import com.owncloud.android.presentation.spaces.SpacesListFragment +import com.owncloud.android.ui.fragment.FileFragment +import com.owncloud.android.utils.PreferenceUtils +import timber.log.Timber + +open class FolderPickerActivity : FileActivity(), + FileFragment.ContainerActivity, + MainFileListFragment.FileActions { + + protected val mainFileListFragment: MainFileListFragment? + get() = supportFragmentManager.findFragmentByTag(TAG_LIST_OF_FOLDERS) as MainFileListFragment? + + private lateinit var pickerMode: PickerMode + + override fun onCreate(savedInstanceState: Bundle?) { + Timber.d("onCreate() start") + + super.onCreate(savedInstanceState) + + setContentView(R.layout.files_folder_picker) // Beware - inflated in other activities too + + // Allow or disallow touches with other visible windows + val filesFolderPickerLayout = findViewById(R.id.filesFolderPickerLayout) + filesFolderPickerLayout.filterTouchesWhenObscured = PreferenceUtils.shouldDisallowTouchesWithOtherVisibleWindows(this) + + pickerMode = intent.getSerializableExtra(EXTRA_PICKER_MODE) as PickerMode + + if (savedInstanceState == null) { + when (pickerMode) { + PickerMode.MOVE -> { + // Show the space where the files come from + val targetFiles = intent.getParcelableArrayListExtra(EXTRA_FILES) + val spaceIdOfFiles = targetFiles?.get(0)?.spaceId + initAndShowListOfFilesFragment(spaceId = spaceIdOfFiles) + } + PickerMode.COPY -> { + // Show the list of spaces + initAndShowListOfSpaces() + } + PickerMode.CAMERA_FOLDER -> { + // Show the personal space + initAndShowListOfFilesFragment(spaceId = null) + } + } + } + + // Set callback listeners for UI elements + initPickerListeners() + + // Action bar setup + setupStandardToolbar( + title = null, + displayHomeAsUpEnabled = false, + homeButtonEnabled = false, + displayShowTitleEnabled = true, + ) + + // Set action button text + setActionButtonText() + + supportFragmentManager.setFragmentResultListener(SpacesListFragment.REQUEST_KEY_CLICK_SPACE, this) { _, bundle -> + val rootSpaceFolder = bundle.getParcelable(SpacesListFragment.BUNDLE_KEY_CLICK_SPACE) + file = rootSpaceFolder + initAndShowListOfFilesFragment() + } + + Timber.d("onCreate() end") + } + + override fun onResume() { + super.onResume() + updateToolbar(null, mainFileListFragment?.getCurrentSpace()) + } + + /** + * Called when the ownCloud {@link Account} associated to the Activity was just updated. + */ + override fun onAccountSet(stateWasRecovered: Boolean) { + super.onAccountSet(stateWasRecovered) + + if (account != null) { + updateFileFromDB() + + var folder = file + if (folder == null || !folder.isFolder) { + // Fall back to root folder + file = storageManager.getFileByPath(OCFile.ROOT_PATH) + folder = file + } + + if (!stateWasRecovered) { + mainFileListFragment?.navigateToFolder(folder) + } + + updateNavigationElementsInActionBar() + } + } + + override fun onCreateOptionsMenu(menu: Menu?): Boolean { + menuInflater.inflate(R.menu.main_menu, menu) + return true + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + when (item.itemId) { + android.R.id.home -> { + onBackPressed() + } + } + + return super.onOptionsItemSelected(item) + } + + override fun onBackPressed() { + val currentDirDisplayed = mainFileListFragment?.getCurrentFile() + // If current file is null (we are in the spaces list, for example), close the activity + if (currentDirDisplayed == null) { + finish() + return + } + // If current file is root folder + else if (currentDirDisplayed.parentId == OCFile.ROOT_PARENT_ID) { + // If we are not in COPY mode, close the activity + if (pickerMode != PickerMode.COPY) { + finish() + return + } + // If we are in COPY mode and inside a space, navigate back to the spaces list + if (mainFileListFragment?.getCurrentSpace()?.isProject == true || mainFileListFragment?.getCurrentSpace()?.isPersonal == true) { + file = null + initAndShowListOfSpaces() + updateToolbar(null) + } + } else { + mainFileListFragment?.onBrowseUp() + } + } + + override fun onCurrentFolderUpdated(newCurrentFolder: OCFile, currentSpace: OCSpace?) { + updateToolbar(newCurrentFolder, currentSpace) + file = newCurrentFolder + } + + override fun initDownloadForSending(file: OCFile) { + // Nothing to do. Downloading files is not allowed. + } + + override fun cancelFileTransference(files: ArrayList) { + // Nothing to do. Transferring files is not allowed. + } + + override fun setBottomBarVisibility(isVisible: Boolean) { + // Nothing to do. No changes will be done in the bottom bar visibility. + } + + override fun onFileClicked(file: OCFile) { + // Nothing to do. Clicking on files is not allowed. + } + + override fun onShareFileClicked(file: OCFile) { + // Nothing to do. Clicking on files is not allowed. + } + + override fun syncFile(file: OCFile) { + // Nothing to do. Clicking on files is not allowed. + } + + override fun openFile(file: OCFile) { + // Nothing to do. Clicking on files is not allowed. + } + + override fun sendDownloadedFile(file: OCFile) { + // Nothing to do. Clicking on files is not allowed. + } + + override fun showDetails(file: OCFile) { + // Nothing to do. Details can't be opened here. + } + + private fun initAndShowListOfFilesFragment(spaceId: String? = null) { + val safeInitialFolder = if (file == null) { + val fileDataStorageManager = FileDataStorageManager(this, account, contentResolver) + fileDataStorageManager.getFileByPath(OCFile.ROOT_PATH, spaceId) + } else { + file + } + + file = safeInitialFolder + + safeInitialFolder?.let { + val mainListOfFiles = MainFileListFragment.newInstance(it, true, FileListOption.ALL_FILES) + mainListOfFiles.fileActions = this + val transaction = supportFragmentManager.beginTransaction() + transaction.replace(R.id.fragment_container, mainListOfFiles, TAG_LIST_OF_FOLDERS) + transaction.commit() + } + } + + private fun initAndShowListOfSpaces() { + val listOfSpaces = SpacesListFragment(showPersonalSpace = true) + val transaction = supportFragmentManager.beginTransaction() + transaction.replace(R.id.fragment_container, listOfSpaces) + transaction.commit() + } + + /** + * Set per-view controllers + */ + private fun initPickerListeners() { + findViewById