From d6414c044b30de08e6a185fd61a7648578a2bd11 Mon Sep 17 00:00:00 2001 From: alperozturk96 Date: Fri, 4 Sep 2026 16:11:57 +0200 Subject: [PATCH] feat(okhttp-client): read folder operation Signed-off-by: alperozturk96 --- .../owncloud/android/AbstractOnServerIT.java | 8 ++-- .../OfflineOperationsWorker.kt | 16 ++++---- .../operations/CreateFolderOperation.java | 28 +++++++++----- .../operations/RefreshFolderOperation.java | 15 ++++++-- .../SynchronizeFolderOperation.java | 37 ++++++++++++++----- .../android/ui/fragment/FolderEncryption.kt | 3 +- gradle.properties | 4 +- gradle/libs.versions.toml | 2 +- settings.gradle.kts | 5 ++- 9 files changed, 76 insertions(+), 42 deletions(-) diff --git a/app/src/androidTest/java/com/owncloud/android/AbstractOnServerIT.java b/app/src/androidTest/java/com/owncloud/android/AbstractOnServerIT.java index a1924f00e162..d7d5c0285347 100644 --- a/app/src/androidTest/java/com/owncloud/android/AbstractOnServerIT.java +++ b/app/src/androidTest/java/com/owncloud/android/AbstractOnServerIT.java @@ -131,12 +131,10 @@ private static boolean isFolder(RemoteFile file) { } public static void deleteAllFilesOnServer() { - var result = new ReadFolderRemoteOperation("/").execute(client); + var result = new ReadFolderRemoteOperation("/").execute(nextcloudClient); assertTrue(result.getLogMessage(targetContext), result.isSuccess()); - for (Object object : result.getData()) { - RemoteFile remoteFile = (RemoteFile) object; - + for (RemoteFile remoteFile : result.getResultData()) { if (!Objects.equals(remoteFile.getRemotePath(), "/")) { if (remoteFile.isEncrypted()) { ToggleEncryptionRemoteOperation operation = new ToggleEncryptionRemoteOperation(remoteFile.getLocalId(), @@ -144,7 +142,7 @@ public static void deleteAllFilesOnServer() { false); boolean operationResult = operation - .execute(client) + .execute(nextcloudClient) .isSuccess(); if (!operationResult && isFolder(remoteFile)) { diff --git a/app/src/main/java/com/nextcloud/client/jobs/offlineOperations/OfflineOperationsWorker.kt b/app/src/main/java/com/nextcloud/client/jobs/offlineOperations/OfflineOperationsWorker.kt index 8a1b966031ad..94f2e34e4012 100644 --- a/app/src/main/java/com/nextcloud/client/jobs/offlineOperations/OfflineOperationsWorker.kt +++ b/app/src/main/java/com/nextcloud/client/jobs/offlineOperations/OfflineOperationsWorker.kt @@ -280,17 +280,15 @@ class OfflineOperationsWorker( private fun getRemoteFile(remotePath: String): RemoteFile? { val mimeType = MimeTypeUtil.getMimeTypeFromPath(remotePath) val isFolder = MimeTypeUtil.isFolder(mimeType) - val client = ClientFactoryImpl(context).create(user) - val result = if (isFolder) { - ReadFolderRemoteOperation(remotePath).execute(client) - } else { - ReadFileRemoteOperation(remotePath).execute(client) - } - return if (result.isSuccess) { - result.data[0] as? RemoteFile + return if (isFolder) { + val nextcloudClient = ClientFactoryImpl(context).createNextcloudClient(user) + val result = ReadFolderRemoteOperation(remotePath).execute(nextcloudClient) + if (result.isSuccess) result.resultData.getOrNull(0) else null } else { - null + val client = ClientFactoryImpl(context).create(user) + val result = ReadFileRemoteOperation(remotePath).execute(client) + if (result.isSuccess) result.data[0] as? RemoteFile else null } } diff --git a/app/src/main/java/com/owncloud/android/operations/CreateFolderOperation.java b/app/src/main/java/com/owncloud/android/operations/CreateFolderOperation.java index 6c57e9965b23..52e8820880b2 100644 --- a/app/src/main/java/com/owncloud/android/operations/CreateFolderOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/CreateFolderOperation.java @@ -16,6 +16,7 @@ import android.util.Pair; import com.nextcloud.client.account.User; +import com.nextcloud.common.NextcloudClient; import com.nextcloud.utils.e2ee.E2ECounterHelper; import com.nextcloud.utils.e2ee.E2EVersionHelper; import com.nextcloud.utils.extensions.OCFileExtensionsKt; @@ -30,6 +31,8 @@ import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedFile; import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedFolderMetadataFile; import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.common.OwnCloudClientFactory; +import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.operations.OnRemoteOperationListener; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; @@ -208,8 +211,9 @@ private RemoteOperationResult encryptedCreateV1(OCFile parent, OwnCloudClient cl } } + NextcloudClient nextcloudClient = OwnCloudClientFactory.createNextcloudClient(user, context); final var remoteFolderOperationResult = new ReadFolderRemoteOperation(encryptedRemotePath) - .execute(client); + .execute(nextcloudClient); if (remoteFolderOperationResult.isSuccess() && remoteFolderOperationResult.getData().get(0) instanceof RemoteFile remoteFile) { createdRemoteFolder = remoteFile; @@ -220,7 +224,7 @@ private RemoteOperationResult encryptedCreateV1(OCFile parent, OwnCloudClient cl newDir.getLocalId(), newDir.getRemotePath(), true) - .execute(client); + .execute(nextcloudClient); if (!encryptionOperationResult.isSuccess()) { throw new RuntimeException("Error creating encrypted subfolder!"); @@ -360,8 +364,9 @@ private RemoteOperationResult encryptedCreateV2(OCFile parent, OwnCloudClient cl throw new RuntimeException("Could not unlock folder!"); } + NextcloudClient nextcloudClient = OwnCloudClientFactory.createNextcloudClient(user, context); final var remoteFolderOperationResult = new ReadFolderRemoteOperation(encryptedRemotePath) - .execute(client); + .execute(nextcloudClient); if (remoteFolderOperationResult.isSuccess() && remoteFolderOperationResult.getData().get(0) instanceof RemoteFile remoteFile) { createdRemoteFolder = remoteFile; @@ -372,7 +377,7 @@ private RemoteOperationResult encryptedCreateV2(OCFile parent, OwnCloudClient cl newDir.getLocalId(), newDir.getRemotePath(), true) - .execute(client); + .execute(nextcloudClient); if (!encryptionOperationResult.isSuccess()) { throw new RuntimeException("Error creating encrypted subfolder!"); @@ -517,12 +522,17 @@ private RemoteOperationResult normalCreate(OwnCloudClient client) { final var result = new CreateFolderRemoteOperation(remotePath, true).execute(client); if (result.isSuccess()) { - final var remoteFolderOperationResult = new ReadFolderRemoteOperation(remotePath) - .execute(client); + try { + NextcloudClient nextcloudClient = OwnCloudClientFactory.createNextcloudClient(user, context); + final var remoteFolderOperationResult = new ReadFolderRemoteOperation(remotePath) + .execute(nextcloudClient); - if (remoteFolderOperationResult.isSuccess() && - remoteFolderOperationResult.getData().get(0) instanceof RemoteFile remoteFile) { - createdRemoteFolder = remoteFile; + if (remoteFolderOperationResult.isSuccess() && + remoteFolderOperationResult.getData().get(0) instanceof RemoteFile remoteFile) { + createdRemoteFolder = remoteFile; + } + } catch (AccountUtils.AccountNotFoundException | NullPointerException e) { + Log_OC.e(TAG, "Could not create NextcloudClient to read created folder " + remotePath, e); } saveFolderInDB(); diff --git a/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java b/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java index 85af19137bc7..f6a29a41045b 100644 --- a/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java @@ -278,7 +278,7 @@ protected RemoteOperationResult run(OwnCloudClient client) { if (result.isSuccess()) { if (mRemoteFolderChanged) { - result = fetchAndSyncRemoteFolder(client); + result = fetchAndSyncRemoteFolder(); } else { Log_OC.d(TAG, "💾 Remote folder is not changed, getting folder content from database"); mChildren = fileDataStorageManager.getFolderContent(mLocalFolder, false); @@ -461,9 +461,18 @@ private RemoteOperationResult checkForChanges(OwnCloudClient client) { return result; } - private RemoteOperationResult fetchAndSyncRemoteFolder(OwnCloudClient client) { + private RemoteOperationResult fetchAndSyncRemoteFolder() { String remotePath = mLocalFolder.getRemotePath(); - RemoteOperationResult result = new ReadFolderRemoteOperation(remotePath).execute(client); + + NextcloudClient nextcloudClient; + try { + nextcloudClient = OwnCloudClientFactory.createNextcloudClient(user, mContext); + } catch (AccountUtils.AccountNotFoundException | NullPointerException e) { + Log_OC.e(TAG, "Could not create NextcloudClient to fetch " + remotePath, e); + return new RemoteOperationResult<>(e); + } + + RemoteOperationResult result = new ReadFolderRemoteOperation(remotePath).execute(nextcloudClient); Log_OC.d(TAG, "⬇ eTag is changed or ignored, fetching folder: " + user.getAccountName() + remotePath); if (result.isSuccess()) { diff --git a/app/src/main/java/com/owncloud/android/operations/SynchronizeFolderOperation.java b/app/src/main/java/com/owncloud/android/operations/SynchronizeFolderOperation.java index 57edd26105c3..47da6d0d0253 100644 --- a/app/src/main/java/com/owncloud/android/operations/SynchronizeFolderOperation.java +++ b/app/src/main/java/com/owncloud/android/operations/SynchronizeFolderOperation.java @@ -17,12 +17,15 @@ import com.nextcloud.client.account.User; import com.nextcloud.client.jobs.download.FileDownloadHelper; import com.nextcloud.client.jobs.folderDownload.FolderDownloadWorkerNotificationManager; +import com.nextcloud.common.NextcloudClient; import com.nextcloud.utils.extensions.ExtensionsKt; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.e2e.v1.decrypted.DecryptedFolderMetadataFileV1; import com.owncloud.android.datamodel.e2e.v2.decrypted.DecryptedFolderMetadataFile; import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.common.OwnCloudClientFactory; +import com.owncloud.android.lib.common.accounts.AccountUtils; import com.owncloud.android.lib.common.operations.OperationCancelledException; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; @@ -146,13 +149,13 @@ protected RemoteOperationResult run(OwnCloudClient client) { if (result.isSuccess()) { if (mRemoteFolderChanged || syncAll) { - result = fetchAndSyncRemoteFolder(client); + result = fetchAndSyncRemoteFolder(); } else { prepareOpsFromLocalKnowledge(); } if (result.isSuccess()) { - syncContents(client); + syncContents(); } } @@ -208,13 +211,21 @@ private RemoteOperationResult checkForChanges(OwnCloudClient client) throws Oper } - private RemoteOperationResult fetchAndSyncRemoteFolder(OwnCloudClient client) throws OperationCancelledException { + private RemoteOperationResult fetchAndSyncRemoteFolder() throws OperationCancelledException { if (mCancellationRequested.get()) { throw new OperationCancelledException(); } + NextcloudClient nextcloudClient; + try { + nextcloudClient = OwnCloudClientFactory.createNextcloudClient(user, mContext); + } catch (AccountUtils.AccountNotFoundException | NullPointerException e) { + Log_OC.e(TAG, "Could not create NextcloudClient to synchronize " + mRemotePath, e); + return new RemoteOperationResult<>(e); + } + ReadFolderRemoteOperation operation = new ReadFolderRemoteOperation(mRemotePath); - var result = operation.execute(client); + var result = operation.execute(nextcloudClient); Log_OC.d(TAG, "Synchronizing " + user.getAccountName() + mRemotePath); Log_OC.d(TAG, "Synchronizing remote id" + mLocalFolder.getRemoteId()); @@ -442,21 +453,27 @@ private void prepareOpsFromLocalKnowledge() throws OperationCancelledException { } } - private void syncContents(OwnCloudClient client) throws OperationCancelledException { + private void syncContents() throws OperationCancelledException { startDirectDownloads(); startContentSynchronizations(mFilesToSyncContents); - updateETag(client); + updateETag(); } /** * Updates the eTag of the local folder after a successful synchronization. * This ensures that any changes to local files, which may alter the eTag, are correctly reflected. - * - * @param client the OwnCloudClient instance used to execute remote operations. */ - private void updateETag(OwnCloudClient client) { + private void updateETag() { + NextcloudClient nextcloudClient; + try { + nextcloudClient = OwnCloudClientFactory.createNextcloudClient(user, mContext); + } catch (AccountUtils.AccountNotFoundException | NullPointerException e) { + Log_OC.e(TAG, "Could not create NextcloudClient to update eTag of " + mRemotePath, e); + return; + } + ReadFolderRemoteOperation operation = new ReadFolderRemoteOperation(mRemotePath); - final var result = operation.execute(client); + final var result = operation.execute(nextcloudClient); if (!result.isSuccess()) { Log_OC.w(TAG, "Cannot update eTag, read folder operation is failed"); return; diff --git a/app/src/main/java/com/owncloud/android/ui/fragment/FolderEncryption.kt b/app/src/main/java/com/owncloud/android/ui/fragment/FolderEncryption.kt index 9823ec26effd..7fb9e202e42d 100644 --- a/app/src/main/java/com/owncloud/android/ui/fragment/FolderEncryption.kt +++ b/app/src/main/java/com/owncloud/android/ui/fragment/FolderEncryption.kt @@ -49,9 +49,10 @@ class FolderEncryption(private val fragment: OCFileListFragment) { val publicKey = provider.getValue(user, EncryptionUtils.PUBLIC_KEY) val privateKey = provider.getValue(user, EncryptionUtils.PRIVATE_KEY) val client = fragment.clientFactory.create(user) + val nextcloudClient = fragment.clientFactory.createNextcloudClient(user) val result = ToggleEncryptionRemoteOperation(localId, remotePath, shouldBeEncrypted) - .execute(client) + .execute(nextcloudClient) return@withContext when { result.isSuccess -> onToggleSuccess( diff --git a/gradle.properties b/gradle.properties index 91f3dedc1c10..aa2eb9ed75c0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -23,8 +23,8 @@ org.gradle.configuration-cache=true org.gradle.workers.max=4 # Needed for local libs -# org.gradle.dependency.verification=off -# systemProp.org.gradle.internal.publish.checksums.insecure=true +org.gradle.dependency.verification=off +systemProp.org.gradle.internal.publish.checksums.insecure=true # Enabled parallel sync for Gradle 9.4+ org.gradle.tooling.parallel=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2858e905d32a..83b71cb007cc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ androidGifDrawableVersion = "1.2.32" androidImageCropperVersion = "4.7.0" androidLibraryVersion ="94372d7cbb8efe1c779ab8c2244a61510efafb28" androidOpensslVersion = "3.5.6" -androidPluginVersion = "9.3.2" +androidPluginVersion = "9.4.0" androidsvgVersion = "1.4" androidxTestVersion = "1.7.0" annotationVersion = "1.10.0" diff --git a/settings.gradle.kts b/settings.gradle.kts index a5b397949b05..e372b782329d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -43,14 +43,15 @@ dependencyResolutionManagement { /* Needed for local android library + +*/ + includeBuild("../android_library") { dependencySubstitution { substitute(module("com.github.nextcloud:android-library")) .using(project(":library")) } } -*/ - /* Needed for local android common library