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..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 @@ -94,8 +94,8 @@ class ReadFolderRemoteOperationIT : AbstractIT() { assertEquals(remotePath + "1.txt", remoteFile.remotePath) assertEquals(2, remoteFile.tags?.size) - remoteFile.tags?.sort() - assertEquals(tag1, remoteFile.tags?.get(0)) - assertEquals(tag2, remoteFile.tags?.get(1)) + remoteFile.tags?.sortBy { it?.name } + 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 7abdd576b9..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 @@ -9,8 +9,20 @@ 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 com.owncloud.android.lib.resources.status.NextcloudVersion 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() { @@ -19,7 +31,10 @@ class GetTagsRemoteOperationIT : AbstractIT() { } @Test + @Suppress("LongMethod") fun list() { + testOnlyOnServer(NextcloudVersion.nextcloud_31) + var sut = GetTagsRemoteOperation().execute(client) assertTrue(sut.isSuccess) @@ -31,8 +46,66 @@ 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 tag1 = sut.resultData.first() + val tag2 = sut.resultData[1] + val newProps = DavPropertySet() + newProps.add( + DefaultDavProperty( + "nc:color", + plainColor, + Namespace.getNamespace(WebdavEntry.NAMESPACE_NC) + ) + ) + val propPatchMethod = + PropPatchMethod( + client.baseUri.toString() + "/remote.php/dav/systemtags/" + tag1.id, + newProps, + DavPropertyNameSet() + ) + assertTrue(client.executeMethod(propPatchMethod) == HttpStatus.SC_MULTI_STATUS) + + sut = GetTagsRemoteOperation().execute(client) + + assertEquals(colorWithHex, sut.resultData.find { it.id == tag1.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( + 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) + val tags = + (rootMetadata.data as ArrayList) + .find { it.remotePath == tagFolder } + ?.tags + 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 978a3e9651..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 @@ -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.tags.Tag 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 = emptyArray() var imageDimension: ImageDimension? = null var geoLocation: GeoLocation? = null var hidden = false @@ -393,24 +394,23 @@ 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) - } - tags = tempList.toTypedArray() - } else { - // single item or empty - val element = prop.value as Element - val value = 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) + } - if (value != null) { - tags = arrayOf(value) + else -> emptyArray() } - } } // NC metadata size property @@ -485,6 +485,18 @@ class WebdavEntry constructor( } } + private fun parseTag(element: Element): Tag { + val name = element.firstChild.textContent + + val color = + if (element.getAttribute("nc:color").isNotEmpty()) { + "#" + element.getAttribute("nc:color") + } else { + null + } + return Tag(remoteId ?: "", name, color) + } + private fun parseLockProperties( ncNamespace: Namespace, propSet: DavPropertySet @@ -659,6 +671,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); 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..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 @@ -14,6 +14,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.tags.Tag import java.io.Serializable /** @@ -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 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/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? )