From fd7e0260e4050a3971f723557c5d9bb0962a9927 Mon Sep 17 00:00:00 2001 From: Juan Carlos Garrote Date: Wed, 11 Dec 2024 13:42:08 +0100 Subject: [PATCH] refactor: refactor methods with more than 100 lines --- .../files/filelist/FileListAdapter.kt | 137 +++--- .../files/filelist/MainFileListFragment.kt | 425 ++++++++++-------- .../security/SettingsSecurityFragment.kt | 9 +- .../sharees/UsersAndGroupsSearchProvider.kt | 29 +- .../transfers/TransfersAdapter.kt | 266 +++++------ .../android/providers/FileContentProvider.kt | 1 + .../android/ui/activity/DrawerActivity.kt | 202 ++++----- 7 files changed, 567 insertions(+), 502 deletions(-) diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/FileListAdapter.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/FileListAdapter.kt index cba5cdf369e..d84a1a6a467 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/FileListAdapter.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/files/filelist/FileListAdapter.kt @@ -207,71 +207,7 @@ class FileListAdapter( holder.itemView.findViewById(R.id.shared_via_users_icon).isVisible = file.sharedWithSharee == true || file.isSharedWithMe - when (viewType) { - ViewType.LIST_ITEM.ordinal -> { - val view = holder as ListViewHolder - view.binding.let { - it.fileListConstraintLayout.filterTouchesWhenObscured = PreferenceUtils.shouldDisallowTouchesWithOtherVisibleWindows(context) - it.Filename.text = file.fileName - it.fileListSize.text = DisplayUtils.bytesToHumanReadable(file.length, context, true) - it.fileListLastMod.text = DisplayUtils.getRelativeTimestamp(context, file.modificationTimestamp) - it.threeDotMenu.isVisible = getCheckedItems().isEmpty() - it.threeDotMenu.contentDescription = context.getString(R.string.content_description_file_operations, file.fileName) - if (fileListOption.isAvailableOffline() || (fileListOption.isSharedByLink() && fileWithSyncInfo.space == null)) { - it.spacePathLine.path.apply { - text = file.getParentRemotePath() - isVisible = true - } - fileWithSyncInfo.space?.let { space -> - it.spacePathLine.spaceIcon.isVisible = true - it.spacePathLine.spaceName.isVisible = true - if (space.isPersonal) { - it.spacePathLine.spaceIcon.setImageResource(R.drawable.ic_folder) - it.spacePathLine.spaceName.setText(R.string.bottom_nav_personal) - } else { - it.spacePathLine.spaceName.text = space.name - } - } - } else { - it.spacePathLine.path.isVisible = false - it.spacePathLine.spaceIcon.isVisible = false - it.spacePathLine.spaceName.isVisible = false - } - it.threeDotMenu.setOnClickListener { - listener.onThreeDotButtonClick(fileWithSyncInfo = fileWithSyncInfo) - } - } - } - - ViewType.GRID_ITEM.ordinal -> { - // Filename - val view = holder as GridViewHolder - view.binding.Filename.text = file.fileName - } - - ViewType.GRID_IMAGE.ordinal -> { - val view = holder as GridImageViewHolder - val layoutParams = fileIcon.layoutParams as ViewGroup.MarginLayoutParams - - if (thumbnail == null) { - view.binding.Filename.text = file.fileName - // Reset layout params values default - manageGridLayoutParams( - layoutParams = layoutParams, - marginVertical = 0, - height = context.resources.getDimensionPixelSize(R.dimen.item_file_grid_height), - width = context.resources.getDimensionPixelSize(R.dimen.item_file_grid_width), - ) - } else { - manageGridLayoutParams( - layoutParams = layoutParams, - marginVertical = context.resources.getDimensionPixelSize(R.dimen.item_file_image_grid_margin), - height = ViewGroup.LayoutParams.MATCH_PARENT, - width = ViewGroup.LayoutParams.MATCH_PARENT, - ) - } - } - } + setSpecificViewHolder(viewType, holder, fileWithSyncInfo, thumbnail) setIconPinAccordingToFilesLocalState(holder.itemView.findViewById(R.id.localFileIndicator), fileWithSyncInfo) @@ -342,6 +278,77 @@ class FileListAdapter( } } + private fun setSpecificViewHolder(viewType: Int, holder: RecyclerView.ViewHolder, fileWithSyncInfo: OCFileWithSyncInfo, thumbnail: Bitmap?) { + val file = fileWithSyncInfo.file + + when (viewType) { + ViewType.LIST_ITEM.ordinal -> { + val view = holder as ListViewHolder + view.binding.let { + it.fileListConstraintLayout.filterTouchesWhenObscured = PreferenceUtils.shouldDisallowTouchesWithOtherVisibleWindows(context) + it.Filename.text = file.fileName + it.fileListSize.text = DisplayUtils.bytesToHumanReadable(file.length, context, true) + it.fileListLastMod.text = DisplayUtils.getRelativeTimestamp(context, file.modificationTimestamp) + it.threeDotMenu.isVisible = getCheckedItems().isEmpty() + it.threeDotMenu.contentDescription = context.getString(R.string.content_description_file_operations, file.fileName) + if (fileListOption.isAvailableOffline() || (fileListOption.isSharedByLink() && fileWithSyncInfo.space == null)) { + it.spacePathLine.path.apply { + text = file.getParentRemotePath() + isVisible = true + } + fileWithSyncInfo.space?.let { space -> + it.spacePathLine.spaceIcon.isVisible = true + it.spacePathLine.spaceName.isVisible = true + if (space.isPersonal) { + it.spacePathLine.spaceIcon.setImageResource(R.drawable.ic_folder) + it.spacePathLine.spaceName.setText(R.string.bottom_nav_personal) + } else { + it.spacePathLine.spaceName.text = space.name + } + } + } else { + it.spacePathLine.path.isVisible = false + it.spacePathLine.spaceIcon.isVisible = false + it.spacePathLine.spaceName.isVisible = false + } + it.threeDotMenu.setOnClickListener { + listener.onThreeDotButtonClick(fileWithSyncInfo = fileWithSyncInfo) + } + } + } + + ViewType.GRID_ITEM.ordinal -> { + // Filename + val view = holder as GridViewHolder + view.binding.Filename.text = file.fileName + } + + ViewType.GRID_IMAGE.ordinal -> { + val view = holder as GridImageViewHolder + val fileIcon = holder.itemView.findViewById(R.id.thumbnail) + val layoutParams = fileIcon.layoutParams as ViewGroup.MarginLayoutParams + + if (thumbnail == null) { + view.binding.Filename.text = file.fileName + // Reset layout params values default + manageGridLayoutParams( + layoutParams = layoutParams, + marginVertical = 0, + height = context.resources.getDimensionPixelSize(R.dimen.item_file_grid_height), + width = context.resources.getDimensionPixelSize(R.dimen.item_file_grid_width), + ) + } else { + manageGridLayoutParams( + layoutParams = layoutParams, + marginVertical = context.resources.getDimensionPixelSize(R.dimen.item_file_image_grid_margin), + height = ViewGroup.LayoutParams.MATCH_PARENT, + width = ViewGroup.LayoutParams.MATCH_PARENT, + ) + } + } + } + } + private fun manageGridLayoutParams(layoutParams: ViewGroup.MarginLayoutParams, marginVertical: Int, height: Int, width: Int) { val marginHorizontal = context.resources.getDimensionPixelSize(R.dimen.item_file_image_grid_margin) layoutParams.setMargins(marginHorizontal, marginVertical, marginHorizontal, marginVertical) 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 d62967464a5..5883200360b 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 @@ -314,6 +314,50 @@ class MainFileListFragment : Fragment(), private fun subscribeToViewModels() { /* MainFileListViewModel observables */ // Observe the current folder displayed + observeCurrentFolderDisplayed() + + // Observe the current space to update the toolbar + // We can't rely exclusively on the [currentFolderDisplayed] because sometimes retrieving the space takes more time + observeSpace() + + // Observe the list of app registries that allow creating new files + observeAppRegistryToCreateFiles() + + // Observe the open in web action to trigger browser + observeOpenInWebFlow() + + // Observe the menu filtered options in multiselection + observeMenuOptions() + + // Observe the app registry in multiselection + observeAppRegistryMimeType() + + // Observe the menu filtered options for a single file + observeMenuOptionsSingleFile() + + // Observe the app registry for a single file + observeAppRegistryMimeTypeSingleFile() + + // Observe the file list UI state + observeFileListUiState() + + /* FileOperationsViewModel observables */ + // Observe the refresh folder operation + observeRefreshFolder() + + // Observe the create file with app provider operation + observeCreateFileWithAppProvider() + + // Observe the check if file is local and not available offline operation + observeCheckIfFileIsLocalAndNotAvailableOffline() + + /* TransfersViewModel observables */ + // Observe transfers + observeTransfers() + + } + + private fun observeCurrentFolderDisplayed() { collectLatestLifecycleFlow(mainFileListViewModel.currentFolderDisplayed) { currentFolderDisplayed: OCFile -> fileActions?.onCurrentFolderUpdated(currentFolderDisplayed, mainFileListViewModel.getSpace()) val fileListOption = mainFileListViewModel.fileListOption.value @@ -336,22 +380,23 @@ class MainFileListFragment : Fragment(), numberOfUploadsRefreshed = 0 hideRefreshFab() } + } - // Observe the current space to update the toolbar - // We can't rely exclusively on the [currentFolderDisplayed] because sometimes retrieving the space takes more time + private fun observeSpace() { collectLatestLifecycleFlow(mainFileListViewModel.space) { currentSpace: OCSpace? -> currentSpace?.let { fileActions?.onCurrentFolderUpdated(mainFileListViewModel.getFile(), currentSpace) } } - - // Observe the list of app registries that allow creating new files + } + private fun observeAppRegistryToCreateFiles() { collectLatestLifecycleFlow(mainFileListViewModel.appRegistryToCreateFiles) { listAppRegistry -> binding.fabNewfile.isVisible = listAppRegistry.isNotEmpty() registerFabNewFileListener(listAppRegistry) } + } - // Observe the open in web action to trigger browser + private fun observeOpenInWebFlow() { collectLatestLifecycleFlow(mainFileListViewModel.openInWebFlow) { if (it != null) { val uiResult = it.peekContent() @@ -382,8 +427,9 @@ class MainFileListFragment : Fragment(), currentDefaultApplication = null } } + } - // Observe the menu filtered options in multiselection + private fun observeMenuOptions() { collectLatestLifecycleFlow(mainFileListViewModel.menuOptions) { menuOptions -> val hasWritePermission = if (checkedFiles.size == 1) { checkedFiles.first().hasWritePermission @@ -392,16 +438,18 @@ class MainFileListFragment : Fragment(), } menu?.filterMenuOptions(menuOptions, hasWritePermission) } + } - // Observe the app registry in multiselection + private fun observeAppRegistryMimeType() { collectLatestLifecycleFlow(mainFileListViewModel.appRegistryMimeType) { appRegistryMimeType -> val appProviders = appRegistryMimeType?.appProviders menu?.let { openInWebProviders = addOpenInWebMenuOptions(it, openInWebProviders, appProviders) } } + } - // Observe the menu filtered options for a single file + private fun observeMenuOptionsSingleFile() { collectLatestLifecycleFlow(mainFileListViewModel.menuOptionsSingleFile) { menuOptions -> fileSingleFile?.let { file -> val fileOptionsBottomSheetSingleFile = layoutInflater.inflate(R.layout.file_options_bottom_sheet_fragment, null) @@ -462,119 +510,124 @@ class MainFileListFragment : Fragment(), fileOptionsBottomSheetSingleFileLayout = fileOptionsBottomSheetSingleFile.findViewById(R.id.file_options_bottom_sheet_layout) menuOptions.forEach { menuOption -> - val fileOptionItemView = BottomSheetFragmentItemView(requireContext()) - fileOptionItemView.apply { - title = if (menuOption.toResId() == R.id.action_open_file_with && !file.hasWritePermission) { - getString(R.string.actionbar_open_with_read_only) - } else { - getString(menuOption.toStringResId()) + setMenuOption(menuOption, file, dialog) + } + // Disable drag gesture + fileOptionsBottomSheetSingleFileBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { + override fun onStateChanged(bottomSheet: View, newState: Int) { + if (newState == BottomSheetBehavior.STATE_DRAGGING) { + fileOptionsBottomSheetSingleFileBehavior.state = BottomSheetBehavior.STATE_EXPANDED } - itemIcon = ResourcesCompat.getDrawable(resources, menuOption.toDrawableResId(), null) - setOnClickListener { - when (menuOption) { - FileMenuOption.SELECT_ALL -> { - // Not applicable here - } + } - FileMenuOption.SELECT_INVERSE -> { - // Not applicable here - } + override fun onSlide(bottomSheet: View, slideOffset: Float) {} + }) + dialog.setOnShowListener { fileOptionsBottomSheetSingleFileBehavior.peekHeight = fileOptionsBottomSheetSingleFile.measuredHeight } + dialog.show() + mainFileListViewModel.getAppRegistryForMimeType(file.mimeType, isMultiselection = false) + } + } + } - FileMenuOption.DOWNLOAD, FileMenuOption.SYNC -> { - syncFiles(listOf(file)) - } + private fun setMenuOption(menuOption: FileMenuOption, file: OCFile, dialog: BottomSheetDialog) { + val fileOptionItemView = BottomSheetFragmentItemView(requireContext()) + fileOptionItemView.apply { + title = if (menuOption.toResId() == R.id.action_open_file_with && !file.hasWritePermission) { + getString(R.string.actionbar_open_with_read_only) + } else { + getString(menuOption.toStringResId()) + } + itemIcon = ResourcesCompat.getDrawable(resources, menuOption.toDrawableResId(), null) + setOnClickListener { + when (menuOption) { + FileMenuOption.SELECT_ALL -> { + // Not applicable here + } - FileMenuOption.RENAME -> { - val dialogRename = RenameFileDialogFragment.newInstance(file) - dialogRename.show(requireActivity().supportFragmentManager, FRAGMENT_TAG_RENAME_FILE) - } + FileMenuOption.SELECT_INVERSE -> { + // Not applicable here + } - FileMenuOption.MOVE -> { - val action = Intent(activity, FolderPickerActivity::class.java) - action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, arrayListOf(file)) - action.putExtra(FolderPickerActivity.EXTRA_PICKER_MODE, FolderPickerActivity.PickerMode.MOVE) - requireActivity().startActivityForResult(action, FileDisplayActivity.REQUEST_CODE__MOVE_FILES) - } + FileMenuOption.DOWNLOAD, FileMenuOption.SYNC -> { + syncFiles(listOf(file)) + } - FileMenuOption.COPY -> { - val action = Intent(activity, FolderPickerActivity::class.java) - action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, arrayListOf(file)) - action.putExtra(FolderPickerActivity.EXTRA_PICKER_MODE, FolderPickerActivity.PickerMode.COPY) - requireActivity().startActivityForResult(action, FileDisplayActivity.REQUEST_CODE__COPY_FILES) - } + FileMenuOption.RENAME -> { + val dialogRename = RenameFileDialogFragment.newInstance(file) + dialogRename.show(requireActivity().supportFragmentManager, FRAGMENT_TAG_RENAME_FILE) + } - FileMenuOption.REMOVE -> { - filesToRemove = listOf(file) - fileOperationsViewModel.showRemoveDialog(filesToRemove) - } + FileMenuOption.MOVE -> { + val action = Intent(activity, FolderPickerActivity::class.java) + action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, arrayListOf(file)) + action.putExtra(FolderPickerActivity.EXTRA_PICKER_MODE, FolderPickerActivity.PickerMode.MOVE) + requireActivity().startActivityForResult(action, FileDisplayActivity.REQUEST_CODE__MOVE_FILES) + } - FileMenuOption.OPEN_WITH -> { - fileActions?.openFile(file) - } + FileMenuOption.COPY -> { + val action = Intent(activity, FolderPickerActivity::class.java) + action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, arrayListOf(file)) + action.putExtra(FolderPickerActivity.EXTRA_PICKER_MODE, FolderPickerActivity.PickerMode.COPY) + requireActivity().startActivityForResult(action, FileDisplayActivity.REQUEST_CODE__COPY_FILES) + } - FileMenuOption.CANCEL_SYNC -> { - fileActions?.cancelFileTransference(arrayListOf(file)) - } + FileMenuOption.REMOVE -> { + filesToRemove = listOf(file) + fileOperationsViewModel.showRemoveDialog(filesToRemove) + } - FileMenuOption.SHARE -> { - fileActions?.onShareFileClicked(file) - } + FileMenuOption.OPEN_WITH -> { + fileActions?.openFile(file) + } - FileMenuOption.DETAILS -> { - fileActions?.showDetails(file) - } + FileMenuOption.CANCEL_SYNC -> { + fileActions?.cancelFileTransference(arrayListOf(file)) + } - FileMenuOption.SEND -> { - if (!file.isAvailableLocally) { // Download the file - Timber.d("${file.remotePath} : File must be downloaded") - fileActions?.initDownloadForSending(file) - } else { - fileActions?.sendDownloadedFile(file) - } - } + FileMenuOption.SHARE -> { + fileActions?.onShareFileClicked(file) + } - FileMenuOption.SET_AV_OFFLINE -> { - fileOperationsViewModel.performOperation(FileOperation.SetFilesAsAvailableOffline(listOf(file))) - if (file.isFolder) { - fileOperationsViewModel.performOperation( - FileOperation.SynchronizeFolderOperation( - folderToSync = file, - accountName = file.owner, - isActionSetFolderAvailableOfflineOrSynchronize = true, - ) - ) - } else { - fileOperationsViewModel.performOperation(FileOperation.SynchronizeFileOperation(file, file.owner)) - } - } + FileMenuOption.DETAILS -> { + fileActions?.showDetails(file) + } - FileMenuOption.UNSET_AV_OFFLINE -> { - fileOperationsViewModel.performOperation(FileOperation.UnsetFilesAsAvailableOffline(listOf(file))) - } - } - dialog.hide() - dialog.dismiss() + FileMenuOption.SEND -> { + if (!file.isAvailableLocally) { // Download the file + Timber.d("${file.remotePath} : File must be downloaded") + fileActions?.initDownloadForSending(file) + } else { + fileActions?.sendDownloadedFile(file) } } - fileOptionsBottomSheetSingleFileLayout!!.addView(fileOptionItemView) - } - // Disable drag gesture - fileOptionsBottomSheetSingleFileBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { - override fun onStateChanged(bottomSheet: View, newState: Int) { - if (newState == BottomSheetBehavior.STATE_DRAGGING) { - fileOptionsBottomSheetSingleFileBehavior.state = BottomSheetBehavior.STATE_EXPANDED + + FileMenuOption.SET_AV_OFFLINE -> { + fileOperationsViewModel.performOperation(FileOperation.SetFilesAsAvailableOffline(listOf(file))) + if (file.isFolder) { + fileOperationsViewModel.performOperation( + FileOperation.SynchronizeFolderOperation( + folderToSync = file, + accountName = file.owner, + isActionSetFolderAvailableOfflineOrSynchronize = true, + ) + ) + } else { + fileOperationsViewModel.performOperation(FileOperation.SynchronizeFileOperation(file, file.owner)) } } - override fun onSlide(bottomSheet: View, slideOffset: Float) {} - }) - dialog.setOnShowListener { fileOptionsBottomSheetSingleFileBehavior.peekHeight = fileOptionsBottomSheetSingleFile.measuredHeight } - dialog.show() - mainFileListViewModel.getAppRegistryForMimeType(file.mimeType, isMultiselection = false) + FileMenuOption.UNSET_AV_OFFLINE -> { + fileOperationsViewModel.performOperation(FileOperation.UnsetFilesAsAvailableOffline(listOf(file))) + } + } + dialog.hide() + dialog.dismiss() } } + fileOptionsBottomSheetSingleFileLayout!!.addView(fileOptionItemView) + } - // Observe the app registry for a single file + private fun observeAppRegistryMimeTypeSingleFile() { collectLatestLifecycleFlow(mainFileListViewModel.appRegistryMimeTypeSingleFile) { appRegistryMimeType -> fileSingleFile?.let { file -> val appProviders = appRegistryMimeType?.appProviders @@ -600,8 +653,19 @@ class MainFileListFragment : Fragment(), } fileSingleFile = null } + } - // Observe the file list UI state + private suspend fun getDrawableFromUrl(context: Context, url: String): Drawable? { + return withContext(Dispatchers.IO) { + Glide.with(context) + .load(url) + .fitCenter() + .submit() + .get() + } + } + + private fun observeFileListUiState() { collectLatestLifecycleFlow(mainFileListViewModel.fileListUiState) { fileListUiState -> if (fileListUiState !is MainFileListViewModel.FileListUiState.Success) return@collectLatestLifecycleFlow @@ -636,9 +700,9 @@ class MainFileListFragment : Fragment(), actionMode?.invalidate() } + } - /* FileOperationsViewModel observables */ - // Observe the refresh folder operation + private fun observeRefreshFolder() { fileOperationsViewModel.refreshFolderLiveData.observe(viewLifecycleOwner) { binding.syncProgressBar.isIndeterminate = it.peekContent().isLoading binding.swipeRefreshMainFileList.isRefreshing = it.peekContent().isLoading @@ -648,8 +712,9 @@ class MainFileListFragment : Fragment(), hideRefreshFab() } + } - // Observe the create file with app provider operation + private fun observeCreateFileWithAppProvider() { collectLatestLifecycleFlow(fileOperationsViewModel.createFileWithAppProviderFlow) { val uiResult = it?.peekContent() if (uiResult is UIResult.Error) { @@ -666,7 +731,9 @@ class MainFileListFragment : Fragment(), } } } + } + private fun observeCheckIfFileIsLocalAndNotAvailableOffline() { collectLatestLifecycleFlow(fileOperationsViewModel.checkIfFileIsLocalAndNotAvailableOfflineSharedFlow) { val fileActivity = (requireActivity() as FileActivity) when (it) { @@ -682,20 +749,6 @@ class MainFileListFragment : Fragment(), } } } - - /* TransfersViewModel observables */ - observeTransfers() - - } - - private suspend fun getDrawableFromUrl(context: Context, url: String): Drawable? { - return withContext(Dispatchers.IO) { - Glide.with(context) - .load(url) - .fitCenter() - .submit() - .get() - } } private fun observeTransfers() { @@ -1148,91 +1201,102 @@ class MainFileListFragment : Fragment(), */ @SuppressLint("UseRequireInsteadOfGet") private fun onFileActionChosen(menuId: Int?): Boolean { + var handled: Boolean val checkedFilesWithSyncInfo = fileListAdapter.getCheckedItems() as ArrayList if (checkedFilesWithSyncInfo.isEmpty()) { return false } else if (checkedFilesWithSyncInfo.size == 1) { - /// action only possible on a single file + /// Action possible on a single file val singleFile = checkedFilesWithSyncInfo.first().file + handled = onSingleFileActionChosen(menuId, singleFile) + } - openInWebProviders.forEach { (openInWebProviderName, menuItemId) -> - if (menuItemId == menuId) { - mainFileListViewModel.openInWeb(singleFile.remoteId!!, openInWebProviderName) - return true - } + /// Actions possible on a batch of files + val checkedFiles = checkedFilesWithSyncInfo.map { it.file } as ArrayList + handled = onCheckedFilesActionChosen(menuId, checkedFiles) + return handled + } + + private fun onSingleFileActionChosen(menuId: Int?, singleFile: OCFile): Boolean { + openInWebProviders.forEach { (openInWebProviderName, menuItemId) -> + if (menuItemId == menuId) { + mainFileListViewModel.openInWeb(singleFile.remoteId!!, openInWebProviderName) + return true } + } - when (menuId) { - R.id.action_share_file -> { - fileActions?.onShareFileClicked(singleFile) - fileListAdapter.clearSelection() - updateActionModeAfterTogglingSelected() - return true - } + when (menuId) { + R.id.action_share_file -> { + fileActions?.onShareFileClicked(singleFile) + fileListAdapter.clearSelection() + updateActionModeAfterTogglingSelected() + return true + } - R.id.action_open_file_with -> { - fileActions?.openFile(singleFile) - fileListAdapter.clearSelection() - updateActionModeAfterTogglingSelected() - return true - } + R.id.action_open_file_with -> { + fileActions?.openFile(singleFile) + fileListAdapter.clearSelection() + updateActionModeAfterTogglingSelected() + return true + } - R.id.action_rename_file -> { - val dialog = RenameFileDialogFragment.newInstance(singleFile) - dialog.show(requireActivity().supportFragmentManager, FRAGMENT_TAG_RENAME_FILE) - fileListAdapter.clearSelection() - updateActionModeAfterTogglingSelected() - return true - } + R.id.action_rename_file -> { + val dialog = RenameFileDialogFragment.newInstance(singleFile) + dialog.show(requireActivity().supportFragmentManager, FRAGMENT_TAG_RENAME_FILE) + fileListAdapter.clearSelection() + updateActionModeAfterTogglingSelected() + return true + } - R.id.action_see_details -> { - fileListAdapter.clearSelection() - updateActionModeAfterTogglingSelected() - fileActions?.showDetails(singleFile) - return true - } + R.id.action_see_details -> { + fileListAdapter.clearSelection() + updateActionModeAfterTogglingSelected() + fileActions?.showDetails(singleFile) + return true + } - R.id.action_sync_file -> { - syncFiles(listOf(singleFile)) - return true - } + R.id.action_sync_file -> { + syncFiles(listOf(singleFile)) + return true + } - R.id.action_send_file -> { - //Obtain the file - if (!singleFile.isAvailableLocally) { // Download the file - Timber.d("%s : File must be downloaded", singleFile.remotePath) - fileActions?.initDownloadForSending(singleFile) - } else { - fileActions?.sendDownloadedFile(singleFile) - } - return true + R.id.action_send_file -> { + //Obtain the file + if (!singleFile.isAvailableLocally) { // Download the file + Timber.d("%s : File must be downloaded", singleFile.remotePath) + fileActions?.initDownloadForSending(singleFile) + } else { + fileActions?.sendDownloadedFile(singleFile) } + return true + } - R.id.action_set_available_offline -> { - fileOperationsViewModel.performOperation(FileOperation.SetFilesAsAvailableOffline(listOf(singleFile))) - if (singleFile.isFolder) { - fileOperationsViewModel.performOperation( - FileOperation.SynchronizeFolderOperation( - folderToSync = singleFile, - accountName = singleFile.owner, - isActionSetFolderAvailableOfflineOrSynchronize = true, - ) + R.id.action_set_available_offline -> { + fileOperationsViewModel.performOperation(FileOperation.SetFilesAsAvailableOffline(listOf(singleFile))) + if (singleFile.isFolder) { + fileOperationsViewModel.performOperation( + FileOperation.SynchronizeFolderOperation( + folderToSync = singleFile, + accountName = singleFile.owner, + isActionSetFolderAvailableOfflineOrSynchronize = true, ) - } else { - fileOperationsViewModel.performOperation(FileOperation.SynchronizeFileOperation(singleFile, singleFile.owner)) - } - return true + ) + } else { + fileOperationsViewModel.performOperation(FileOperation.SynchronizeFileOperation(singleFile, singleFile.owner)) } + return true + } - R.id.action_unset_available_offline -> { - fileOperationsViewModel.performOperation(FileOperation.UnsetFilesAsAvailableOffline(listOf(singleFile))) - } + R.id.action_unset_available_offline -> { + fileOperationsViewModel.performOperation(FileOperation.UnsetFilesAsAvailableOffline(listOf(singleFile))) + return true } } + return false + } - /// Actions possible on a batch of files - val checkedFiles = checkedFilesWithSyncInfo.map { it.file } as ArrayList + private fun onCheckedFilesActionChosen(menuId: Int?, checkedFiles: ArrayList): Boolean { when (menuId) { R.id.file_action_select_all -> { fileListAdapter.selectAll() @@ -1304,7 +1368,6 @@ class MainFileListFragment : Fragment(), return true } } - return false } diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/security/SettingsSecurityFragment.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/security/SettingsSecurityFragment.kt index a883999ac51..6a84ed1e116 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/security/SettingsSecurityFragment.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/settings/security/SettingsSecurityFragment.kt @@ -107,7 +107,6 @@ class SettingsSecurityFragment : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.settings_security, rootKey) - screenSecurity = findPreference(SCREEN_SECURITY) prefPasscode = findPreference(PassCodeActivity.PREFERENCE_SET_PASSCODE) prefPattern = findPreference(PatternActivity.PREFERENCE_SET_PATTERN) @@ -173,9 +172,7 @@ class SettingsSecurityFragment : PreferenceFragmentCompat() { screenSecurity?.removePreferenceFromScreen(prefBiometric) } else { // Disable biometric lock if Passcode or Pattern locks are disabled - if (prefPasscode?.isChecked == false && prefPattern?.isChecked == false) { - disableBiometric() - } + if (prefPasscode?.isChecked == false && prefPattern?.isChecked == false) { disableBiometric() } prefBiometric?.setOnPreferenceChangeListener { _: Preference?, newValue: Any -> val incomingValue = newValue as Boolean @@ -191,9 +188,7 @@ class SettingsSecurityFragment : PreferenceFragmentCompat() { } // Lock application - if (prefPasscode?.isChecked == false && prefPattern?.isChecked == false) { - prefLockApplication?.isEnabled = false - } + if (prefPasscode?.isChecked == false && prefPattern?.isChecked == false) { prefLockApplication?.isEnabled = false } // Lock access from document provider prefLockAccessDocumentProvider?.setOnPreferenceChangeListener { _: Preference?, newValue: Any -> diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/sharees/UsersAndGroupsSearchProvider.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/sharees/UsersAndGroupsSearchProvider.kt index a5a3d9d3011..82b46a959b0 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/sharees/UsersAndGroupsSearchProvider.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/sharing/sharees/UsersAndGroupsSearchProvider.kt @@ -167,15 +167,9 @@ class UsersAndGroupsSearchProvider : ContentProvider() { var dataUri: Uri? = null var count = 0 - val userBaseUri = Uri.Builder().scheme(CONTENT).authority( - suggestAuthority!! + DATA_USER_SUFFIX - ).build() - val groupBaseUri = Uri.Builder().scheme(CONTENT).authority( - suggestAuthority!! + DATA_GROUP_SUFFIX - ).build() - val remoteBaseUri = Uri.Builder().scheme(CONTENT).authority( - suggestAuthority!! + DATA_REMOTE_SUFFIX - ).build() + val userBaseUri = Uri.Builder().scheme(CONTENT).authority(suggestAuthority!! + DATA_USER_SUFFIX).build() + val groupBaseUri = Uri.Builder().scheme(CONTENT).authority(suggestAuthority!! + DATA_GROUP_SUFFIX).build() + val remoteBaseUri = Uri.Builder().scheme(CONTENT).authority(suggestAuthority!! + DATA_REMOTE_SUFFIX).build() val federatedShareAllowed = capabilities?.filesSharingFederationOutgoing?.isTrue ?: false @@ -184,9 +178,7 @@ class UsersAndGroupsSearchProvider : ContentProvider() { val fullName = AccountManager.get(context).getUserData(account, KEY_DISPLAY_NAME) while (namesIt.hasNext()) { item = namesIt.next() - if (item.label == userName || item.label == fullName && item.shareType == ShareType.USER) { - continue - } + if (item.label == userName || item.label == fullName && item.shareType == ShareType.USER) { continue } var userName = item.label val type = item.shareType val shareWith = item.shareWith @@ -212,15 +204,10 @@ class UsersAndGroupsSearchProvider : ContentProvider() { ShareType.FEDERATED -> { if (federatedShareAllowed) { icon = R.drawable.ic_user - displayName = if (userName == shareWith) { - context?.getString(R.string.share_remote_clarification, userName) - } else { - val uriSplitted = - shareWith.split("@".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() - context?.getString( - R.string.share_known_remote_clarification, userName, - uriSplitted[uriSplitted.size - 1] - ) + displayName = if (userName == shareWith) { context?.getString(R.string.share_remote_clarification, userName) } + else { + val uriSplitted = shareWith.split("@".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + context?.getString(R.string.share_known_remote_clarification, userName, uriSplitted[uriSplitted.size - 1]) } dataUri = Uri.withAppendedPath(remoteBaseUri, shareWith) } diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/transfers/TransfersAdapter.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/transfers/TransfersAdapter.kt index 0c163464b0a..cd50af79117 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/presentation/transfers/TransfersAdapter.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/transfers/TransfersAdapter.kt @@ -77,137 +77,11 @@ class TransfersAdapter( when (holder) { is TransferItemViewHolder -> { val transferItem = getItem(position) as TransferItem - holder.binding.apply { - val remoteFile = File(transferItem.transfer.remotePath) - - var fileName = remoteFile.name - if (fileName.isEmpty()) { - fileName = File.separator - } - uploadName.text = fileName - - transferItem.space?.let { - spacePathLine.spaceName.isVisible = true - spacePathLine.spaceIcon.isVisible = true - if (it.isPersonal) { - spacePathLine.spaceIcon.setImageResource(R.drawable.ic_folder) - spacePathLine.spaceName.setText(R.string.bottom_nav_personal) - } else { - spacePathLine.spaceName.text = it.name - } - } - - remoteFile.parent?.let { - spacePathLine.path.text = if (it.endsWith("${OCFile.PATH_SEPARATOR}")) it else "$it${OCFile.PATH_SEPARATOR}" - } - - uploadFileSize.text = DisplayUtils.bytesToHumanReadable(transferItem.transfer.fileSize, holder.itemView.context, true) - - uploadDate.isVisible = - transferItem.transfer.transferEndTimestamp != null && transferItem.transfer.status != TransferStatus.TRANSFER_FAILED - transferItem.transfer.transferEndTimestamp?.let { - val dateString = DisplayUtils.getRelativeDateTimeString( - holder.itemView.context, - it, - DateUtils.SECOND_IN_MILLIS, - DateUtils.WEEK_IN_MILLIS, - 0 - ) - uploadDate.text = ", $dateString" - } - - try { - val account = AccountUtils.getOwnCloudAccountByName(holder.itemView.context, transferItem.transfer.accountName) - val oca = OwnCloudAccount(account, holder.itemView.context) - val accountName = oca.displayName + " @ " + - DisplayUtils.convertIdn(account.name.substring(account.name.lastIndexOf("@") + 1), false) - uploadAccount.text = accountName - } catch (e: Exception) { - Timber.w("Couldn't get display name for account, using old style") - uploadAccount.text = transferItem.transfer.accountName - } - - uploadStatus.isVisible = transferItem.transfer.status != TransferStatus.TRANSFER_SUCCEEDED - uploadStatus.text = " — " + holder.itemView.context.getString(transferItem.transfer.statusToStringRes()) - - Glide.with(holder.itemView) - .load(transferItem.transfer.localPath) - .diskCacheStrategy(DiskCacheStrategy.ALL) - .placeholder( - MimetypeIconUtil.getFileTypeIconId( - MimetypeIconUtil.getBestMimeTypeByFilename(transferItem.transfer.localPath), - fileName - ) - ) - .into(thumbnail) - - uploadRightButton.isVisible = transferItem.transfer.status != TransferStatus.TRANSFER_SUCCEEDED - - uploadProgressBar.isVisible = transferItem.transfer.status == TransferStatus.TRANSFER_IN_PROGRESS - - holder.itemView.setOnClickListener(null) - - when (transferItem.transfer.status) { - TransferStatus.TRANSFER_IN_PROGRESS, TransferStatus.TRANSFER_QUEUED -> { - uploadRightButton.apply { - setImageResource(R.drawable.ic_action_cancel_grey) - setOnClickListener { - cancel(transferItem.transfer) - } - } - } - TransferStatus.TRANSFER_FAILED -> { - uploadRightButton.apply { - setImageResource(R.drawable.ic_action_delete_grey) - setOnClickListener { - cancel(transferItem.transfer) - } - } - holder.itemView.setOnClickListener { - retry(transferItem.transfer) - } - holder.binding.ListItemLayout.isClickable = true - holder.binding.ListItemLayout.isFocusable = true - } - TransferStatus.TRANSFER_SUCCEEDED -> { - // Nothing to do - } - } - } + onBindTransferItemViewHolder(holder, transferItem) } is HeaderItemViewHolder -> { val headerItem = getItem(position) as HeaderItem - holder.binding.apply { - uploadListGroupName.text = holder.itemView.context.getString(headerTitleStringRes(headerItem.status)) - - val stringResFileCount = - if (headerItem.numberTransfers == 1) R.string.uploads_view_group_file_count_single else R.string.uploads_view_group_file_count - val fileCountText: String = String.format(holder.itemView.context.getString(stringResFileCount), headerItem.numberTransfers) - textViewFileCount.text = fileCountText - - uploadListGroupButtonClear.isVisible = headerItem.status == TransferStatus.TRANSFER_FAILED || - headerItem.status == TransferStatus.TRANSFER_SUCCEEDED - uploadListGroupButtonRetry.isVisible = headerItem.status == TransferStatus.TRANSFER_FAILED - - when (headerItem.status) { - TransferStatus.TRANSFER_FAILED -> { - uploadListGroupButtonClear.setOnClickListener { - clearFailed() - } - uploadListGroupButtonRetry.setOnClickListener { - retryFailed() - } - } - TransferStatus.TRANSFER_SUCCEEDED -> { - uploadListGroupButtonClear.setOnClickListener { - clearSuccessful() - } - } - TransferStatus.TRANSFER_QUEUED, TransferStatus.TRANSFER_IN_PROGRESS -> { - // Nothing to do - } - } - } + onBindHeaderItemViewHolder(holder, headerItem) } } @@ -226,6 +100,142 @@ class TransfersAdapter( } + private fun onBindTransferItemViewHolder(holder: TransferItemViewHolder, transferItem: TransferItem) { + holder.binding.apply { + val remoteFile = File(transferItem.transfer.remotePath) + + var fileName = remoteFile.name + if (fileName.isEmpty()) { + fileName = File.separator + } + uploadName.text = fileName + + transferItem.space?.let { + spacePathLine.spaceName.isVisible = true + spacePathLine.spaceIcon.isVisible = true + if (it.isPersonal) { + spacePathLine.spaceIcon.setImageResource(R.drawable.ic_folder) + spacePathLine.spaceName.setText(R.string.bottom_nav_personal) + } else { + spacePathLine.spaceName.text = it.name + } + } + + remoteFile.parent?.let { + spacePathLine.path.text = if (it.endsWith("${OCFile.PATH_SEPARATOR}")) it else "$it${OCFile.PATH_SEPARATOR}" + } + + uploadFileSize.text = DisplayUtils.bytesToHumanReadable(transferItem.transfer.fileSize, holder.itemView.context, true) + + uploadDate.isVisible = + transferItem.transfer.transferEndTimestamp != null && transferItem.transfer.status != TransferStatus.TRANSFER_FAILED + transferItem.transfer.transferEndTimestamp?.let { + val dateString = DisplayUtils.getRelativeDateTimeString( + holder.itemView.context, + it, + DateUtils.SECOND_IN_MILLIS, + DateUtils.WEEK_IN_MILLIS, + 0 + ) + uploadDate.text = ", $dateString" + } + + try { + val account = AccountUtils.getOwnCloudAccountByName(holder.itemView.context, transferItem.transfer.accountName) + val oca = OwnCloudAccount(account, holder.itemView.context) + val accountName = oca.displayName + " @ " + + DisplayUtils.convertIdn(account.name.substring(account.name.lastIndexOf("@") + 1), false) + uploadAccount.text = accountName + } catch (e: Exception) { + Timber.w("Couldn't get display name for account, using old style") + uploadAccount.text = transferItem.transfer.accountName + } + + uploadStatus.isVisible = transferItem.transfer.status != TransferStatus.TRANSFER_SUCCEEDED + uploadStatus.text = " — " + holder.itemView.context.getString(transferItem.transfer.statusToStringRes()) + + Glide.with(holder.itemView) + .load(transferItem.transfer.localPath) + .diskCacheStrategy(DiskCacheStrategy.ALL) + .placeholder( + MimetypeIconUtil.getFileTypeIconId( + MimetypeIconUtil.getBestMimeTypeByFilename(transferItem.transfer.localPath), + fileName + ) + ) + .into(thumbnail) + + uploadRightButton.isVisible = transferItem.transfer.status != TransferStatus.TRANSFER_SUCCEEDED + + uploadProgressBar.isVisible = transferItem.transfer.status == TransferStatus.TRANSFER_IN_PROGRESS + + holder.itemView.setOnClickListener(null) + + when (transferItem.transfer.status) { + TransferStatus.TRANSFER_IN_PROGRESS, TransferStatus.TRANSFER_QUEUED -> { + uploadRightButton.apply { + setImageResource(R.drawable.ic_action_cancel_grey) + setOnClickListener { + cancel(transferItem.transfer) + } + } + } + + TransferStatus.TRANSFER_FAILED -> { + uploadRightButton.apply { + setImageResource(R.drawable.ic_action_delete_grey) + setOnClickListener { + cancel(transferItem.transfer) + } + } + holder.itemView.setOnClickListener { + retry(transferItem.transfer) + } + holder.binding.ListItemLayout.isClickable = true + holder.binding.ListItemLayout.isFocusable = true + } + + TransferStatus.TRANSFER_SUCCEEDED -> { + // Nothing to do + } + } + } + } + + private fun onBindHeaderItemViewHolder(holder: HeaderItemViewHolder, headerItem: HeaderItem) { + holder.binding.apply { + uploadListGroupName.text = holder.itemView.context.getString(headerTitleStringRes(headerItem.status)) + + val stringResFileCount = + if (headerItem.numberTransfers == 1) R.string.uploads_view_group_file_count_single else R.string.uploads_view_group_file_count + val fileCountText: String = String.format(holder.itemView.context.getString(stringResFileCount), headerItem.numberTransfers) + textViewFileCount.text = fileCountText + + uploadListGroupButtonClear.isVisible = headerItem.status == TransferStatus.TRANSFER_FAILED || + headerItem.status == TransferStatus.TRANSFER_SUCCEEDED + uploadListGroupButtonRetry.isVisible = headerItem.status == TransferStatus.TRANSFER_FAILED + + when (headerItem.status) { + TransferStatus.TRANSFER_FAILED -> { + uploadListGroupButtonClear.setOnClickListener { + clearFailed() + } + uploadListGroupButtonRetry.setOnClickListener { + retryFailed() + } + } + TransferStatus.TRANSFER_SUCCEEDED -> { + uploadListGroupButtonClear.setOnClickListener { + clearSuccessful() + } + } + TransferStatus.TRANSFER_QUEUED, TransferStatus.TRANSFER_IN_PROGRESS -> { + // Nothing to do + } + } + } + } + private fun headerTitleStringRes(status: TransferStatus): Int { return when (status) { TransferStatus.TRANSFER_IN_PROGRESS -> R.string.uploads_view_group_current_uploads diff --git a/owncloudApp/src/main/java/com/owncloud/android/providers/FileContentProvider.kt b/owncloudApp/src/main/java/com/owncloud/android/providers/FileContentProvider.kt index f00709fa4f8..db8409ebdba 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/providers/FileContentProvider.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/providers/FileContentProvider.kt @@ -482,6 +482,7 @@ class FileContentProvider(val executors: Executors = Executors()) : ContentProvi createCameraUploadsSyncTable(db) } + @Suppress("LongMethod") override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { Timber.i("SQL : Entering in onUpgrade") var upgraded = false diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.kt b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.kt index b7a4a285177..0cc7ef9a8d7 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.kt @@ -57,6 +57,7 @@ import com.google.android.material.navigation.NavigationView import com.owncloud.android.R import com.owncloud.android.domain.capabilities.model.OCCapability import com.owncloud.android.domain.files.model.FileListOption +import com.owncloud.android.domain.user.model.UserQuota import com.owncloud.android.domain.user.model.UserQuotaState import com.owncloud.android.domain.utils.Event import com.owncloud.android.extensions.goToUrl @@ -311,106 +312,7 @@ abstract class DrawerActivity : ToolbarActivity() { when (val uiResult = event.peekContent()) { is UIResult.Success -> { uiResult.data?.let { userQuota -> - when { - userQuota.available == -4L -> { // Light users (oCIS) - getAccountQuotaText()?.text = getString(R.string.drawer_unavailable_used_storage) - getAccountQuotaBar()?.isVisible = false - getAccountQuotaStatusText()?.isVisible = false - } - - userQuota.available < 0 -> { // Pending, unknown or unlimited free storage - getAccountQuotaBar()?.apply { - isVisible = true - progress = 0 - progressTintList = ColorStateList.valueOf(resources.getColor(R.color.color_accent)) - } - getAccountQuotaText()?.text = String.format( - getString(R.string.drawer_unavailable_free_storage), - DisplayUtils.bytesToHumanReadable(userQuota.used, this, true) - ) - getAccountQuotaStatusText()?.visibility = View.GONE - } - - userQuota.available == 0L -> { // Exceeded storage. The value is over 100%. - getAccountQuotaBar()?.apply { - isVisible = true - progress = 100 - progressTintList = ColorStateList.valueOf(resources.getColor(R.color.quota_exceeded)) - } - - if (userQuota.state == UserQuotaState.EXCEEDED) { // oCIS - getAccountQuotaText()?.apply { - text = String.format( - getString(R.string.drawer_quota), - DisplayUtils.bytesToHumanReadable(userQuota.used, context, true), - DisplayUtils.bytesToHumanReadable(userQuota.getTotal(), context, true), - userQuota.getRelative() - ) - } - getAccountQuotaStatusText()?.apply { - visibility = View.VISIBLE - text = getString(R.string.drawer_exceeded_quota) - } - } else { // oC10 - getAccountQuotaText()?.text = getString(R.string.drawer_exceeded_quota) - getAccountQuotaStatusText()?.visibility = View.GONE - } - } - - else -> { // Limited storage. Value under 100% - if (userQuota.state == UserQuotaState.NEARING) { // Nearing storage. Value between 75% and 90% - getAccountQuotaBar()?.apply { - isVisible = true - progress = userQuota.getRelative().toInt() - progressTintList = ColorStateList.valueOf(resources.getColor(R.color.color_accent)) - } - getAccountQuotaText()?.apply { - text = String.format( - getString(R.string.drawer_quota), - DisplayUtils.bytesToHumanReadable(userQuota.used, context, true), - DisplayUtils.bytesToHumanReadable(userQuota.getTotal(), context, true), - userQuota.getRelative() - ) - } - getAccountQuotaStatusText()?.apply { - visibility = View.VISIBLE - text = getString(R.string.drawer_nearing_quota) - } - } else if (userQuota.state == UserQuotaState.CRITICAL || - userQuota.state == UserQuotaState.EXCEEDED) { // Critical storage. Value over 90% - getAccountQuotaBar()?.apply { - isVisible = true - progress = userQuota.getRelative().toInt() - progressTintList = ColorStateList.valueOf(resources.getColor(R.color.quota_exceeded)) - } - getAccountQuotaText()?.apply { - text = String.format( - getString(R.string.drawer_quota), - DisplayUtils.bytesToHumanReadable(userQuota.used, context, true), - DisplayUtils.bytesToHumanReadable(userQuota.getTotal(), context, true), - userQuota.getRelative() - ) - } - getAccountQuotaStatusText()?.apply { - visibility = View.VISIBLE - text = getString(R.string.drawer_critical_quota) - } - } else { // Normal storage. Value under 75% - getAccountQuotaBar()?.apply { - progress = userQuota.getRelative().toInt() - isVisible = true - progressTintList = ColorStateList.valueOf(resources.getColor(R.color.color_accent)) - } - getAccountQuotaText()?.text = String.format( - getString(R.string.drawer_quota), - DisplayUtils.bytesToHumanReadable(userQuota.used, this, true), - DisplayUtils.bytesToHumanReadable(userQuota.getTotal(), this, true), - userQuota.getRelative() - ) - getAccountQuotaStatusText()?.visibility = View.GONE - } - } - } + onUpdateQuotaIsSuccessful(userQuota) } } is UIResult.Loading -> getAccountQuotaText()?.text = getString(R.string.drawer_loading_quota) @@ -419,6 +321,106 @@ abstract class DrawerActivity : ToolbarActivity() { } } + private fun onUpdateQuotaIsSuccessful(userQuota: UserQuota) { + when { + userQuota.available == -4L -> { // Light users (oCIS) + getAccountQuotaText()?.text = getString(R.string.drawer_unavailable_used_storage) + getAccountQuotaBar()?.isVisible = false + getAccountQuotaStatusText()?.isVisible = false + } + userQuota.available < 0 -> { // Pending, unknown or unlimited free storage + getAccountQuotaBar()?.apply { + isVisible = true + progress = 0 + progressTintList = ColorStateList.valueOf(resources.getColor(R.color.color_accent)) + } + getAccountQuotaText()?.text = String.format( + getString(R.string.drawer_unavailable_free_storage), + DisplayUtils.bytesToHumanReadable(userQuota.used, this, true) + ) + getAccountQuotaStatusText()?.visibility = View.GONE + } + userQuota.available == 0L -> { // Exceeded storage. The value is over 100%. + getAccountQuotaBar()?.apply { + isVisible = true + progress = 100 + progressTintList = ColorStateList.valueOf(resources.getColor(R.color.quota_exceeded)) + } + + if (userQuota.state == UserQuotaState.EXCEEDED) { // oCIS + getAccountQuotaText()?.apply { + text = String.format( + getString(R.string.drawer_quota), + DisplayUtils.bytesToHumanReadable(userQuota.used, context, true), + DisplayUtils.bytesToHumanReadable(userQuota.getTotal(), context, true), + userQuota.getRelative() + ) + } + getAccountQuotaStatusText()?.apply { + visibility = View.VISIBLE + text = getString(R.string.drawer_exceeded_quota) + } + } else { // oC10 + getAccountQuotaText()?.text = getString(R.string.drawer_exceeded_quota) + getAccountQuotaStatusText()?.visibility = View.GONE + } + } + else -> { // Limited storage. Value under 100% + if (userQuota.state == UserQuotaState.NEARING) { // Nearing storage. Value between 75% and 90% + getAccountQuotaBar()?.apply { + isVisible = true + progress = userQuota.getRelative().toInt() + progressTintList = ColorStateList.valueOf(resources.getColor(R.color.color_accent)) + } + getAccountQuotaText()?.apply { + text = String.format( + getString(R.string.drawer_quota), + DisplayUtils.bytesToHumanReadable(userQuota.used, context, true), + DisplayUtils.bytesToHumanReadable(userQuota.getTotal(), context, true), + userQuota.getRelative() + ) + } + getAccountQuotaStatusText()?.apply { + visibility = View.VISIBLE + text = getString(R.string.drawer_nearing_quota) + } + } else if (userQuota.state == UserQuotaState.CRITICAL || + userQuota.state == UserQuotaState.EXCEEDED) { // Critical storage. Value over 90% + getAccountQuotaBar()?.apply { + isVisible = true + progress = userQuota.getRelative().toInt() + progressTintList = ColorStateList.valueOf(resources.getColor(R.color.quota_exceeded)) + } + getAccountQuotaText()?.apply { + text = String.format( + getString(R.string.drawer_quota), + DisplayUtils.bytesToHumanReadable(userQuota.used, context, true), + DisplayUtils.bytesToHumanReadable(userQuota.getTotal(), context, true), + userQuota.getRelative() + ) + } + getAccountQuotaStatusText()?.apply { + visibility = View.VISIBLE + text = getString(R.string.drawer_critical_quota) + } + } else { // Normal storage. Value under 75% + getAccountQuotaBar()?.apply { + progress = userQuota.getRelative().toInt() + isVisible = true + progressTintList = ColorStateList.valueOf(resources.getColor(R.color.color_accent)) + } + getAccountQuotaText()?.text = String.format( + getString(R.string.drawer_quota), + DisplayUtils.bytesToHumanReadable(userQuota.used, this, true), + DisplayUtils.bytesToHumanReadable(userQuota.getTotal(), this, true), + userQuota.getRelative() + ) + getAccountQuotaStatusText()?.visibility = View.GONE + } + } + } + } + override fun setupRootToolbar(title: String, isSearchEnabled: Boolean, isAvatarRequested: Boolean) { super.setupRootToolbar( title = title,