diff --git a/app/src/main/java/org/tasks/Tasks.kt b/app/src/main/java/org/tasks/Tasks.kt index 1314a7f04..4486ce7a4 100644 --- a/app/src/main/java/org/tasks/Tasks.kt +++ b/app/src/main/java/org/tasks/Tasks.kt @@ -18,6 +18,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.tasks.billing.BillingClient import org.tasks.billing.Inventory +import org.tasks.caldav.property.Invite import org.tasks.caldav.property.ShareAccess import org.tasks.files.FileHelper import org.tasks.injection.InjectingJobIntentService @@ -94,6 +95,7 @@ class Tasks : Application(), Configuration.Provider { appWidgetManager.get().reconfigureWidgets() PropertyRegistry.register(listOf( ShareAccess.Factory(), + Invite.Factory() )) } diff --git a/app/src/main/java/org/tasks/caldav/CaldavClient.kt b/app/src/main/java/org/tasks/caldav/CaldavClient.kt index 05062bf65..34aef13ec 100644 --- a/app/src/main/java/org/tasks/caldav/CaldavClient.kt +++ b/app/src/main/java/org/tasks/caldav/CaldavClient.kt @@ -19,6 +19,7 @@ import okhttp3.HttpUrl import okhttp3.OkHttpClient import org.tasks.R import org.tasks.Strings.isNullOrEmpty +import org.tasks.caldav.property.Invite import org.tasks.caldav.property.ShareAccess import org.tasks.data.CaldavAccount import org.tasks.ui.DisplayableException @@ -124,6 +125,7 @@ open class CaldavClient( CalendarColor.NAME, SyncToken.NAME, ShareAccess.NAME, + Invite.NAME ) { response: Response, relation: HrefRelation -> if (relation == HrefRelation.MEMBER) { responses.add(response) diff --git a/app/src/main/java/org/tasks/caldav/property/Invite.kt b/app/src/main/java/org/tasks/caldav/property/Invite.kt new file mode 100644 index 000000000..046616c94 --- /dev/null +++ b/app/src/main/java/org/tasks/caldav/property/Invite.kt @@ -0,0 +1,40 @@ +package org.tasks.caldav.property + +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils +import at.bitfire.dav4jvm.XmlUtils.propertyName +import org.tasks.BuildConfig +import org.xmlpull.v1.XmlPullParser + +data class Invite(val sharees: List): Property { + + companion object { + @JvmField + val NAME = Property.Name(XmlUtils.NS_WEBDAV, "invite") + + val SHAREE = Property.Name(XmlUtils.NS_WEBDAV, "sharee") + } + + + class Factory : PropertyFactory { + + override fun getName() = NAME + + override fun create(parser: XmlPullParser): Invite { + val depth = parser.depth + var eventType = parser.eventType + val sharees = ArrayList() + while (!(eventType == XmlPullParser.END_TAG && parser.depth == depth)) { + if (eventType == XmlPullParser.START_TAG && parser.depth == depth + 1) { + if (parser.propertyName() == SHAREE) { + sharees.add(Sharee(parser)) + } + } + eventType = parser.next() + } + if (BuildConfig.DEBUG && parser.depth != depth) { error("Assertion failed") } + return Invite(sharees) + } + } +} diff --git a/app/src/main/java/org/tasks/caldav/property/Sharee.kt b/app/src/main/java/org/tasks/caldav/property/Sharee.kt new file mode 100644 index 000000000..257da33e1 --- /dev/null +++ b/app/src/main/java/org/tasks/caldav/property/Sharee.kt @@ -0,0 +1,56 @@ +package org.tasks.caldav.property + +import at.bitfire.dav4jvm.DavResource +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyRegistry +import at.bitfire.dav4jvm.XmlUtils +import at.bitfire.dav4jvm.XmlUtils.propertyName +import org.tasks.BuildConfig +import org.xmlpull.v1.XmlPullParser + +class Sharee(parser: XmlPullParser) { + lateinit var href: String + private set + lateinit var access: ShareAccess + private set + lateinit var response: Property.Name + private set + var comment: String? = null + private set + val properties = ArrayList() + + init { + val depth = parser.depth + var eventType = parser.eventType + while (!(eventType == XmlPullParser.END_TAG && parser.depth == depth)) { + if (eventType == XmlPullParser.START_TAG && parser.depth == depth + 1) { + when (val name = parser.propertyName()) { + DavResource.HREF -> + XmlUtils.readText(parser)?.let { href = it } + ShareAccess.NAME -> + access = PropertyRegistry.create(ShareAccess.NAME, parser) as ShareAccess + COMMENT -> + comment = XmlUtils.readText(parser) + INVITE_ACCEPTED, INVITE_DECLINED, INVITE_NORESPONSE, INVITE_INVALID -> + response = name + DavResource.PROP -> + properties.addAll(Property.parse(parser)) + } + } + eventType = parser.next() + } + if (BuildConfig.DEBUG && parser.depth != depth) { error("Assertion failed") } + } + + override fun toString(): String { + return "Sharee(href='$href', access=$access, response=$response, comment=$comment, properties=$properties)" + } + + companion object { + val COMMENT = Property.Name(XmlUtils.NS_WEBDAV, "comment") + val INVITE_ACCEPTED = Property.Name(XmlUtils.NS_WEBDAV, "invite-accepted") + val INVITE_DECLINED = Property.Name(XmlUtils.NS_WEBDAV, "invite-declined") + val INVITE_NORESPONSE = Property.Name(XmlUtils.NS_WEBDAV, "invite-noresponse") + val INVITE_INVALID = Property.Name(XmlUtils.NS_WEBDAV, "invite-invalid") + } +} \ No newline at end of file diff --git a/app/src/test/java/org/tasks/caldav/property/InviteTest.kt b/app/src/test/java/org/tasks/caldav/property/InviteTest.kt new file mode 100644 index 000000000..b69b15c33 --- /dev/null +++ b/app/src/test/java/org/tasks/caldav/property/InviteTest.kt @@ -0,0 +1,62 @@ +package org.tasks.caldav.property + +import at.bitfire.dav4jvm.PropertyRegistry +import org.junit.Assert.* +import org.junit.Before +import org.junit.Test +import org.tasks.caldav.property.PropertyUtils.toProperty +import org.tasks.caldav.property.ShareAccess.Companion.SHARED_OWNER + +class InviteTest { + @Before + fun setUp() { + PropertyRegistry.register(listOf( + ShareAccess.Factory(), + Invite.Factory() + )) + } + + @Test + fun emptyInvite() { + val invite: Invite = "".toProperty() + + assertTrue(invite.sharees.isEmpty()) + } + + @Test + fun shareeAccess() { + assertEquals(ShareAccess(SHARED_OWNER), sharee(SHARE_OWNER).access) + } + + @Test + fun shareeHref() { + assertEquals("/principals/102967489186752069531", sharee(SHARE_OWNER).href) + } + + @Test + fun inviteStatus() { + assertEquals(Sharee.INVITE_ACCEPTED, sharee(SHARE_OWNER).response) + } + + @Test + fun noComment() { + assertNull(sharee(SHARE_OWNER).comment) + } + + private fun sharee(xml: String): Sharee = xml.toProperty().sharees.first() + + companion object { + val SHARE_OWNER = """ + + + /principals/102967489186752069531 + + + + + + + + """.trimIndent() + } +} \ No newline at end of file