From 58bc0e72bc7665b47f58af6bb94f4f55232f672f Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Wed, 8 Jan 2025 09:32:34 +0100 Subject: [PATCH 01/11] tag color Signed-off-by: tobiasKaminsky --- .../com/owncloud/android/lib/common/network/Tag.kt | 10 ++++++++++ .../owncloud/android/lib/common/network/WebdavEntry.kt | 3 ++- .../android/lib/common/network/WebdavUtils.java | 1 + 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 library/src/main/java/com/owncloud/android/lib/common/network/Tag.kt diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/Tag.kt b/library/src/main/java/com/owncloud/android/lib/common/network/Tag.kt new file mode 100644 index 0000000000..f49219e941 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/common/network/Tag.kt @@ -0,0 +1,10 @@ +/* + * Nextcloud Android Library + * + * SPDX-FileCopyrightText: 2025 Your Name + * SPDX-License-Identifier: MIT + */ + +package com.owncloud.android.lib.common.network + +data class Tag (val name: String, val color: String) diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt index 978a3e9651..60a3d1730f 100644 --- a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt +++ b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt @@ -90,7 +90,7 @@ class WebdavEntry constructor( private set var lockToken: String? = null private set - var tags = arrayOfNulls(0) + var tags = arrayOfNulls(0) var imageDimension: ImageDimension? = null var geoLocation: GeoLocation? = null var hidden = false @@ -659,6 +659,7 @@ class WebdavEntry constructor( const val EXTENDED_PROPERTY_LOCK_TIMEOUT = "lock-timeout" const val EXTENDED_PROPERTY_LOCK_TOKEN = "lock-token" const val EXTENDED_PROPERTY_SYSTEM_TAGS = "system-tags" + const val EXTENDED_PROPERTY_SYSTEM_TAGS_COLOR = "color" // v27 const val EXTENDED_PROPERTY_METADATA_SIZE = "file-metadata-size" diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavUtils.java b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavUtils.java index e15e02b0f8..e83afbbcd9 100644 --- a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavUtils.java +++ b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavUtils.java @@ -117,6 +117,7 @@ public static DavPropertyNameSet getAllPropSet() { propSet.add(WebdavEntry.EXTENDED_PROPERTY_LOCK_TIMEOUT, ncNamespace); propSet.add(WebdavEntry.EXTENDED_PROPERTY_LOCK_TOKEN, ncNamespace); propSet.add(WebdavEntry.EXTENDED_PROPERTY_SYSTEM_TAGS, ncNamespace); + propSet.add(WebdavEntry.EXTENDED_PROPERTY_SYSTEM_TAGS_COLOR, ncNamespace); propSet.add(WebdavEntry.EXTENDED_PROPERTY_METADATA_SIZE, ncNamespace); propSet.add(WebdavEntry.EXTENDED_PROPERTY_METADATA_GPS, ncNamespace); propSet.add(WebdavEntry.EXTENDED_PROPERTY_METADATA_PHOTOS_SIZE, ncNamespace); From b341d8d3dfa04945583f7f8250a78856bb7e6bbc Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Wed, 8 Jan 2025 09:35:37 +0100 Subject: [PATCH 02/11] tag color Signed-off-by: tobiasKaminsky --- .../main/java/com/owncloud/android/lib/common/network/Tag.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/Tag.kt b/library/src/main/java/com/owncloud/android/lib/common/network/Tag.kt index f49219e941..49f8b52e26 100644 --- a/library/src/main/java/com/owncloud/android/lib/common/network/Tag.kt +++ b/library/src/main/java/com/owncloud/android/lib/common/network/Tag.kt @@ -1,7 +1,8 @@ /* * Nextcloud Android Library * - * SPDX-FileCopyrightText: 2025 Your Name + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-FileCopyrightText: 2025 Tobias Kaminsky * SPDX-License-Identifier: MIT */ From 867a12b9e2c4d84be09030b4d7eca1a805f4cc97 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 8 Jan 2025 10:01:11 +0100 Subject: [PATCH 03/11] parse tags Signed-off-by: alperozturk --- .../android/lib/common/network/WebdavEntry.kt | 33 ++++++++++--------- .../lib/resources/files/model/RemoteFile.kt | 3 +- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt index 60a3d1730f..ed736f974e 100644 --- a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt +++ b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt @@ -393,23 +393,20 @@ class WebdavEntry constructor( } prop = propSet[EXTENDED_PROPERTY_SYSTEM_TAGS, ncNamespace] - if (prop != null && prop.value != null) { - if (prop.value is ArrayList<*>) { - val list = prop.value as ArrayList<*> - val tempList: MutableList = ArrayList(list.size) - for (i in list.indices) { - val element = list[i] as Element - tempList.add(element.firstChild.textContent) + if (prop?.value != null) { + tags = when (prop.value) { + is ArrayList<*> -> (prop.value as ArrayList<*>) + .filterIsInstance() + .map { parseTag(it) } + .toTypedArray() + + is Element -> { + val element = (prop.value as Element) + val tag = parseTag(element) + arrayOf(tag) } - tags = tempList.toTypedArray() - } else { - // single item or empty - val element = prop.value as Element - val value = element.firstChild.textContent - if (value != null) { - tags = arrayOf(value) - } + else -> emptyArray() } } @@ -485,6 +482,12 @@ class WebdavEntry constructor( } } + private fun parseTag(element: Element): Tag { + val name = element.firstChild.textContent + val color = element.getAttribute("nc:color") + return Tag(name, color) + } + private fun parseLockProperties( ncNamespace: Namespace, propSet: DavPropertySet diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt index 052ce8e14a..282a79d1bb 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt @@ -8,6 +8,7 @@ package com.owncloud.android.lib.resources.files.model import android.os.Parcel import android.os.Parcelable +import com.owncloud.android.lib.common.network.Tag import com.nextcloud.android.lib.resources.files.FileDownloadLimit import com.owncloud.android.lib.common.network.WebdavEntry import com.owncloud.android.lib.common.network.WebdavEntry.MountType @@ -53,7 +54,7 @@ class RemoteFile : var lockOwnerEditor: String? = null var lockTimeout: Long = 0 var lockToken: String? = null - var tags: Array? = null + var tags: Array? = null var imageDimension: ImageDimension? = null var geoLocation: GeoLocation? = null var hidden = false From 57da6f04cf3c9fcdc6755f825a2827f93ba320f9 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Wed, 8 Jan 2025 10:51:49 +0100 Subject: [PATCH 04/11] distinguish tag and system tag Signed-off-by: alperozturk --- .../com/owncloud/android/lib/common/network/Tag.kt | 11 ----------- .../android/lib/common/network/WebdavEntry.kt | 9 +++++---- .../android/lib/resources/files/model/RemoteFile.kt | 3 ++- .../android/lib/resources/systemTag/SystemTag.kt | 10 ++++++++++ 4 files changed, 17 insertions(+), 16 deletions(-) delete mode 100644 library/src/main/java/com/owncloud/android/lib/common/network/Tag.kt create mode 100644 library/src/main/java/com/owncloud/android/lib/resources/systemTag/SystemTag.kt diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/Tag.kt b/library/src/main/java/com/owncloud/android/lib/common/network/Tag.kt deleted file mode 100644 index 49f8b52e26..0000000000 --- a/library/src/main/java/com/owncloud/android/lib/common/network/Tag.kt +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Nextcloud Android Library - * - * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors - * SPDX-FileCopyrightText: 2025 Tobias Kaminsky - * SPDX-License-Identifier: MIT - */ - -package com.owncloud.android.lib.common.network - -data class Tag (val name: String, val color: String) diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt index ed736f974e..fcc5b385d0 100644 --- a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt +++ b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt @@ -21,6 +21,7 @@ import com.owncloud.android.lib.resources.files.model.GeoLocation import com.owncloud.android.lib.resources.files.model.ImageDimension import com.owncloud.android.lib.resources.shares.ShareType import com.owncloud.android.lib.resources.shares.ShareeUser +import com.owncloud.android.lib.resources.systemTag.SystemTag import org.apache.jackrabbit.webdav.MultiStatusResponse import org.apache.jackrabbit.webdav.property.DavProperty import org.apache.jackrabbit.webdav.property.DavPropertyName @@ -90,7 +91,7 @@ class WebdavEntry constructor( private set var lockToken: String? = null private set - var tags = arrayOfNulls(0) + var tags = arrayOfNulls(0) var imageDimension: ImageDimension? = null var geoLocation: GeoLocation? = null var hidden = false @@ -482,10 +483,10 @@ class WebdavEntry constructor( } } - private fun parseTag(element: Element): Tag { + private fun parseTag(element: Element): SystemTag { val name = element.firstChild.textContent - val color = element.getAttribute("nc:color") - return Tag(name, color) + val color = "#" + element.getAttribute("nc:color") + return SystemTag(name, color) } private fun parseLockProperties( diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt index 282a79d1bb..fa27a5fb42 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt @@ -15,6 +15,7 @@ import com.owncloud.android.lib.common.network.WebdavEntry.MountType import com.owncloud.android.lib.resources.files.FileUtils import com.owncloud.android.lib.resources.files.model.FileLockType.Companion.fromValue import com.owncloud.android.lib.resources.shares.ShareeUser +import com.owncloud.android.lib.resources.systemTag.SystemTag import java.io.Serializable /** @@ -54,7 +55,7 @@ class RemoteFile : var lockOwnerEditor: String? = null var lockTimeout: Long = 0 var lockToken: String? = null - var tags: Array? = null + var tags: Array? = null var imageDimension: ImageDimension? = null var geoLocation: GeoLocation? = null var hidden = false diff --git a/library/src/main/java/com/owncloud/android/lib/resources/systemTag/SystemTag.kt b/library/src/main/java/com/owncloud/android/lib/resources/systemTag/SystemTag.kt new file mode 100644 index 0000000000..ac8a590b82 --- /dev/null +++ b/library/src/main/java/com/owncloud/android/lib/resources/systemTag/SystemTag.kt @@ -0,0 +1,10 @@ +/* + * Nextcloud - Android Client + * + * SPDX-FileCopyrightText: 2025 Alper Ozturk + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +package com.owncloud.android.lib.resources.systemTag + +data class SystemTag(val name: String, val color: String?) From 906747cc64dc2fa64692dd711db08b7b0f47fa16 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Mon, 13 Jan 2025 07:41:42 +0100 Subject: [PATCH 05/11] test for tags Signed-off-by: tobiasKaminsky --- .../tags/GetTagsRemoteOperationIT.kt | 57 +++++++++++++++++++ .../android/lib/common/network/WebdavEntry.kt | 28 ++++----- .../lib/resources/systemTag/SystemTag.kt | 5 +- .../resources/tags/GetTagsRemoteOperation.kt | 17 +++++- .../android/lib/resources/tags/Tag.kt | 3 +- 5 files changed, 94 insertions(+), 16 deletions(-) diff --git a/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperationIT.kt b/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperationIT.kt index 7abdd576b9..500fdb5217 100644 --- a/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperationIT.kt +++ b/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperationIT.kt @@ -9,8 +9,19 @@ package com.owncloud.android.lib.resources.tags import com.nextcloud.test.RandomStringGenerator import com.owncloud.android.AbstractIT +import com.owncloud.android.lib.common.network.WebdavEntry +import com.owncloud.android.lib.resources.files.CreateFolderRemoteOperation +import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation +import com.owncloud.android.lib.resources.files.ReadFolderRemoteOperation +import com.owncloud.android.lib.resources.files.model.RemoteFile import junit.framework.TestCase.assertEquals import junit.framework.TestCase.assertTrue +import org.apache.commons.httpclient.HttpStatus +import org.apache.jackrabbit.webdav.client.methods.PropPatchMethod +import org.apache.jackrabbit.webdav.property.DavPropertyNameSet +import org.apache.jackrabbit.webdav.property.DavPropertySet +import org.apache.jackrabbit.webdav.property.DefaultDavProperty +import org.apache.jackrabbit.webdav.xml.Namespace import org.junit.Test class GetTagsRemoteOperationIT : AbstractIT() { @@ -34,5 +45,51 @@ class GetTagsRemoteOperationIT : AbstractIT() { sut = GetTagsRemoteOperation().execute(client) assertTrue(sut.isSuccess) assertEquals(count + 1, sut.resultData.size) + + // add color to one tag + val plainColor = "ff00ff" + val colorWithHex = "#$plainColor" + val tag = sut.resultData.first() + val newProps = DavPropertySet() + newProps.add( + DefaultDavProperty( + "nc:color", + plainColor, + Namespace.getNamespace(WebdavEntry.NAMESPACE_NC) + ) + ) + val propPatchMethod = + PropPatchMethod( + client.baseUri.toString() + "/remote.php/dav/systemtags/" + tag.id, + newProps, + DavPropertyNameSet() + ) + assertTrue(client.executeMethod(propPatchMethod) == HttpStatus.SC_MULTI_STATUS) + + sut = GetTagsRemoteOperation().execute(client) + + assertEquals(colorWithHex, sut.resultData.find { it.id == tag.id }?.color) + + // add colored tag to file + val tagFolder = "/coloredFolder" + assertTrue(CreateFolderRemoteOperation(tagFolder, true).execute(client).isSuccess) + val folderMetadata = ReadFileRemoteOperation(tagFolder).execute(client) + assertTrue( + PutTagRemoteOperation( + tag.id, + (folderMetadata.data[0] as RemoteFile).localId + ).execute(nextcloudClient).isSuccess + ) + + // read metadata + val rootMetadata = ReadFolderRemoteOperation("/").execute(client) + assertEquals( + colorWithHex, + (rootMetadata.data as ArrayList) + .find { it.remotePath == tagFolder } + ?.tags + ?.first() + ?.color + ) } } diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt index fcc5b385d0..6f8821aacb 100644 --- a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt +++ b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt @@ -395,20 +395,22 @@ class WebdavEntry constructor( prop = propSet[EXTENDED_PROPERTY_SYSTEM_TAGS, ncNamespace] if (prop?.value != null) { - tags = when (prop.value) { - is ArrayList<*> -> (prop.value as ArrayList<*>) - .filterIsInstance() - .map { parseTag(it) } - .toTypedArray() - - is Element -> { - val element = (prop.value as Element) - val tag = parseTag(element) - arrayOf(tag) - } + tags = + when (prop.value) { + is ArrayList<*> -> + (prop.value as ArrayList<*>) + .filterIsInstance() + .map { parseTag(it) } + .toTypedArray() + + is Element -> { + val element = (prop.value as Element) + val tag = parseTag(element) + arrayOf(tag) + } - else -> emptyArray() - } + else -> emptyArray() + } } // NC metadata size property diff --git a/library/src/main/java/com/owncloud/android/lib/resources/systemTag/SystemTag.kt b/library/src/main/java/com/owncloud/android/lib/resources/systemTag/SystemTag.kt index ac8a590b82..edaf433416 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/systemTag/SystemTag.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/systemTag/SystemTag.kt @@ -7,4 +7,7 @@ package com.owncloud.android.lib.resources.systemTag -data class SystemTag(val name: String, val color: String?) +data class SystemTag( + val name: String, + val color: String? +) diff --git a/library/src/main/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperation.kt b/library/src/main/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperation.kt index 7a5b2a2940..3a68bacabb 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperation.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperation.kt @@ -9,6 +9,8 @@ package com.owncloud.android.lib.resources.tags import com.owncloud.android.lib.common.OwnCloudClient import com.owncloud.android.lib.common.network.WebdavEntry.Companion.EXTENDED_PROPERTY_NAME_REMOTE_ID +import com.owncloud.android.lib.common.network.WebdavEntry.Companion.EXTENDED_PROPERTY_SYSTEM_TAGS_COLOR +import com.owncloud.android.lib.common.network.WebdavEntry.Companion.NAMESPACE_NC import com.owncloud.android.lib.common.network.WebdavEntry.Companion.NAMESPACE_OC import com.owncloud.android.lib.common.network.WebdavEntry.Companion.SHAREES_DISPLAY_NAME import com.owncloud.android.lib.common.operations.RemoteOperation @@ -18,15 +20,18 @@ import org.apache.jackrabbit.webdav.client.methods.PropFindMethod import org.apache.jackrabbit.webdav.property.DavPropertyNameSet import org.apache.jackrabbit.webdav.xml.Namespace +@Suppress("NestedBlockDepth") class GetTagsRemoteOperation : RemoteOperation>() { @Deprecated("Deprecated in Java") override fun run(client: OwnCloudClient): RemoteOperationResult> { val ocNamespace = Namespace.getNamespace(NAMESPACE_OC) + val ncNamespace = Namespace.getNamespace(NAMESPACE_NC) val propSet = DavPropertyNameSet().apply { add(EXTENDED_PROPERTY_NAME_REMOTE_ID, ocNamespace) add(SHAREES_DISPLAY_NAME, ocNamespace) + add(EXTENDED_PROPERTY_SYSTEM_TAGS_COLOR, ncNamespace) } val propFindMethod = @@ -55,7 +60,17 @@ class GetTagsRemoteOperation : RemoteOperation>() { .get(SHAREES_DISPLAY_NAME, ocNamespace) .value as String - result.add(Tag(id, name)) + var color = + it + .getProperties(HttpStatus.SC_OK) + .get(EXTENDED_PROPERTY_SYSTEM_TAGS_COLOR, ncNamespace) + ?.value as String? + + if (color != null) { + color = "#$color" + } + + result.add(Tag(id, name, color)) } } diff --git a/library/src/main/java/com/owncloud/android/lib/resources/tags/Tag.kt b/library/src/main/java/com/owncloud/android/lib/resources/tags/Tag.kt index b737e9a86b..4c5b80dbde 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/tags/Tag.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/tags/Tag.kt @@ -9,5 +9,6 @@ package com.owncloud.android.lib.resources.tags data class Tag( val id: String, - val name: String + val name: String, + val color: String? ) From 7e839c6183cf7ff856cb56f5c1593a8c8c719527 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Tue, 14 Jan 2025 07:19:13 +0100 Subject: [PATCH 06/11] test for tags Signed-off-by: tobiasKaminsky --- .../lib/resources/files/ReadFolderRemoteOperationIT.kt | 2 +- .../android/lib/resources/tags/GetTagsRemoteOperationIT.kt | 3 +++ .../owncloud/android/lib/resources/status/NextcloudVersion.kt | 3 +++ .../com/owncloud/android/lib/resources/systemTag/SystemTag.kt | 4 ++-- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/library/src/androidTest/java/com/owncloud/android/lib/resources/files/ReadFolderRemoteOperationIT.kt b/library/src/androidTest/java/com/owncloud/android/lib/resources/files/ReadFolderRemoteOperationIT.kt index 11613b2a7b..d62946632e 100644 --- a/library/src/androidTest/java/com/owncloud/android/lib/resources/files/ReadFolderRemoteOperationIT.kt +++ b/library/src/androidTest/java/com/owncloud/android/lib/resources/files/ReadFolderRemoteOperationIT.kt @@ -94,7 +94,7 @@ class ReadFolderRemoteOperationIT : AbstractIT() { assertEquals(remotePath + "1.txt", remoteFile.remotePath) assertEquals(2, remoteFile.tags?.size) - remoteFile.tags?.sort() + remoteFile.tags?.sortBy { it?.name } assertEquals(tag1, remoteFile.tags?.get(0)) assertEquals(tag2, remoteFile.tags?.get(1)) } diff --git a/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperationIT.kt b/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperationIT.kt index 500fdb5217..b7e4edc0b2 100644 --- a/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperationIT.kt +++ b/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperationIT.kt @@ -14,6 +14,7 @@ import com.owncloud.android.lib.resources.files.CreateFolderRemoteOperation import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation import com.owncloud.android.lib.resources.files.ReadFolderRemoteOperation import com.owncloud.android.lib.resources.files.model.RemoteFile +import com.owncloud.android.lib.resources.status.NextcloudVersion import junit.framework.TestCase.assertEquals import junit.framework.TestCase.assertTrue import org.apache.commons.httpclient.HttpStatus @@ -31,6 +32,8 @@ class GetTagsRemoteOperationIT : AbstractIT() { @Test fun list() { + testOnlyOnServer(NextcloudVersion.nextcloud_31) + var sut = GetTagsRemoteOperation().execute(client) assertTrue(sut.isSuccess) diff --git a/library/src/main/java/com/owncloud/android/lib/resources/status/NextcloudVersion.kt b/library/src/main/java/com/owncloud/android/lib/resources/status/NextcloudVersion.kt index 5fc1d25cff..50ffa3608c 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/status/NextcloudVersion.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/status/NextcloudVersion.kt @@ -38,6 +38,9 @@ class NextcloudVersion : OwnCloudVersion { @JvmField val nextcloud_30 = NextcloudVersion(0x1E000000) // 30.0 + + @JvmField + val nextcloud_31 = NextcloudVersion(0x1F000000) // 31.0 } constructor(string: String) : super(string) diff --git a/library/src/main/java/com/owncloud/android/lib/resources/systemTag/SystemTag.kt b/library/src/main/java/com/owncloud/android/lib/resources/systemTag/SystemTag.kt index edaf433416..1912a205d4 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/systemTag/SystemTag.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/systemTag/SystemTag.kt @@ -1,8 +1,8 @@ /* - * Nextcloud - Android Client + * Nextcloud Android Library * * SPDX-FileCopyrightText: 2025 Alper Ozturk - * SPDX-License-Identifier: AGPL-3.0-or-later +* SPDX-License-Identifier: MIT */ package com.owncloud.android.lib.resources.systemTag From 1c2c99da11868fbfb6e5d1ed973faf8265cb471c Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Tue, 14 Jan 2025 08:06:29 +0100 Subject: [PATCH 07/11] update Signed-off-by: tobiasKaminsky --- .../lib/resources/files/ReadFolderRemoteOperationIT.kt | 4 ++-- .../android/lib/resources/tags/GetTagsRemoteOperationIT.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/src/androidTest/java/com/owncloud/android/lib/resources/files/ReadFolderRemoteOperationIT.kt b/library/src/androidTest/java/com/owncloud/android/lib/resources/files/ReadFolderRemoteOperationIT.kt index d62946632e..17b8041927 100644 --- a/library/src/androidTest/java/com/owncloud/android/lib/resources/files/ReadFolderRemoteOperationIT.kt +++ b/library/src/androidTest/java/com/owncloud/android/lib/resources/files/ReadFolderRemoteOperationIT.kt @@ -95,7 +95,7 @@ class ReadFolderRemoteOperationIT : AbstractIT() { assertEquals(2, remoteFile.tags?.size) remoteFile.tags?.sortBy { it?.name } - assertEquals(tag1, remoteFile.tags?.get(0)) - assertEquals(tag2, remoteFile.tags?.get(1)) + assertEquals(tag1, remoteFile.tags?.get(0)?.name) + assertEquals(tag2, remoteFile.tags?.get(1)?.name) } } diff --git a/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperationIT.kt b/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperationIT.kt index b7e4edc0b2..42e20f8b25 100644 --- a/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperationIT.kt +++ b/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperationIT.kt @@ -74,7 +74,7 @@ class GetTagsRemoteOperationIT : AbstractIT() { assertEquals(colorWithHex, sut.resultData.find { it.id == tag.id }?.color) // add colored tag to file - val tagFolder = "/coloredFolder" + val tagFolder = "/coloredFolder/" assertTrue(CreateFolderRemoteOperation(tagFolder, true).execute(client).isSuccess) val folderMetadata = ReadFileRemoteOperation(tagFolder).execute(client) assertTrue( From e1867066b1ee82802216f14c99c0271c21cc4ff8 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Tue, 14 Jan 2025 11:27:16 +0100 Subject: [PATCH 08/11] allow to have tags without color Signed-off-by: tobiasKaminsky --- .../tags/GetTagsRemoteOperationIT.kt | 33 +++++++++++++------ .../android/lib/common/network/WebdavEntry.kt | 8 ++++- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperationIT.kt b/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperationIT.kt index 42e20f8b25..eeef1a6d9c 100644 --- a/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperationIT.kt +++ b/library/src/androidTest/java/com/owncloud/android/lib/resources/tags/GetTagsRemoteOperationIT.kt @@ -31,6 +31,7 @@ class GetTagsRemoteOperationIT : AbstractIT() { } @Test + @Suppress("LongMethod") fun list() { testOnlyOnServer(NextcloudVersion.nextcloud_31) @@ -45,14 +46,21 @@ class GetTagsRemoteOperationIT : AbstractIT() { .isSuccess ) + assertTrue( + CreateTagRemoteOperation(RandomStringGenerator.make(TAG_LENGTH)) + .execute(nextcloudClient) + .isSuccess + ) + sut = GetTagsRemoteOperation().execute(client) assertTrue(sut.isSuccess) - assertEquals(count + 1, sut.resultData.size) + assertEquals(count + 2, sut.resultData.size) // add color to one tag val plainColor = "ff00ff" val colorWithHex = "#$plainColor" - val tag = sut.resultData.first() + val tag1 = sut.resultData.first() + val tag2 = sut.resultData[1] val newProps = DavPropertySet() newProps.add( DefaultDavProperty( @@ -63,7 +71,7 @@ class GetTagsRemoteOperationIT : AbstractIT() { ) val propPatchMethod = PropPatchMethod( - client.baseUri.toString() + "/remote.php/dav/systemtags/" + tag.id, + client.baseUri.toString() + "/remote.php/dav/systemtags/" + tag1.id, newProps, DavPropertyNameSet() ) @@ -71,7 +79,7 @@ class GetTagsRemoteOperationIT : AbstractIT() { sut = GetTagsRemoteOperation().execute(client) - assertEquals(colorWithHex, sut.resultData.find { it.id == tag.id }?.color) + assertEquals(colorWithHex, sut.resultData.find { it.id == tag1.id }?.color) // add colored tag to file val tagFolder = "/coloredFolder/" @@ -79,20 +87,25 @@ class GetTagsRemoteOperationIT : AbstractIT() { val folderMetadata = ReadFileRemoteOperation(tagFolder).execute(client) assertTrue( PutTagRemoteOperation( - tag.id, + tag1.id, + (folderMetadata.data[0] as RemoteFile).localId + ).execute(nextcloudClient).isSuccess + ) + assertTrue( + PutTagRemoteOperation( + tag2.id, (folderMetadata.data[0] as RemoteFile).localId ).execute(nextcloudClient).isSuccess ) // read metadata val rootMetadata = ReadFolderRemoteOperation("/").execute(client) - assertEquals( - colorWithHex, + val tags = (rootMetadata.data as ArrayList) .find { it.remotePath == tagFolder } ?.tags - ?.first() - ?.color - ) + assertEquals(2, tags?.size) + assertEquals(colorWithHex, tags?.first()?.color) + assertEquals(null, tags?.get(1)?.color) } } diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt index 6f8821aacb..94bb5392b7 100644 --- a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt +++ b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt @@ -487,7 +487,13 @@ class WebdavEntry constructor( private fun parseTag(element: Element): SystemTag { val name = element.firstChild.textContent - val color = "#" + element.getAttribute("nc:color") + + val color = + if (element.getAttribute("nc:color").isNotEmpty()) { + "#" + element.getAttribute("nc:color") + } else { + null + } return SystemTag(name, color) } From e4896758f5d23f27dcb2bb778c83966da070ec53 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 21 Jan 2025 11:36:30 +0100 Subject: [PATCH 09/11] use tag class Signed-off-by: alperozturk --- .../android/lib/common/network/WebdavEntry.kt | 8 ++++---- .../android/lib/resources/files/model/RemoteFile.kt | 4 ++-- .../android/lib/resources/systemTag/SystemTag.kt | 13 ------------- 3 files changed, 6 insertions(+), 19 deletions(-) delete mode 100644 library/src/main/java/com/owncloud/android/lib/resources/systemTag/SystemTag.kt diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt index 94bb5392b7..e9caaa5ae0 100644 --- a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt +++ b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt @@ -21,7 +21,7 @@ import com.owncloud.android.lib.resources.files.model.GeoLocation import com.owncloud.android.lib.resources.files.model.ImageDimension import com.owncloud.android.lib.resources.shares.ShareType import com.owncloud.android.lib.resources.shares.ShareeUser -import com.owncloud.android.lib.resources.systemTag.SystemTag +import com.owncloud.android.lib.resources.tags.Tag import org.apache.jackrabbit.webdav.MultiStatusResponse import org.apache.jackrabbit.webdav.property.DavProperty import org.apache.jackrabbit.webdav.property.DavPropertyName @@ -91,7 +91,7 @@ class WebdavEntry constructor( private set var lockToken: String? = null private set - var tags = arrayOfNulls(0) + var tags = arrayOfNulls(0) var imageDimension: ImageDimension? = null var geoLocation: GeoLocation? = null var hidden = false @@ -485,7 +485,7 @@ class WebdavEntry constructor( } } - private fun parseTag(element: Element): SystemTag { + private fun parseTag(element: Element): Tag { val name = element.firstChild.textContent val color = @@ -494,7 +494,7 @@ class WebdavEntry constructor( } else { null } - return SystemTag(name, color) + return Tag(remoteId ?: "", name, color) } private fun parseLockProperties( diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt index fa27a5fb42..23e47763ab 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt @@ -15,7 +15,7 @@ import com.owncloud.android.lib.common.network.WebdavEntry.MountType import com.owncloud.android.lib.resources.files.FileUtils import com.owncloud.android.lib.resources.files.model.FileLockType.Companion.fromValue import com.owncloud.android.lib.resources.shares.ShareeUser -import com.owncloud.android.lib.resources.systemTag.SystemTag +import com.owncloud.android.lib.resources.tags.Tag import java.io.Serializable /** @@ -55,7 +55,7 @@ class RemoteFile : var lockOwnerEditor: String? = null var lockTimeout: Long = 0 var lockToken: String? = null - var tags: Array? = null + var tags: Array? = null var imageDimension: ImageDimension? = null var geoLocation: GeoLocation? = null var hidden = false diff --git a/library/src/main/java/com/owncloud/android/lib/resources/systemTag/SystemTag.kt b/library/src/main/java/com/owncloud/android/lib/resources/systemTag/SystemTag.kt deleted file mode 100644 index 1912a205d4..0000000000 --- a/library/src/main/java/com/owncloud/android/lib/resources/systemTag/SystemTag.kt +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Nextcloud Android Library - * - * SPDX-FileCopyrightText: 2025 Alper Ozturk -* SPDX-License-Identifier: MIT - */ - -package com.owncloud.android.lib.resources.systemTag - -data class SystemTag( - val name: String, - val color: String? -) From da126dcde49a497817427b660c50713cbf877825 Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 21 Jan 2025 11:39:58 +0100 Subject: [PATCH 10/11] apply suggestion Signed-off-by: alperozturk --- .../java/com/owncloud/android/lib/common/network/WebdavEntry.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt index e9caaa5ae0..c0ccf03191 100644 --- a/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt +++ b/library/src/main/java/com/owncloud/android/lib/common/network/WebdavEntry.kt @@ -91,7 +91,7 @@ class WebdavEntry constructor( private set var lockToken: String? = null private set - var tags = arrayOfNulls(0) + var tags = emptyArray() var imageDimension: ImageDimension? = null var geoLocation: GeoLocation? = null var hidden = false From 0b31cc65bed7bffc776e177dbee76cdc3545445e Mon Sep 17 00:00:00 2001 From: alperozturk Date: Tue, 21 Jan 2025 11:44:27 +0100 Subject: [PATCH 11/11] rebase master Signed-off-by: alperozturk --- .../com/owncloud/android/lib/resources/files/model/RemoteFile.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt b/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt index 23e47763ab..facffe2e18 100644 --- a/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt +++ b/library/src/main/java/com/owncloud/android/lib/resources/files/model/RemoteFile.kt @@ -8,7 +8,6 @@ package com.owncloud.android.lib.resources.files.model import android.os.Parcel import android.os.Parcelable -import com.owncloud.android.lib.common.network.Tag import com.nextcloud.android.lib.resources.files.FileDownloadLimit import com.owncloud.android.lib.common.network.WebdavEntry import com.owncloud.android.lib.common.network.WebdavEntry.MountType