浏览代码

updatePathsIfParentPathMatches

Signed-off-by: alperozturk <alper_ozturk@proton.me>
alperozturk 10 月之前
父节点
当前提交
501f139716

+ 131 - 0
app/src/androidTest/java/com/nextcloud/extensions/OfflineOperationExtensionTests.kt

@@ -0,0 +1,131 @@
+/*
+ * Nextcloud - Android Client
+ *
+ * SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+package com.nextcloud.extensions
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.nextcloud.client.database.entity.OfflineOperationEntity
+import com.nextcloud.utils.extensions.getParentPathFromPath
+import com.nextcloud.utils.extensions.updatePath
+import com.nextcloud.utils.extensions.updatePathsIfParentPathMatches
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNull
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class OfflineOperationExtensionTests {
+
+    /*
+      private val entity = OfflineOperationEntity(
+        1,
+        null,
+        null,
+        OfflineOperationType.CreateFolder,
+        "/Folder/Folder2/Folder3/",
+        "Folder",
+        null
+    )
+
+    @Test
+    fun testGetParentPathFromPath() {
+        assert(entity.getParentPathFromPath() == "/Folder/")
+    }
+
+    @Test
+    fun testUpdatePath() {
+        assert(entity.updatePath("/MaxPa/") == "/MaxPa/Folder2/Folder3/")
+    }
+
+    @Test
+    fun testUpdatePathsIfParentPathMatches() {
+        entity.path = "/MaxPa/Folder2/Folder3/"
+        val oldPath = "/Folder/Folder2/Folder3/"
+        assert(entity.updatePathsIfParentPathMatches(oldPath, "/MaxPa/") == "/MaxPa/Folder2/Folder3/")
+    }
+
+     */
+
+    @Test
+    fun testUpdatePathsIfParentPathMatches() {
+        val entity1 = OfflineOperationEntity(path = "/abc/def/file1/")
+        val entity2 = OfflineOperationEntity(path = "/xyz/file2/")
+
+        val updatedPath1 = entity1.updatePathsIfParentPathMatches(entity1.path, "/newAbc/")
+        val updatedPath2 = entity2.updatePathsIfParentPathMatches(entity2.path, "/newAbc/")
+
+        assertEquals("/newAbc/def/file1/", updatedPath1)
+        assertEquals("/newAbc/file2/", updatedPath2)
+    }
+
+    @Test
+    fun testUpdatePathsIfParentPathMatchesWithNullInputs() {
+        val entity = OfflineOperationEntity(path = "/abc/def/file/")
+
+        val result1 = entity.updatePathsIfParentPathMatches(null, "/newPath/")
+        val result2 = entity.updatePathsIfParentPathMatches("/oldPath/", null)
+
+        assertNull(result1)
+        assertNull(result2)
+    }
+
+    @Test
+    fun testUpdatePath() {
+        val entity = OfflineOperationEntity(path = "/abc/def/file/")
+        val newPath = entity.updatePath("/newAbc/")
+        assertEquals("/newAbc/def/file/", newPath)
+    }
+
+    @Test
+    fun testUpdatePathWithNullInput() {
+        val entity = OfflineOperationEntity(path = "/abc/def/file/")
+        val newPath = entity.updatePath(null)
+        assertNull(newPath)
+    }
+
+    @Test
+    fun testGetParentPathFromPath() {
+        val entity = OfflineOperationEntity(path = "/abc/def/file/")
+        val parentPath = entity.getParentPathFromPath()
+        assertEquals("/abc/", parentPath)
+    }
+
+    @Test
+    fun testGetParentPathFromPathWithRootPath() {
+        val entity = OfflineOperationEntity(path = "/")
+        val parentPath = entity.getParentPathFromPath()
+        assertEquals("//", parentPath)
+    }
+
+    @Test
+    fun testGetParentPathFromPathWithEmptyString() {
+        val entity = OfflineOperationEntity(path = "")
+        val parentPath = entity.getParentPathFromPath()
+        assertEquals("//", parentPath)
+    }
+
+    @Test
+    fun testGetParentPathFromPathWithNullPath() {
+        val entity = OfflineOperationEntity(path = null)
+        val parentPath = entity.getParentPathFromPath()
+        assertNull(parentPath)
+    }
+
+    @Test
+    fun testUpdatePathWithEmptyPath() {
+        val entity = OfflineOperationEntity(path = "")
+        val newPath = entity.updatePath("/newAbc/")
+        assertNull(newPath)
+    }
+
+    @Test
+    fun testUpdatePathsIfParentPathMatchesWithSingleDirectoryPath() {
+        val entity = OfflineOperationEntity(path = "/abc/")
+        val updatedPath = entity.updatePathsIfParentPathMatches(entity.path, "/newAbc/")
+        assertEquals("/newAbc/", updatedPath)
+    }
+}

+ 4 - 0
app/src/androidTest/java/com/owncloud/android/files/services/FileUploaderIT.kt

