From 01cc7db83a611b457d1849d36967443c64d9c6d9 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Fri, 8 May 2026 15:59:05 +0200 Subject: [PATCH 01/19] fix(oc-file-list): favorite refresh Signed-off-by: alperozturk96 --- .../android/ui/adapter/OCFileListAdapter.java | 10 ++---- .../ui/fragment/OCFileListSearchTask.kt | 31 +++++++------------ 2 files changed, 14 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java b/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java index a2c7616dda3c..a23ee63ef570 100644 --- a/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java +++ b/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java @@ -875,7 +875,9 @@ public void swapDirectory( public void updateAdapter(List newFiles, OCFile directory) { Log_OC.d(TAG, "updating the adapter"); - mFiles = new ArrayList<>(newFiles); + mFiles.clear(); + mFiles.addAll(newFiles); + mFilesAll.clear(); mFilesAll.addAll(mFiles); @@ -982,12 +984,6 @@ public void insertFile(@Nullable OCFile file) { } } - public void addVirtualFile(@NonNull OCFile file) { - if (mFiles.isEmpty() || !mFiles.contains(file)) { - mFiles.add(file); - } - } - @Override public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) { super.onViewRecycled(holder); diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt index 26a8943b311d..5c439f75741a 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt @@ -97,7 +97,6 @@ class OCFileListSearchTask( ) } else { parseAndSaveVirtuals(result.resultData ?: listOf(), fragment) - fragment.adapter.files } val sortedNewList = sortSearchData(newList, searchType, null, setNewSortOrder = { @@ -193,9 +192,9 @@ class OCFileListSearchTask( } @Suppress("DEPRECATION") - private suspend fun parseAndSaveVirtuals(data: List, fragment: OCFileListFragment) = + private suspend fun parseAndSaveVirtuals(data: List, fragment: OCFileListFragment): List = withContext(Dispatchers.IO) { - val activity = fragment.activity ?: return@withContext + val activity = fragment.activity ?: return@withContext emptyList() val now = System.currentTimeMillis() val (virtualType, onlyMedia) = when (fragment.currentSearchType) { @@ -205,6 +204,7 @@ class OCFileListSearchTask( } val contentValuesList = ArrayList() + val resultFiles = ArrayList() for (obj in data) { try { @@ -215,37 +215,28 @@ class OCFileListSearchTask( ocFile = handleEncryptionIfNeeded(ocFile, storageManager, activity) if (fragment.currentSearchType != SearchType.GALLERY_SEARCH && ocFile.isFolder) { - RefreshFolderOperation( - ocFile, - now, - true, - false, - storageManager, - currentUser, - activity - ).execute(currentUser, activity) + RefreshFolderOperation(ocFile, now, true, false, storageManager, currentUser, activity) + .execute(currentUser, activity) } - val isMediaAllowed = - !onlyMedia || MimeTypeUtil.isImage(ocFile) || MimeTypeUtil.isVideo(ocFile) - + val isMediaAllowed = !onlyMedia || MimeTypeUtil.isImage(ocFile) || MimeTypeUtil.isVideo(ocFile) if (isMediaAllowed) { - fragment.adapter.addVirtualFile(ocFile) + resultFiles.add(ocFile) } - val cv = ContentValues().apply { + contentValuesList.add(ContentValues().apply { put(ProviderMeta.ProviderTableMeta.VIRTUAL_TYPE, virtualType.toString()) put(ProviderMeta.ProviderTableMeta.VIRTUAL_OCFILE_ID, ocFile.fileId) - } - contentValuesList.add(cv) + }) } catch (e: Exception) { Log_OC.e(TAG, "parseAndSaveVirtuals():", e) } } - // Save timestamp + virtual entries preferences.setPhotoSearchTimestamp(System.currentTimeMillis()) storageManager.saveVirtuals(contentValuesList) + + return@withContext resultFiles } @Suppress("DEPRECATION") From 5ba22cbbd50194bc7a9b294517bd16412b0d273d Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 11 May 2026 08:23:53 +0200 Subject: [PATCH 02/19] refresh directory to always use latest cached files to prevent duplicate item Signed-off-by: alperozturk96 --- .../ui/fragment/OCFileListSearchTask.kt | 122 +++++++++++------- 1 file changed, 74 insertions(+), 48 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt index 5c439f75741a..bc791180d6dd 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt @@ -67,67 +67,75 @@ class OCFileListSearchTask( job = fragment.lifecycleScope.launch(Dispatchers.IO) { val searchType = fragment.currentSearchType - // using cached data - val filesInDb = loadCachedDbFiles(event.searchType) - val sortedFilesInDb = sortSearchData(filesInDb, searchType, null, setNewSortOrder = { - fragment.adapter.setSortOrder(it) - }) - updateAdapterData(fragment, sortedFilesInDb) - - // updating cache and refreshing adapter - val result = fetchRemoteResults() - if (result?.isSuccess == true) { - if (result.resultData?.isEmpty() == true) { - withContext(Dispatchers.Main) { - fragment.setEmptyListMessage(fragment.currentSearchType) - return@withContext - } - - return@launch - } - - fragment.adapter.prepareForSearchData(storageManager, fragment.currentSearchType) - - val newList = if (searchType == SearchType.SHARED_FILTER) { - OCShareToOCFileConverter.parseAndSaveShares( - sortedFilesInDb, - result.resultData ?: listOf(), - storageManager, - currentUser.accountName - ) - } else { - parseAndSaveVirtuals(result.resultData ?: listOf(), fragment) - } + if (!refreshCurrentDir(fragment)) { + Log_OC.e(TAG, "folder refresh failed") + return@launch + } - val sortedNewList = sortSearchData(newList, searchType, null, setNewSortOrder = { - fragment.adapter.setSortOrder(it) - }) + val cachedFiles = loadSortedCachedDbFiles(event.searchType, searchType, fragment) + updateAdapterData(fragment, cachedFiles) - updateAdapterData(fragment, sortedNewList) + val result = fetchRemoteResults()?.takeIf { it.isSuccess } ?: run { + showSnackbarError(fragment) + return@launch + } + val resultData = result.resultData?.takeIf { it.isNotEmpty() } ?: run { + withContext(Dispatchers.Main) { fragment.setEmptyListMessage(fragment.currentSearchType) } return@launch } - withContext(Dispatchers.Main) { - fragment.activity?.let { - DisplayUtils.showSnackMessage(it, R.string.error_fetching_sharees) - } + fragment.adapter.prepareForSearchData(storageManager, fragment.currentSearchType) + val remoteFiles = fetchAndSortRemoteFiles(searchType, cachedFiles, resultData, fragment) + updateAdapterData(fragment, remoteFiles) + } + } + + private suspend fun showSnackbarError(fragment: OCFileListFragment) { + withContext(Dispatchers.Main) { + fragment.activity?.let { + DisplayUtils.showSnackMessage(it, R.string.error_fetching_sharees) } } } - fun cancel() = job?.cancel(null) + private suspend fun loadSortedCachedDbFiles( + searchType: SearchRemoteOperation.SearchType, + fragmentSearchType: SearchType, + fragment: OCFileListFragment + ): List { + val files = if (searchType == SearchRemoteOperation.SearchType.SHARED_FILTER) { + storageManager.fileDao.getSharedFiles(currentUser.accountName) + } else { + storageManager.fileDao.getFavoriteFiles(currentUser.accountName) + }.mapNotNull { storageManager.createFileInstance(it) } - fun isFinished(): Boolean = job?.isCompleted == true + return sortSearchData(files, fragmentSearchType, null, setNewSortOrder = { + fragment.adapter.setSortOrder(it) + }) + } - private suspend fun loadCachedDbFiles(searchType: SearchRemoteOperation.SearchType): List = - if (searchType == SearchRemoteOperation.SearchType.SHARED_FILTER) { - storageManager.fileDao - .getSharedFiles(currentUser.accountName) + private suspend fun fetchAndSortRemoteFiles( + searchType: SearchType, + sortedFilesInDb: List, + resultData: List, + fragment: OCFileListFragment + ): List { + val newList = if (searchType == SearchType.SHARED_FILTER) { + OCShareToOCFileConverter.parseAndSaveShares( + sortedFilesInDb, + resultData, + storageManager, + currentUser.accountName + ) } else { - storageManager.fileDao - .getFavoriteFiles(currentUser.accountName) - }.mapNotNull { storageManager.createFileInstance(it) } + parseAndSaveVirtuals(resultData, fragment) + } + + return sortSearchData(newList, searchType, null, setNewSortOrder = { + fragment.adapter.setSortOrder(it) + }) + } @Suppress("DEPRECATION") private suspend fun fetchRemoteResults(): RemoteOperationResult>? { @@ -281,4 +289,22 @@ class OCFileListSearchTask( return fileDataStorage.saveFileWithParent(ocFile, activity) } + + private fun refreshCurrentDir(fragment: OCFileListFragment): Boolean { + val folder = fragment.currentFile ?: storageManager.getFileByDecryptedRemotePath(OCFile.ROOT_PATH) + val operation = + RefreshFolderOperation( + folder, + storageManager, + currentUser, + fragment.context + ) + return operation.execute(currentUser, fragment.context).isSuccess + } + + // region public methods + fun cancel() = job?.cancel(null) + + fun isFinished(): Boolean = job?.isCompleted == true + // endregion } From 10d9dcbe884563d6ac16efeb720c71e67c11a524 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 11 May 2026 08:44:25 +0200 Subject: [PATCH 03/19] only show loading state first time if app doesn't have active search task Signed-off-by: alperozturk96 --- .../com/owncloud/android/ui/fragment/OCFileListFragment.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java index d31dd21f5fba..3a146c7e5f9c 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java @@ -1818,7 +1818,9 @@ protected void handleSearchEvent(SearchEvent event) { } final var activity = getActivity(); - if (activity != null) { + + // only show loading state first time if app doesn't have active search task + if (activity != null && searchTask == null) { activity.runOnUiThread(() -> { getAdapter().removeAllFiles(); setEmptyListMessage(EmptyListState.LOADING); From f477145555e810870bc52c33b4b3e72a2a98b607 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 11 May 2026 08:58:55 +0200 Subject: [PATCH 04/19] refresh current dir was not mandatory Signed-off-by: alperozturk96 --- .../ui/fragment/OCFileListSearchTask.kt | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt index bc791180d6dd..e393c67ce088 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt @@ -10,6 +10,7 @@ package com.owncloud.android.ui.fragment import android.annotation.SuppressLint import android.app.Activity +import android.accounts.Account import android.content.ContentValues import androidx.lifecycle.lifecycleScope import com.nextcloud.client.account.User @@ -67,13 +68,12 @@ class OCFileListSearchTask( job = fragment.lifecycleScope.launch(Dispatchers.IO) { val searchType = fragment.currentSearchType - if (!refreshCurrentDir(fragment)) { - Log_OC.e(TAG, "folder refresh failed") - return@launch - } + refreshCurrentDir(fragment) val cachedFiles = loadSortedCachedDbFiles(event.searchType, searchType, fragment) - updateAdapterData(fragment, cachedFiles) + if (cachedFiles.isNotEmpty()) { + updateAdapterData(fragment, cachedFiles) + } val result = fetchRemoteResults()?.takeIf { it.isSuccess } ?: run { showSnackbarError(fragment) @@ -162,18 +162,16 @@ class OCFileListSearchTask( fragment.adapter.updateAdapter(newList, null) } - private suspend fun sortSearchData( + private fun sortSearchData( list: List, searchType: SearchType, folder: OCFile?, setNewSortOrder: (FileSortOrder) -> Unit - ): List = withContext(Dispatchers.IO) { - var newList = list.toMutableList() - + ): List { if (searchType == SearchType.GALLERY_SEARCH || searchType == SearchType.RECENT_FILES_SEARCH ) { - return@withContext FileStorageUtils.sortOcFolderDescDateModifiedWithoutFavoritesFirst(newList) + return FileStorageUtils.sortOcFolderDescDateModifiedWithoutFavoritesFirst(list) } val foldersBeforeFiles = preferences.isSortFoldersBeforeFiles() @@ -194,9 +192,7 @@ class OCFileListSearchTask( } setNewSortOrder(sortOrder) - newList = sortOrder.sortCloudFiles(newList, foldersBeforeFiles, favoritesFirst) - - return@withContext newList + return sortOrder.sortCloudFiles(list.toMutableList(), foldersBeforeFiles, favoritesFirst) } @Suppress("DEPRECATION") @@ -213,6 +209,7 @@ class OCFileListSearchTask( val contentValuesList = ArrayList() val resultFiles = ArrayList() + var cachedClient: Account? = null for (obj in data) { try { @@ -220,7 +217,9 @@ class OCFileListSearchTask( var ocFile = FileStorageUtils.fillOCFile(remoteFile) FileStorageUtils.searchForLocalFileInDefaultPath(ocFile, currentUser.accountName) ocFile = storageManager.saveFileWithParent(ocFile, activity) - ocFile = handleEncryptionIfNeeded(ocFile, storageManager, activity) + ocFile = handleEncryptionIfNeeded(ocFile, storageManager, activity) { + cachedClient ?: currentUser.toPlatformAccount().also { cachedClient = it } + } if (fragment.currentSearchType != SearchType.GALLERY_SEARCH && ocFile.isFolder) { RefreshFolderOperation(ocFile, now, true, false, storageManager, currentUser, activity) @@ -251,17 +250,15 @@ class OCFileListSearchTask( private fun handleEncryptionIfNeeded( ocFile: OCFile, fileDataStorage: FileDataStorageManager, - activity: Activity + activity: Activity, + accountProvider: () -> Account ): OCFile { val parent = fileDataStorage.getFileById(ocFile.parentId) ?: return ocFile if (!ocFile.isEncrypted && !parent.isEncrypted) return ocFile - val client = OwnCloudClientFactory.createOwnCloudClient( - currentUser.toPlatformAccount(), - activity - ) + val client = OwnCloudClientFactory.createOwnCloudClient(accountProvider(), activity) val metadata = RefreshFolderOperation.getDecryptedFolderMetadata( true, From 7e1f9fb2b4b90b5acee491dfacaea58a696c9b25 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 11 May 2026 09:20:57 +0200 Subject: [PATCH 05/19] resolveLocalFileId instead refresh whole directory Signed-off-by: alperozturk96 --- .../ui/fragment/OCFileListSearchTask.kt | 32 ++++++------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt index e393c67ce088..4b5906e802fa 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt @@ -68,8 +68,6 @@ class OCFileListSearchTask( job = fragment.lifecycleScope.launch(Dispatchers.IO) { val searchType = fragment.currentSearchType - refreshCurrentDir(fragment) - val cachedFiles = loadSortedCachedDbFiles(event.searchType, searchType, fragment) if (cachedFiles.isNotEmpty()) { updateAdapterData(fragment, cachedFiles) @@ -110,9 +108,7 @@ class OCFileListSearchTask( storageManager.fileDao.getFavoriteFiles(currentUser.accountName) }.mapNotNull { storageManager.createFileInstance(it) } - return sortSearchData(files, fragmentSearchType, null, setNewSortOrder = { - fragment.adapter.setSortOrder(it) - }) + return sortSearchData(files, fragmentSearchType, fragment) } private suspend fun fetchAndSortRemoteFiles( @@ -132,9 +128,7 @@ class OCFileListSearchTask( parseAndSaveVirtuals(resultData, fragment) } - return sortSearchData(newList, searchType, null, setNewSortOrder = { - fragment.adapter.setSortOrder(it) - }) + return sortSearchData(newList, searchType, fragment) } @Suppress("DEPRECATION") @@ -165,8 +159,7 @@ class OCFileListSearchTask( private fun sortSearchData( list: List, searchType: SearchType, - folder: OCFile?, - setNewSortOrder: (FileSortOrder) -> Unit + fragment: OCFileListFragment ): List { if (searchType == SearchType.GALLERY_SEARCH || searchType == SearchType.RECENT_FILES_SEARCH @@ -187,11 +180,11 @@ class OCFileListSearchTask( } else -> { - preferences.getSortOrderByFolder(folder) + preferences.getSortOrderByFolder(null) } } - setNewSortOrder(sortOrder) + fragment.adapter.setSortOrder(sortOrder) return sortOrder.sortCloudFiles(list.toMutableList(), foldersBeforeFiles, favoritesFirst) } @@ -216,6 +209,7 @@ class OCFileListSearchTask( val remoteFile = obj as? RemoteFile ?: continue var ocFile = FileStorageUtils.fillOCFile(remoteFile) FileStorageUtils.searchForLocalFileInDefaultPath(ocFile, currentUser.accountName) + resolveLocalFileId(ocFile) ocFile = storageManager.saveFileWithParent(ocFile, activity) ocFile = handleEncryptionIfNeeded(ocFile, storageManager, activity) { cachedClient ?: currentUser.toPlatformAccount().also { cachedClient = it } @@ -287,16 +281,10 @@ class OCFileListSearchTask( return fileDataStorage.saveFileWithParent(ocFile, activity) } - private fun refreshCurrentDir(fragment: OCFileListFragment): Boolean { - val folder = fragment.currentFile ?: storageManager.getFileByDecryptedRemotePath(OCFile.ROOT_PATH) - val operation = - RefreshFolderOperation( - folder, - storageManager, - currentUser, - fragment.context - ) - return operation.execute(currentUser, fragment.context).isSuccess + private fun resolveLocalFileId(ocFile: OCFile) { + if (ocFile.fileId != -1L) return + val localFile = storageManager.getFileByLocalId(ocFile.localId) ?: return + ocFile.fileId = localFile.fileId } // region public methods From 2a26fe66812d7716e3192f01ac74f020be9182a1 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 11 May 2026 09:30:08 +0200 Subject: [PATCH 06/19] simplify on rename logics Signed-off-by: alperozturk96 --- .../ui/activity/FileDisplayActivity.kt | 85 ++++++++++++------- .../ui/dialog/RenameFileDialogFragment.kt | 64 +++++++------- 2 files changed, 82 insertions(+), 67 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt index db6f451d3ef8..64a2936e2405 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt @@ -2352,38 +2352,7 @@ class FileDisplayActivity : private fun onRenameFileOperationFinish(operation: RenameFileOperation, result: RemoteOperationResult<*>) { val optionalUser = user val renamedFile = operation.file - if (result.isSuccess && optionalUser.isPresent) { - val currentUser = optionalUser.get() - val leftFragment = this.leftFragment - if (leftFragment is FileFragment) { - if (leftFragment is FileDetailFragment && renamedFile == leftFragment.file) { - leftFragment.updateFileDetails(renamedFile, currentUser) - showDetails(renamedFile) - } else if (leftFragment is PreviewMediaFragment && renamedFile == leftFragment.file) { - leftFragment.updateFile(renamedFile) - if (PreviewMediaFragment.canBePreviewed(renamedFile)) { - val position = leftFragment.position - startMediaPreview(renamedFile, position, true, true, true, false) - } else { - fileOperationsHelper.openFile(renamedFile) - } - } else if (leftFragment is PreviewTextFragment && renamedFile == leftFragment.file) { - (leftFragment as PreviewTextFileFragment).updateFile(renamedFile) - if (PreviewTextFileFragment.canBePreviewed(renamedFile)) { - startTextPreview(renamedFile, true) - } else { - fileOperationsHelper.openFile(renamedFile) - } - } - } - - val file = storageManager.getFileById(renamedFile.parentId) - if (file != null && file == getCurrentDir()) { - updateListOfFilesFragment() - } - refreshGalleryFragmentIfNeeded() - fetchRecommendedFilesIfNeeded(ignoreETag = true, currentDir) - } else { + if (!result.isSuccess || optionalUser.isEmpty) { DisplayUtils.showSnackMessage( this, ErrorMessageAdapter.getErrorCauseMessage(result, operation, getResources()) @@ -2393,6 +2362,58 @@ class FileDisplayActivity : mLastSslUntrustedServerResult = result showUntrustedCertDialog(mLastSslUntrustedServerResult) } + return + } + + val currentUser = optionalUser.get() + val leftFragment = this.leftFragment + if (leftFragment is FileFragment) { + onRenameFileOperationFinishForFileFragment(leftFragment, renamedFile, currentUser) + } + + val file = storageManager.getFileById(renamedFile.parentId) + if (file != null && file == getCurrentDir()) { + updateListOfFilesFragment() + } + refreshGalleryFragmentIfNeeded() + fetchRecommendedFilesIfNeeded(ignoreETag = true, currentDir) + } + + private fun onRenameFileOperationFinishForFileFragment( + fragment: FileFragment, + ocFile: OCFile, + user: User + ) { + if (fragment.file != ocFile) return + + when (fragment) { + is FileDetailFragment -> { + fragment.updateFileDetails(ocFile, user) + showDetails(ocFile) + } + is PreviewMediaFragment -> { + fragment.updateFile(ocFile) + if (PreviewMediaFragment.canBePreviewed(ocFile)) { + startMediaPreview( + ocFile, + fragment.position, + true, + true, + true, + false + ) + } else { + fileOperationsHelper.openFile(ocFile) + } + } + is PreviewTextFileFragment -> { + fragment.updateFile(ocFile) + if (PreviewTextFileFragment.canBePreviewed(ocFile)) { + startTextPreview(ocFile, true) + } else { + fileOperationsHelper.openFile(ocFile) + } + } } } diff --git a/app/src/main/java/com/owncloud/android/ui/dialog/RenameFileDialogFragment.kt b/app/src/main/java/com/owncloud/android/ui/dialog/RenameFileDialogFragment.kt index 4042629d7560..ffba3be824f4 100644 --- a/app/src/main/java/com/owncloud/android/ui/dialog/RenameFileDialogFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/dialog/RenameFileDialogFragment.kt @@ -37,10 +37,6 @@ import com.owncloud.android.utils.KeyboardUtils import com.owncloud.android.utils.theme.ViewThemeUtils import javax.inject.Inject -/** - * Dialog to input a new name for an [OCFile] being renamed. - * Triggers the rename operation. - */ class RenameFileDialogFragment : DialogFragment(), DialogInterface.OnClickListener, @@ -58,7 +54,7 @@ class RenameFileDialogFragment : lateinit var currentAccount: CurrentAccountProvider private lateinit var binding: EditBoxDialogBinding - private var mTargetFile: OCFile? = null + private var targetFile: OCFile? = null private var positiveButton: MaterialButton? = null private var fileNames: MutableSet? = null @@ -73,15 +69,15 @@ class RenameFileDialogFragment : } override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - mTargetFile = requireArguments().getParcelableArgument(ARG_TARGET_FILE, OCFile::class.java) + targetFile = requireArguments().getParcelableArgument(ARG_TARGET_FILE, OCFile::class.java) val inflater = requireActivity().layoutInflater binding = EditBoxDialogBinding.inflate(inflater, null, false) - val currentName = mTargetFile?.fileName + val currentName = targetFile?.fileName binding.userInput.setText(currentName) viewThemeUtils.material.colorTextInputLayout(binding.userInputContainer) - val extensionStart = if (mTargetFile?.isFolder == true) -1 else currentName?.lastIndexOf('.') + val extensionStart = if (targetFile?.isFolder == true) -1 else currentName?.lastIndexOf('.') val selectionEnd = if ((extensionStart ?: -1) >= 0) extensionStart else currentName?.length if (selectionEnd != null) { binding.userInput.setSelection(0, selectionEnd) @@ -97,7 +93,7 @@ class RenameFileDialogFragment : binding.userInput.addTextChangedListener( FileNameTextWatcher( - previousFileName = mTargetFile?.fileName, + previousFileName = targetFile?.fileName, context = binding.userInputContainer.context, capabilitiesProvider = { oCCapability }, existingFileNamesProvider = { fileNames ?: setOf() }, @@ -168,17 +164,24 @@ class RenameFileDialogFragment : return } - if (mTargetFile?.isOfflineOperation == true) { - fileDataStorageManager.renameOfflineOperation(mTargetFile, newFileName) - typedActivity()?.refreshCurrentDirectory() - } else { - typedActivity()?.connectivityService?.isNetworkAndServerAvailable { result -> - if (result) { - typedActivity()?.fileOperationsHelper?.renameFile(mTargetFile, newFileName) - } else { - fileDataStorageManager.addRenameFileOfflineOperation(mTargetFile, newFileName) - typedActivity()?.refreshCurrentDirectory() - } + val fda = typedActivity() + + if (targetFile?.isOfflineOperation == true) { + fileDataStorageManager.renameOfflineOperation(targetFile, newFileName) + fda?.refreshCurrentDirectory() + return + } + + fda?.connectivityService?.isNetworkAndServerAvailable { result -> + if (result) { + /** + * result of it triggered by + * [com.owncloud.android.ui.activity.FileDisplayActivity.onRemoteOperationFinish] + */ + typedActivity()?.fileOperationsHelper?.renameFile(targetFile, newFileName) + } else { + fileDataStorageManager.addRenameFileOfflineOperation(targetFile, newFileName) + fda.refreshCurrentDirectory() } } } @@ -188,22 +191,13 @@ class RenameFileDialogFragment : private const val ARG_TARGET_FILE = "TARGET_FILE" private const val ARG_PARENT_FOLDER = "PARENT_FOLDER" - /** - * Public factory method to create new RenameFileDialogFragment instances. - * - * @param file File to rename. - * @return Dialog ready to show. - */ @JvmStatic - fun newInstance(file: OCFile?, parentFolder: OCFile?): RenameFileDialogFragment { - val bundle = Bundle().apply { - putParcelable(ARG_TARGET_FILE, file) - putParcelable(ARG_PARENT_FOLDER, parentFolder) - } - - return RenameFileDialogFragment().apply { - arguments = bundle + fun newInstance(file: OCFile?, parentFolder: OCFile?): RenameFileDialogFragment = + RenameFileDialogFragment().apply { + arguments = Bundle().apply { + putParcelable(ARG_TARGET_FILE, file) + putParcelable(ARG_PARENT_FOLDER, parentFolder) + } } - } } } From 9b7c453ea22fae7989440e81dced9f7105adb638 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 11 May 2026 09:41:05 +0200 Subject: [PATCH 07/19] fix refresh after rename Signed-off-by: alperozturk96 --- .../com/owncloud/android/ui/activity/FileDisplayActivity.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt index 64a2936e2405..0b1f82be2e36 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt @@ -2371,10 +2371,7 @@ class FileDisplayActivity : onRenameFileOperationFinishForFileFragment(leftFragment, renamedFile, currentUser) } - val file = storageManager.getFileById(renamedFile.parentId) - if (file != null && file == getCurrentDir()) { - updateListOfFilesFragment() - } + updateListOfFilesFragment() refreshGalleryFragmentIfNeeded() fetchRecommendedFilesIfNeeded(ignoreETag = true, currentDir) } From 243ca5d78b4fe4e186ad29e082d902249bbf9819 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 11 May 2026 09:43:53 +0200 Subject: [PATCH 08/19] fix codacy Signed-off-by: alperozturk96 --- .../android/ui/activity/FileDisplayActivity.kt | 8 +++----- .../ui/dialog/RenameFileDialogFragment.kt | 2 +- .../android/ui/fragment/OCFileListSearchTask.kt | 16 +++++++--------- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt index 0b1f82be2e36..4582aefddd9a 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt @@ -2376,11 +2376,7 @@ class FileDisplayActivity : fetchRecommendedFilesIfNeeded(ignoreETag = true, currentDir) } - private fun onRenameFileOperationFinishForFileFragment( - fragment: FileFragment, - ocFile: OCFile, - user: User - ) { + private fun onRenameFileOperationFinishForFileFragment(fragment: FileFragment, ocFile: OCFile, user: User) { if (fragment.file != ocFile) return when (fragment) { @@ -2388,6 +2384,7 @@ class FileDisplayActivity : fragment.updateFileDetails(ocFile, user) showDetails(ocFile) } + is PreviewMediaFragment -> { fragment.updateFile(ocFile) if (PreviewMediaFragment.canBePreviewed(ocFile)) { @@ -2403,6 +2400,7 @@ class FileDisplayActivity : fileOperationsHelper.openFile(ocFile) } } + is PreviewTextFileFragment -> { fragment.updateFile(ocFile) if (PreviewTextFileFragment.canBePreviewed(ocFile)) { diff --git a/app/src/main/java/com/owncloud/android/ui/dialog/RenameFileDialogFragment.kt b/app/src/main/java/com/owncloud/android/ui/dialog/RenameFileDialogFragment.kt index ffba3be824f4..cc4de04cba0b 100644 --- a/app/src/main/java/com/owncloud/android/ui/dialog/RenameFileDialogFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/dialog/RenameFileDialogFragment.kt @@ -174,7 +174,7 @@ class RenameFileDialogFragment : fda?.connectivityService?.isNetworkAndServerAvailable { result -> if (result) { - /** + /* * result of it triggered by * [com.owncloud.android.ui.activity.FileDisplayActivity.onRemoteOperationFinish] */ diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt index 4b5906e802fa..6788110f67cf 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListSearchTask.kt @@ -156,11 +156,7 @@ class OCFileListSearchTask( fragment.adapter.updateAdapter(newList, null) } - private fun sortSearchData( - list: List, - searchType: SearchType, - fragment: OCFileListFragment - ): List { + private fun sortSearchData(list: List, searchType: SearchType, fragment: OCFileListFragment): List { if (searchType == SearchType.GALLERY_SEARCH || searchType == SearchType.RECENT_FILES_SEARCH ) { @@ -225,10 +221,12 @@ class OCFileListSearchTask( resultFiles.add(ocFile) } - contentValuesList.add(ContentValues().apply { - put(ProviderMeta.ProviderTableMeta.VIRTUAL_TYPE, virtualType.toString()) - put(ProviderMeta.ProviderTableMeta.VIRTUAL_OCFILE_ID, ocFile.fileId) - }) + contentValuesList.add( + ContentValues().apply { + put(ProviderMeta.ProviderTableMeta.VIRTUAL_TYPE, virtualType.toString()) + put(ProviderMeta.ProviderTableMeta.VIRTUAL_OCFILE_ID, ocFile.fileId) + } + ) } catch (e: Exception) { Log_OC.e(TAG, "parseAndSaveVirtuals():", e) } From 6ac4399c0bd43634be95a43acea9a309a2d4125d Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 11 May 2026 12:15:42 +0200 Subject: [PATCH 09/19] fix delete file refresh Signed-off-by: alperozturk96 --- .../ui/activity/FileDisplayActivity.kt | 59 +++++++++---------- .../android/ui/adapter/OCFileListAdapter.java | 14 +++++ 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt index 4582aefddd9a..f6714f4477b9 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt @@ -1691,6 +1691,10 @@ class FileDisplayActivity : it.setEmptyListMessage(EmptyListState.ONLY_ON_DEVICE) } + it.searchEvent?.searchType == SearchRemoteOperation.SearchType.FAVORITE_SEARCH -> { + it.setEmptyListMessage(SearchType.FAVORITE_SEARCH) + } + else -> it.setEmptyListMessage(SearchType.NO_SEARCH) } } @@ -2174,41 +2178,34 @@ class FileDisplayActivity : */ private fun onRemoveFileOperationFinish(operation: RemoveFileOperation, result: RemoteOperationResult<*>) { deleteBatchTracker.onSingleDeleteFinished() + if (!result.isSuccess && result.isSslRecoverableException) { + mLastSslUntrustedServerResult = result + showUntrustedCertDialog(mLastSslUntrustedServerResult) + return + } - if (result.isSuccess) { - val removedFile = operation.file - tryStopPlaying(removedFile) - val leftFragment = this.leftFragment + val removedFile = operation.file + tryStopPlaying(removedFile) + val leftFragment = this.leftFragment - // check if file is still available, if so do nothing - val fileAvailable = storageManager.fileExists(removedFile.fileId) - if (leftFragment is FileFragment && !fileAvailable && removedFile == leftFragment.file) { - file = storageManager.getFileById(removedFile.parentId) - resetScrollingAndUpdateActionBar() - } - val parentFile = storageManager.getFileById(removedFile.parentId) - if (parentFile != null && parentFile == getCurrentDir()) { - updateListOfFilesFragment() - } else if (leftFragment is OCFileListFragment && - SearchRemoteOperation.SearchType.FAVORITE_SEARCH == leftFragment.searchEvent?.searchType - ) { - leftFragment.adapter?.run { - val file = files.find { it.fileId == removedFile.fileId } - if (file != null) { - val pos = getItemPosition(file) - files.remove(file) - notifyItemRemoved(pos) - } - } - } - supportInvalidateOptionsMenu() - fetchRecommendedFilesIfNeeded(ignoreETag = true, currentDir) - } else { - if (result.isSslRecoverableException) { - mLastSslUntrustedServerResult = result - showUntrustedCertDialog(mLastSslUntrustedServerResult) + // check if file is still available, if so do nothing + val fileAvailable = storageManager.fileExists(removedFile.fileId) + if (leftFragment is FileFragment && !fileAvailable && removedFile == leftFragment.file) { + file = storageManager.getFileById(removedFile.parentId) + resetScrollingAndUpdateActionBar() + } + + if (leftFragment is OCFileListFragment) { + leftFragment.adapter?.removeFile(removedFile) + + if (leftFragment.adapter?.isEmpty == true) { + val emptyState = leftFragment.searchEvent?.toSearchType() ?: SearchType.NO_SEARCH + leftFragment.setEmptyListMessage(emptyState) } } + + supportInvalidateOptionsMenu() + fetchRecommendedFilesIfNeeded(ignoreETag = true, currentDir) } override fun onAutoUploadFolderRemoved( diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java b/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java index a23ee63ef570..1a139f950da6 100644 --- a/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java +++ b/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java @@ -1108,4 +1108,18 @@ public void removeAllFiles() { mFilesAll.clear(); notifyDataSetChanged(); } + + @SuppressLint("NotifyDataSetChanged") + public void removeFile(@NonNull OCFile file) { + int position = getItemPosition(file); + + mFiles.remove(file); + mFilesAll.remove(file); + + if (position != -1) { + notifyItemRemoved(position); + } else { + notifyDataSetChanged(); + } + } } From bef362f2654b24837569f0a9bff0ded2c5e35681 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Mon, 11 May 2026 15:42:35 +0200 Subject: [PATCH 10/19] keep layout style after rename Signed-off-by: alperozturk96 --- .../client/preferences/AppPreferences.java | 2 +- .../client/preferences/AppPreferencesImpl.java | 4 ++-- .../android/ui/fragment/FileListLayoutManager.kt | 15 ++++++++++----- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java b/app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java index b7d6818ea5a1..135d3fb364bd 100644 --- a/app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java +++ b/app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java @@ -135,7 +135,7 @@ default void onDarkThemeModeChanged(DarkMode mode) { * @return preference value, default is * {@link com.owncloud.android.ui.fragment.OCFileListFragment#FOLDER_LAYOUT_LIST} */ - String getFolderLayout(OCFile folder); + String getFolderLayout(OCFile folder, String defaultLayout); /** * Set preferred folder display type. diff --git a/app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java b/app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java index a16beaeaaad9..59d4de7ccfd1 100644 --- a/app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java +++ b/app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java @@ -336,12 +336,12 @@ public String[] getPassCode() { } @Override - public String getFolderLayout(OCFile folder) { + public String getFolderLayout(OCFile folder, String defaultLayout) { return getFolderPreference(context, userAccountManager.getUser(), PREF__FOLDER_LAYOUT, folder, - FOLDER_LAYOUT_LIST); + defaultLayout); } @Override diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/FileListLayoutManager.kt b/app/src/main/java/com/owncloud/android/ui/fragment/FileListLayoutManager.kt index 87070d218f14..7601aa881d22 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/FileListLayoutManager.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/FileListLayoutManager.kt @@ -22,6 +22,10 @@ import com.owncloud.android.utils.FileSortOrder class FileListLayoutManager(private val fragment: OCFileListFragment, private val preferences: AppPreferences) { + companion object { + private var lastLayout = OCFileListFragment.FOLDER_LAYOUT_LIST + } + fun sortFiles(sortOrder: FileSortOrder?) { fragment.mSortButton?.setText(DisplayUtils.getSortOrderStringId(sortOrder)) sortOrder?.let { fragment.mAdapter.setSortOrder(fragment.mFile, it) } @@ -40,9 +44,9 @@ class FileListLayoutManager(private val fragment: OCFileListFragment, private va */ fun isGridViewPreferred(folder: OCFile?): Boolean = if (fragment.searchEvent != null) { (fragment.searchEvent.toSearchType() != SearchType.SHARED_FILTER) && - (OCFileListFragment.FOLDER_LAYOUT_GRID == preferences.getFolderLayout(folder)) + (OCFileListFragment.FOLDER_LAYOUT_GRID == preferences.getFolderLayout(folder, lastLayout)) } else { - OCFileListFragment.FOLDER_LAYOUT_GRID == preferences.getFolderLayout(folder) + OCFileListFragment.FOLDER_LAYOUT_GRID == preferences.getFolderLayout(folder, lastLayout) } fun setLayoutViewMode() { @@ -65,6 +69,7 @@ class FileListLayoutManager(private val fragment: OCFileListFragment, private va fun switchToListView() { if (fragment.isGridEnabled) { switchLayoutManager(false) + lastLayout = OCFileListFragment.FOLDER_LAYOUT_LIST } } @@ -76,6 +81,7 @@ class FileListLayoutManager(private val fragment: OCFileListFragment, private va fun switchToGridView() { if (!fragment.isGridEnabled) { switchLayoutManager(true) + lastLayout = OCFileListFragment.FOLDER_LAYOUT_GRID } } @@ -100,12 +106,11 @@ class FileListLayoutManager(private val fragment: OCFileListFragment, private va val layoutManager: RecyclerView.LayoutManager? if (grid) { layoutManager = GridLayoutManager(context, fragment.columnsCount) - val gridLayoutManager = layoutManager - gridLayoutManager.spanSizeLookup = object : SpanSizeLookup() { + layoutManager.spanSizeLookup = object : SpanSizeLookup() { override fun getSpanSize(position: Int): Int = if (position == fragment.adapter.itemCount - 1 || (position == 0 && fragment.adapter.shouldShowHeader()) ) { - gridLayoutManager.spanCount + layoutManager.spanCount } else { 1 } From 3e9412e45fe87ca72f65e68d81ff00acae313676 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Thu, 21 May 2026 11:22:57 +0300 Subject: [PATCH 11/19] introduce FolderLayout Signed-off-by: alperozturk96 --- .../client/preferences/AppPreferences.java | 20 +++++++++- .../preferences/AppPreferencesImpl.java | 23 ++++++++++- .../ui/fragment/FileListLayoutManager.kt | 40 ++++++++----------- .../ui/fragment/OCFileListFragment.java | 2 +- 4 files changed, 57 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java b/app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java index 135d3fb364bd..37f3d6552499 100644 --- a/app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java +++ b/app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java @@ -13,6 +13,7 @@ import com.nextcloud.appReview.AppReviewShownModel; import com.nextcloud.client.jobs.LogEntry; import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.ui.fragment.FileListLayoutManager; import com.owncloud.android.utils.FileSortOrder; import java.util.List; @@ -135,7 +136,7 @@ default void onDarkThemeModeChanged(DarkMode mode) { * @return preference value, default is * {@link com.owncloud.android.ui.fragment.OCFileListFragment#FOLDER_LAYOUT_LIST} */ - String getFolderLayout(OCFile folder, String defaultLayout); + String getFolderLayout(OCFile folder); /** * Set preferred folder display type. @@ -145,6 +146,23 @@ default void onDarkThemeModeChanged(DarkMode mode) { */ void setFolderLayout(@Nullable OCFile folder, String layoutName); + /** + * Get preferred folder display type by view type. + * + * @param type The folder view type + * @return preference value, default is + * {@link com.owncloud.android.ui.fragment.OCFileListFragment#FOLDER_LAYOUT_LIST} + */ + String getFolderLayout(FileListLayoutManager.FolderLayout type); + + /** + * Set preferred folder display type by view type. + * + * @param type The folder view type + * @param layoutName preference value + */ + void setFolderLayout(FileListLayoutManager.FolderLayout type, String layoutName); + /** * Saves the path where the user selected to do the last upload of a file shared from other app. * diff --git a/app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java b/app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java index 59d4de7ccfd1..0969649144d4 100644 --- a/app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java +++ b/app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java @@ -28,6 +28,7 @@ import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.ui.activity.PassCodeActivity; import com.owncloud.android.ui.activity.SettingsActivity; +import com.owncloud.android.ui.fragment.FileListLayoutManager; import com.owncloud.android.utils.FileSortOrder; import java.lang.reflect.Type; @@ -336,12 +337,12 @@ public String[] getPassCode() { } @Override - public String getFolderLayout(OCFile folder, String defaultLayout) { + public String getFolderLayout(OCFile folder) { return getFolderPreference(context, userAccountManager.getUser(), PREF__FOLDER_LAYOUT, folder, - defaultLayout); + FOLDER_LAYOUT_LIST); } @Override @@ -353,6 +354,24 @@ public void setFolderLayout(@Nullable OCFile folder, String layoutName) { layoutName); } + @Override + public String getFolderLayout(FileListLayoutManager.FolderLayout type) { + User user = userAccountManager.getUser(); + if (user.isAnonymous()) { + return FOLDER_LAYOUT_LIST; + } + ArbitraryDataProvider dataProvider = new ArbitraryDataProviderImpl(context); + String value = dataProvider.getValue(user.getAccountName(), PREF__FOLDER_LAYOUT + "_" + type); + return value.isEmpty() ? FOLDER_LAYOUT_LIST : value; + } + + @Override + public void setFolderLayout(FileListLayoutManager.FolderLayout type, String layoutName) { + User user = userAccountManager.getUser(); + ArbitraryDataProvider dataProvider = new ArbitraryDataProviderImpl(context); + dataProvider.storeOrUpdateKeyValue(user.getAccountName(), PREF__FOLDER_LAYOUT + "_" + type, layoutName); + } + @Override public FileSortOrder getSortOrderByFolder(OCFile folder) { return FileSortOrder.sortOrders.get(getFolderPreference(context, diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/FileListLayoutManager.kt b/app/src/main/java/com/owncloud/android/ui/fragment/FileListLayoutManager.kt index 7601aa881d22..35c48c5baa15 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/FileListLayoutManager.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/FileListLayoutManager.kt @@ -14,7 +14,6 @@ import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.nextcloud.client.preferences.AppPreferences -import com.owncloud.android.datamodel.OCFile import com.owncloud.android.lib.common.utils.Log_OC import com.owncloud.android.ui.adapter.OCFileListAdapter import com.owncloud.android.utils.DisplayUtils @@ -22,8 +21,11 @@ import com.owncloud.android.utils.FileSortOrder class FileListLayoutManager(private val fragment: OCFileListFragment, private val preferences: AppPreferences) { - companion object { - private var lastLayout = OCFileListFragment.FOLDER_LAYOUT_LIST + enum class FolderLayout { + Shared, + Favorites, + AllFiles, + Child } fun sortFiles(sortOrder: FileSortOrder?) { @@ -31,26 +33,18 @@ class FileListLayoutManager(private val fragment: OCFileListFragment, private va sortOrder?.let { fragment.mAdapter.setSortOrder(fragment.mFile, it) } } - /** - * Determines whether a folder should be displayed in grid or list view. - * - * - * The preference is checked for the given folder. If the folder itself does not have a preference set, - * it will fall back to its parent folder recursively until a preference is found (root folder is always set). - * Additionally, if a search event is active and is of type `SHARED_FILTER`, grid view is disabled. - * - * @param folder The folder to check, or `null` to refer to the root folder. - * @return `true` if the folder should be displayed in grid mode, `false` if list mode is preferred. - */ - fun isGridViewPreferred(folder: OCFile?): Boolean = if (fragment.searchEvent != null) { - (fragment.searchEvent.toSearchType() != SearchType.SHARED_FILTER) && - (OCFileListFragment.FOLDER_LAYOUT_GRID == preferences.getFolderLayout(folder, lastLayout)) - } else { - OCFileListFragment.FOLDER_LAYOUT_GRID == preferences.getFolderLayout(folder, lastLayout) + private fun resolveLayoutType(): FolderLayout = when { + fragment.getCurrentSearchType() == SearchType.SHARED_FILTER -> FolderLayout.Shared + fragment.getCurrentSearchType() == SearchType.FAVORITE_SEARCH -> FolderLayout.Favorites + fragment.mFile == null || fragment.mFile.isRootDirectory -> FolderLayout.AllFiles + else -> FolderLayout.Child } + fun isGridViewPreferred(): Boolean = + OCFileListFragment.FOLDER_LAYOUT_GRID == preferences.getFolderLayout(resolveLayoutType()) + fun setLayoutViewMode() { - val isGrid = isGridViewPreferred(fragment.mFile) + val isGrid = isGridViewPreferred() if (isGrid) { switchToGridView() @@ -62,26 +56,24 @@ class FileListLayoutManager(private val fragment: OCFileListFragment, private va } fun setListAsPreferred() { - preferences.setFolderLayout(fragment.mFile, OCFileListFragment.FOLDER_LAYOUT_LIST) + preferences.setFolderLayout(resolveLayoutType(), OCFileListFragment.FOLDER_LAYOUT_LIST) switchToListView() } fun switchToListView() { if (fragment.isGridEnabled) { switchLayoutManager(false) - lastLayout = OCFileListFragment.FOLDER_LAYOUT_LIST } } fun setGridAsPreferred() { - preferences.setFolderLayout(fragment.mFile, OCFileListFragment.FOLDER_LAYOUT_GRID) + preferences.setFolderLayout(resolveLayoutType(), OCFileListFragment.FOLDER_LAYOUT_GRID) switchToGridView() } fun switchToGridView() { if (!fragment.isGridEnabled) { switchLayoutManager(true) - lastLayout = OCFileListFragment.FOLDER_LAYOUT_GRID } } diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java index 3a146c7e5f9c..92c8c1749821 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java +++ b/app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java @@ -468,7 +468,7 @@ protected void setAdapter(Bundle args) { boolean hideItemOptions = args != null && args.getBoolean(ARG_HIDE_ITEM_OPTIONS, false); boolean isGridViewPreferred = false; if (fileListLayoutManager != null) { - isGridViewPreferred = fileListLayoutManager.isGridViewPreferred(mFile); + isGridViewPreferred = fileListLayoutManager.isGridViewPreferred(); } mAdapter = new OCFileListAdapter( From 8880402d06a9f06b0f727b31f1f0f199f8e7a293 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Thu, 21 May 2026 12:17:06 +0300 Subject: [PATCH 12/19] introduce FolderLayout Signed-off-by: alperozturk96 --- .../client/preferences/AppPreferences.java | 26 ++------- .../preferences/AppPreferencesImpl.java | 55 +++++++++---------- .../ui/fragment/FileListLayoutManager.kt | 24 +++----- .../android/ui/fragment/FolderLayout.kt | 41 ++++++++++++++ 4 files changed, 79 insertions(+), 67 deletions(-) create mode 100644 app/src/main/java/com/owncloud/android/ui/fragment/FolderLayout.kt diff --git a/app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java b/app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java index 37f3d6552499..e2f76f05f6f5 100644 --- a/app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java +++ b/app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java @@ -14,6 +14,7 @@ import com.nextcloud.client.jobs.LogEntry; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.ui.fragment.FileListLayoutManager; +import com.owncloud.android.ui.fragment.FolderLayout; import com.owncloud.android.utils.FileSortOrder; import java.util.List; @@ -132,36 +133,19 @@ default void onDarkThemeModeChanged(DarkMode mode) { /** * Get preferred folder display type. * - * @param folder Folder + * @param layout FolderLayout * @return preference value, default is * {@link com.owncloud.android.ui.fragment.OCFileListFragment#FOLDER_LAYOUT_LIST} */ - String getFolderLayout(OCFile folder); + String getFolderLayout(FolderLayout layout); /** * Set preferred folder display type. * - * @param folder Folder which layout is being set or null for root folder + * @param layout FolderLayout which layout is being set * @param layoutName preference value */ - void setFolderLayout(@Nullable OCFile folder, String layoutName); - - /** - * Get preferred folder display type by view type. - * - * @param type The folder view type - * @return preference value, default is - * {@link com.owncloud.android.ui.fragment.OCFileListFragment#FOLDER_LAYOUT_LIST} - */ - String getFolderLayout(FileListLayoutManager.FolderLayout type); - - /** - * Set preferred folder display type by view type. - * - * @param type The folder view type - * @param layoutName preference value - */ - void setFolderLayout(FileListLayoutManager.FolderLayout type, String layoutName); + void setFolderLayout(@Nullable FolderLayout layout, String layoutName); /** * Saves the path where the user selected to do the last upload of a file shared from other app. diff --git a/app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java b/app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java index 0969649144d4..ddff28ef3701 100644 --- a/app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java +++ b/app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java @@ -28,7 +28,7 @@ import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.ui.activity.PassCodeActivity; import com.owncloud.android.ui.activity.SettingsActivity; -import com.owncloud.android.ui.fragment.FileListLayoutManager; +import com.owncloud.android.ui.fragment.FolderLayout; import com.owncloud.android.utils.FileSortOrder; import java.lang.reflect.Type; @@ -83,7 +83,6 @@ public final class AppPreferencesImpl implements AppPreferences { private static final String PREF__AUTO_UPLOAD_SPLIT_OUT = "autoUploadEntriesSplitOut"; private static final String PREF__AUTO_UPLOAD_INIT = "autoUploadInit"; private static final String PREF__FOLDER_SORT_ORDER = "folder_sort_order"; - private static final String PREF__FOLDER_LAYOUT = "folder_layout"; private static final String PREF__LOCK_TIMESTAMP = "lock_timestamp"; private static final String PREF__SHOW_MEDIA_SCAN_NOTIFICATIONS = "show_media_scan_notifications"; @@ -337,39 +336,37 @@ public String[] getPassCode() { } @Override - public String getFolderLayout(OCFile folder) { - return getFolderPreference(context, - userAccountManager.getUser(), - PREF__FOLDER_LAYOUT, - folder, - FOLDER_LAYOUT_LIST); - } + public String getFolderLayout(FolderLayout layout) { + if (layout instanceof FolderLayout.Child child) { + return getFolderPreference(context, + userAccountManager.getUser(), + layout.getKey(), + child.getFolder(), + FOLDER_LAYOUT_LIST); + } else { + User user = userAccountManager.getUser(); + if (user.isAnonymous()) { + return FOLDER_LAYOUT_LIST; + } - @Override - public void setFolderLayout(@Nullable OCFile folder, String layoutName) { - setFolderPreference(context, - userAccountManager.getUser(), - PREF__FOLDER_LAYOUT, - folder, - layoutName); + return preferences.getString(layout.getPrefKey(user), FOLDER_LAYOUT_LIST); + } } @Override - public String getFolderLayout(FileListLayoutManager.FolderLayout type) { - User user = userAccountManager.getUser(); - if (user.isAnonymous()) { - return FOLDER_LAYOUT_LIST; + public void setFolderLayout(FolderLayout layout, String layoutName) { + if (layout instanceof FolderLayout.Child child) { + setFolderPreference(context, + userAccountManager.getUser(), + child.getKey(), + child.getFolder(), + layoutName); + return; } - ArbitraryDataProvider dataProvider = new ArbitraryDataProviderImpl(context); - String value = dataProvider.getValue(user.getAccountName(), PREF__FOLDER_LAYOUT + "_" + type); - return value.isEmpty() ? FOLDER_LAYOUT_LIST : value; - } - @Override - public void setFolderLayout(FileListLayoutManager.FolderLayout type, String layoutName) { - User user = userAccountManager.getUser(); - ArbitraryDataProvider dataProvider = new ArbitraryDataProviderImpl(context); - dataProvider.storeOrUpdateKeyValue(user.getAccountName(), PREF__FOLDER_LAYOUT + "_" + type, layoutName); + preferences.edit() + .putString(layout.getPrefKey(userAccountManager.getUser()), layoutName) + .apply(); } @Override diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/FileListLayoutManager.kt b/app/src/main/java/com/owncloud/android/ui/fragment/FileListLayoutManager.kt index 35c48c5baa15..1f4375466bc7 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/FileListLayoutManager.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/FileListLayoutManager.kt @@ -21,28 +21,16 @@ import com.owncloud.android.utils.FileSortOrder class FileListLayoutManager(private val fragment: OCFileListFragment, private val preferences: AppPreferences) { - enum class FolderLayout { - Shared, - Favorites, - AllFiles, - Child - } - fun sortFiles(sortOrder: FileSortOrder?) { fragment.mSortButton?.setText(DisplayUtils.getSortOrderStringId(sortOrder)) sortOrder?.let { fragment.mAdapter.setSortOrder(fragment.mFile, it) } } - private fun resolveLayoutType(): FolderLayout = when { - fragment.getCurrentSearchType() == SearchType.SHARED_FILTER -> FolderLayout.Shared - fragment.getCurrentSearchType() == SearchType.FAVORITE_SEARCH -> FolderLayout.Favorites - fragment.mFile == null || fragment.mFile.isRootDirectory -> FolderLayout.AllFiles - else -> FolderLayout.Child + fun isGridViewPreferred(): Boolean { + val layout = FolderLayout.get(fragment.mFile, fragment.currentSearchType) + return preferences.getFolderLayout(layout) == OCFileListFragment.FOLDER_LAYOUT_GRID } - fun isGridViewPreferred(): Boolean = - OCFileListFragment.FOLDER_LAYOUT_GRID == preferences.getFolderLayout(resolveLayoutType()) - fun setLayoutViewMode() { val isGrid = isGridViewPreferred() @@ -56,7 +44,8 @@ class FileListLayoutManager(private val fragment: OCFileListFragment, private va } fun setListAsPreferred() { - preferences.setFolderLayout(resolveLayoutType(), OCFileListFragment.FOLDER_LAYOUT_LIST) + val layout = FolderLayout.get(fragment.mFile, fragment.currentSearchType) + preferences.setFolderLayout(layout, OCFileListFragment.FOLDER_LAYOUT_LIST) switchToListView() } @@ -67,7 +56,8 @@ class FileListLayoutManager(private val fragment: OCFileListFragment, private va } fun setGridAsPreferred() { - preferences.setFolderLayout(resolveLayoutType(), OCFileListFragment.FOLDER_LAYOUT_GRID) + val layout = FolderLayout.get(fragment.mFile, fragment.currentSearchType) + preferences.setFolderLayout(layout, OCFileListFragment.FOLDER_LAYOUT_GRID) switchToGridView() } diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/FolderLayout.kt b/app/src/main/java/com/owncloud/android/ui/fragment/FolderLayout.kt new file mode 100644 index 000000000000..65eec5c2d1e5 --- /dev/null +++ b/app/src/main/java/com/owncloud/android/ui/fragment/FolderLayout.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2026 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.owncloud.android.ui.fragment + +import com.nextcloud.client.account.User +import com.owncloud.android.datamodel.OCFile + +sealed class FolderLayout(val key: String) { + data object Shared : FolderLayout("shared_folder_layout") + data object Favorites : FolderLayout("favorite_folder_layout") + data object AllFiles : FolderLayout("all_files_folder_layout") + data class Child(val folder: OCFile) : FolderLayout("folder_layout") + + fun getPrefKey(user: User): String { + if (this is Child) { + return key + } + + return user.accountName + "_" + key + } + + companion object { + fun get(folder: OCFile?, searchType: SearchType): FolderLayout { + if (folder != null && folder.isFolder && !folder.isRootDirectory) { + return Child(folder) + } + + return when { + searchType == SearchType.SHARED_FILTER -> Shared + searchType == SearchType.FAVORITE_SEARCH -> Favorites + folder == null || folder.isRootDirectory -> AllFiles + else -> AllFiles + } + } + } +} From 1e4a6c406e009fdbcc6f0b25421b23afe2fdd706 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Thu, 21 May 2026 12:21:09 +0300 Subject: [PATCH 13/19] wip Signed-off-by: alperozturk96 --- .../java/com/owncloud/android/ui/fragment/FolderLayout.kt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/FolderLayout.kt b/app/src/main/java/com/owncloud/android/ui/fragment/FolderLayout.kt index 65eec5c2d1e5..efbb762b6c5a 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/FolderLayout.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/FolderLayout.kt @@ -30,10 +30,9 @@ sealed class FolderLayout(val key: String) { return Child(folder) } - return when { - searchType == SearchType.SHARED_FILTER -> Shared - searchType == SearchType.FAVORITE_SEARCH -> Favorites - folder == null || folder.isRootDirectory -> AllFiles + return when (searchType) { + SearchType.SHARED_FILTER -> Shared + SearchType.FAVORITE_SEARCH -> Favorites else -> AllFiles } } From 9ef33d0a2d0faf3d5335266cdd295755500cd2fd Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Thu, 21 May 2026 12:25:34 +0300 Subject: [PATCH 14/19] wip Signed-off-by: alperozturk96 --- .../client/preferences/AppPreferencesImpl.java | 2 ++ .../android/ui/fragment/FolderLayout.kt | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java b/app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java index ddff28ef3701..d2243e2080ae 100644 --- a/app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java +++ b/app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java @@ -338,6 +338,7 @@ public String[] getPassCode() { @Override public String getFolderLayout(FolderLayout layout) { if (layout instanceof FolderLayout.Child child) { + // keep existing logic for child directories return getFolderPreference(context, userAccountManager.getUser(), layout.getKey(), @@ -364,6 +365,7 @@ public void setFolderLayout(FolderLayout layout, String layoutName) { return; } + // only use new way for root shared, favorite and all files preferences.edit() .putString(layout.getPrefKey(userAccountManager.getUser()), layoutName) .apply(); diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/FolderLayout.kt b/app/src/main/java/com/owncloud/android/ui/fragment/FolderLayout.kt index efbb762b6c5a..cfa69a6493c7 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/FolderLayout.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/FolderLayout.kt @@ -10,12 +10,25 @@ package com.owncloud.android.ui.fragment import com.nextcloud.client.account.User import com.owncloud.android.datamodel.OCFile +/** + * AllFiles, Favorites and Shared represents only for root of them + * Child is valid for any child directory of all files, favorites or shared. + * + * Important: + * Do not change key to not lose data. + */ sealed class FolderLayout(val key: String) { - data object Shared : FolderLayout("shared_folder_layout") - data object Favorites : FolderLayout("favorite_folder_layout") data object AllFiles : FolderLayout("all_files_folder_layout") + data object Favorites : FolderLayout("favorite_folder_layout") + data object Shared : FolderLayout("shared_folder_layout") data class Child(val folder: OCFile) : FolderLayout("folder_layout") + /** + * Returns shared pref key only child uses key without user so that we dont lose + * previous information. + * + * User is needed since multiple account can be used. + */ fun getPrefKey(user: User): String { if (this is Child) { return key From 8d5d146f8d304226d36571efc4fcfa331a9eaac7 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Thu, 21 May 2026 12:30:22 +0300 Subject: [PATCH 15/19] wip Signed-off-by: alperozturk96 --- .../com/owncloud/android/ui/activity/FileDisplayActivity.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt index f6714f4477b9..77e826844250 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt @@ -2368,7 +2368,11 @@ class FileDisplayActivity : onRenameFileOperationFinishForFileFragment(leftFragment, renamedFile, currentUser) } - updateListOfFilesFragment() + val file = storageManager.getFileById(renamedFile.parentId) + if (file != null && file == getCurrentDir()) { + updateListOfFilesFragment() + } + refreshGalleryFragmentIfNeeded() fetchRecommendedFilesIfNeeded(ignoreETag = true, currentDir) } From 8162621668756e41a641e88c54b0e9e4475d3af5 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Thu, 21 May 2026 15:11:40 +0300 Subject: [PATCH 16/19] fix spotbugs Signed-off-by: alperozturk96 --- .../java/com/nextcloud/client/preferences/AppPreferences.java | 3 +-- .../com/nextcloud/client/preferences/AppPreferencesImpl.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java b/app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java index e2f76f05f6f5..4f4e85599480 100644 --- a/app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java +++ b/app/src/main/java/com/nextcloud/client/preferences/AppPreferences.java @@ -13,7 +13,6 @@ import com.nextcloud.appReview.AppReviewShownModel; import com.nextcloud.client.jobs.LogEntry; import com.owncloud.android.datamodel.OCFile; -import com.owncloud.android.ui.fragment.FileListLayoutManager; import com.owncloud.android.ui.fragment.FolderLayout; import com.owncloud.android.utils.FileSortOrder; @@ -145,7 +144,7 @@ default void onDarkThemeModeChanged(DarkMode mode) { * @param layout FolderLayout which layout is being set * @param layoutName preference value */ - void setFolderLayout(@Nullable FolderLayout layout, String layoutName); + void setFolderLayout(@NonNull FolderLayout layout, String layoutName); /** * Saves the path where the user selected to do the last upload of a file shared from other app. diff --git a/app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java b/app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java index d2243e2080ae..709f368080d8 100644 --- a/app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java +++ b/app/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java @@ -355,7 +355,7 @@ public String getFolderLayout(FolderLayout layout) { } @Override - public void setFolderLayout(FolderLayout layout, String layoutName) { + public void setFolderLayout(@NonNull FolderLayout layout, String layoutName) { if (layout instanceof FolderLayout.Child child) { setFolderPreference(context, userAccountManager.getUser(), From a9359c6b6f26d4c9359b3b9068f170c2cf94ebd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alper=20=C3=96zt=C3=BCrk?= <67455295+alperozturk96@users.noreply.github.com> Date: Thu, 21 May 2026 15:12:59 +0300 Subject: [PATCH 17/19] Potential fix for pull request finding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Signed-off-by: Alper Öztürk <67455295+alperozturk96@users.noreply.github.com> --- .../com/owncloud/android/ui/dialog/RenameFileDialogFragment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/owncloud/android/ui/dialog/RenameFileDialogFragment.kt b/app/src/main/java/com/owncloud/android/ui/dialog/RenameFileDialogFragment.kt index cc4de04cba0b..c420fab77023 100644 --- a/app/src/main/java/com/owncloud/android/ui/dialog/RenameFileDialogFragment.kt +++ b/app/src/main/java/com/owncloud/android/ui/dialog/RenameFileDialogFragment.kt @@ -181,7 +181,7 @@ class RenameFileDialogFragment : typedActivity()?.fileOperationsHelper?.renameFile(targetFile, newFileName) } else { fileDataStorageManager.addRenameFileOfflineOperation(targetFile, newFileName) - fda.refreshCurrentDirectory() + fda?.refreshCurrentDirectory() } } } From 08a9444cdfbb573c8e24232048eb546ea9235a19 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Thu, 21 May 2026 15:16:40 +0300 Subject: [PATCH 18/19] fix on remove file operation on finish Signed-off-by: alperozturk96 --- .../com/owncloud/android/ui/activity/FileDisplayActivity.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt index 77e826844250..769b279233ef 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt @@ -2184,6 +2184,11 @@ class FileDisplayActivity : return } + if (!result.isSuccess) { + Log_OC.e(TAG, "deletion failed") + return + } + val removedFile = operation.file tryStopPlaying(removedFile) val leftFragment = this.leftFragment From 30e8fceff90eff5a530e4de283f9c2353be83d78 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Fri, 22 May 2026 10:45:16 +0300 Subject: [PATCH 19/19] update file name Signed-off-by: alperozturk96 --- .../operations/RenameFileOperation.java | 6 ++- .../ui/activity/FileDisplayActivity.kt | 2 +- .../android/ui/adapter/OCFileListAdapter.java | 50 +++++++++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/owncloud/android/operations/RenameFileOperation.java b/app/src/main/java/com/owncloud/android/operations/RenameFileOperation.java index 93e60b156689..2e9241d37ae1 100644 --- a/app/src/main/java/com/owncloud/android/operations/RenameFileOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/RenameFileOperation.java @@ -91,8 +91,10 @@ protected RemoteOperationResult run(OwnCloudClient client) { if (result.isSuccess()) { if (file.isFolder()) { getStorageManager().moveLocalFile(file, newRemotePath, parent); - //saveLocalDirectory(); - + file.setFileName(newName); + if (!file.isEncrypted()) { + file.setDecryptedRemotePath(newRemotePath); + } } else { saveLocalFile(newRemotePath); } diff --git a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt index 769b279233ef..2fb3834aeb7e 100644 --- a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt +++ b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt @@ -2375,7 +2375,7 @@ class FileDisplayActivity : val file = storageManager.getFileById(renamedFile.parentId) if (file != null && file == getCurrentDir()) { - updateListOfFilesFragment() + fileListFragment?.adapter?.updateFile(renamedFile) } refreshGalleryFragmentIfNeeded() diff --git a/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java b/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java index 1a139f950da6..a7566c809d19 100644 --- a/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java +++ b/app/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java @@ -81,6 +81,7 @@ import java.util.Locale; import java.util.Set; import java.util.UUID; +import java.util.stream.IntStream; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -1122,4 +1123,53 @@ public void removeFile(@NonNull OCFile file) { notifyDataSetChanged(); } } + + @SuppressLint("NotifyDataSetChanged") + public void updateFile(@NonNull OCFile updatedFile) { + long fileId = updatedFile.getFileId(); + + IntStream.range(0, mFilesAll.size()) + .filter(i -> mFilesAll.get(i).getFileId() == fileId) + .findFirst() + .ifPresent(i -> mFilesAll.set(i, updatedFile)); + + int oldIndex = IntStream.range(0, mFiles.size()) + .filter(i -> mFiles.get(i).getFileId() == fileId) + .findFirst() + .orElse(-1); + if (oldIndex == -1) return; + + mFiles.remove(oldIndex); + mFiles.add(updatedFile); + + FileSortOrder currentSortOrder = preferences.getSortOrderByFolder(currentDirectory); + if (searchType == SearchType.SHARED_FILTER) { + mFiles.sort((o1, o2) -> Long.compare(o2.getFirstShareTimestamp(), o1.getFirstShareTimestamp())); + } else { + boolean foldersBeforeFiles = preferences.isSortFoldersBeforeFiles(); + boolean favoritesFirst = preferences.isSortFavoritesFirst(); + mFiles = currentSortOrder.sortCloudFiles(mFiles, foldersBeforeFiles, favoritesFirst); + } + + int newIndex = mFiles.indexOf(updatedFile); + if (newIndex == -1) { + notifyDataSetChanged(); + return; + } + + int headerOffset = shouldShowHeader() ? 1 : 0; + int oldAdapterPos = oldIndex + headerOffset; + int newAdapterPos = newIndex + headerOffset; + + if (oldAdapterPos != newAdapterPos) { + notifyItemMoved(oldAdapterPos, newAdapterPos); + } + notifyItemChanged(newAdapterPos); + + if (shouldShowRecommendedFiles() && recommendedFilesAdapter != null && updatedFile.isRecommendedFile()) { + int pos = recommendedFilesAdapter.getItemPosition(updatedFile); + if (pos != -1) recommendedFilesAdapter.notifyItemChanged(pos); + } + } + }