@@ -34,6 +34,10 @@ abstract class FileUploaderIT : AbstractOnServerIT() {
     private var uploadsStorageManager: UploadsStorageManager? = null
 
     private val connectivityServiceMock: ConnectivityService = object : ConnectivityService {
+        override fun isNetworkAndServerAvailable(): Boolean {
+            return false
+        }
+
         override fun isConnected(): Boolean {
             return false
         }

+ 3 - 0
app/src/main/java/com/nextcloud/client/database/dao/OfflineOperationDao.kt

@@ -36,4 +36,7 @@ interface OfflineOperationDao {
 
     @Query("SELECT * FROM offline_operations WHERE offline_operations_path = :path LIMIT 1")
     fun getByPath(path: String): OfflineOperationEntity?
+
+    @Query("UPDATE offline_operations SET offline_operations_parent_path = :parentPath WHERE _id = :id")
+    fun updateParentPathById(id: Int, parentPath: String)
 }

+ 10 - 21
app/src/main/java/com/nextcloud/client/jobs/offlineOperations/OfflineOperationsWorker.kt

@@ -114,8 +114,16 @@ class OfflineOperationsWorker(
         Log_OC.d(TAG, "$logMessage path: ${operation.path}, type: ${operation.type}")
 
         if (result.isSuccess) {
-            updateNextOperationsParentPaths(operations, operation)
-            fileDataStorageManager.offlineOperationDao.delete(operation)
+            fileDataStorageManager.offlineOperationDao.run {
+                operation.id?.let { id ->
+                    operation.path?.let { path ->
+                        updateParentPathById(operation.id, path)
+                    }
+                }
+
+                delete(operation)
+            }
+
             notificationManager.update(operations.size, currentOperationIndex, operation.filename ?: "")
         } else {
             val excludedErrorCodes = listOf(RemoteOperationResult.ResultCode.FOLDER_ALREADY_EXISTS)
@@ -125,23 +133,4 @@ class OfflineOperationsWorker(
             }
         }
     }
-
-    private fun updateNextOperationsParentPaths(
-        operations: List<OfflineOperationEntity>,
-        currentOperation: OfflineOperationEntity
-    ) {
-        operations.forEach { nextOperation ->
-            val nextOperationParentPath = getParentPath(nextOperation.path ?: "")
-            if (nextOperationParentPath == currentOperation.path) {
-                nextOperation.parentPath = currentOperation.path
-                fileDataStorageManager.offlineOperationDao.update(nextOperation)
-            }
-        }
-    }
-
-    private fun getParentPath(path: String): String {
-        val trimmedPath = path.trim('/')
-        val firstDir = trimmedPath.split('/').firstOrNull() ?: ""
-        return "/$firstDir/"
-    }
 }

+ 24 - 0
app/src/main/java/com/nextcloud/utils/extensions/DateExtensions.kt

@@ -0,0 +1,24 @@
+/*
+ * Nextcloud - Android Client
+ *
+ * SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+package com.nextcloud.utils.extensions
+
+import android.annotation.SuppressLint
+import java.text.SimpleDateFormat
+import java.util.Date
+
+enum class DateFormatPattern(val pattern: String) {
+    /**
+     * e.g. 10.11.2024 - 12:44
+     */
+    FullDateWithHours("dd.MM.yyyy - HH:mm")
+}
+
+@SuppressLint("SimpleDateFormat")
+fun Date.currentDateRepresentation(formatPattern: DateFormatPattern): String {
+    return SimpleDateFormat(formatPattern.pattern).format(this)
+}

+ 61 - 0
app/src/main/java/com/nextcloud/utils/extensions/OfflineOperationExtensions.kt

@@ -0,0 +1,61 @@
+/*
+ * Nextcloud - Android Client
+ *
+ * SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+package com.nextcloud.utils.extensions
+
+import com.nextcloud.client.database.dao.OfflineOperationDao
+import com.nextcloud.client.database.entity.OfflineOperationEntity
+
+fun OfflineOperationDao.updatePathsIfParentPathMatches(oldPath: String?, newTopDir: String?) {
+    if (oldPath.isNullOrEmpty() || newTopDir.isNullOrEmpty()) return
+
+    getAll().forEach {
+        val newPath = it.updatePathsIfParentPathMatches(oldPath, newTopDir)
+        if (newPath != it.path) {
+
+            // TODO add parent path so it can upload
+            it.path = newPath
+            update(it)
+        }
+    }
+}
+
+fun OfflineOperationEntity.updatePathsIfParentPathMatches(oldPath: String?, newTopDir: String?): String? {
+    if (oldPath.isNullOrEmpty() || newTopDir.isNullOrEmpty()) return null
+
+    val topDir = getParentPathFromPath()
+    val oldTopDir = oldPath.getParentPathFromPath()
+    return if (topDir == oldTopDir) {
+        updatePath(newTopDir)
+    } else {
+        path
+    }
+}
+
+fun OfflineOperationEntity.updatePath(newParentPath: String?): String? {
+    if (newParentPath.isNullOrEmpty() || path.isNullOrEmpty()) return null
+
+    val segments = path!!.trim('/').split('/').toMutableList()
+
+    if (segments.size == 1) {
+        return newParentPath
+    }
+
+    segments.removeAt(0)
+
+    return newParentPath + segments.joinToString(separator = "/") + "/"
+}
+
+fun OfflineOperationEntity.getParentPathFromPath(): String? {
+    return path?.getParentPathFromPath()
+}
+
+private fun String?.getParentPathFromPath(): String {
+    val trimmedPath = this?.trim('/')
+    val firstDir = trimmedPath?.split('/')?.firstOrNull() ?: ""
+    return "/$firstDir/"
+}