Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/bitfireAT/ical4android.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Lang <72232737+patrickunterwegs@users.noreply.github.com>2022-02-15 21:34:47 +0300
committerGitHub <noreply@github.com>2022-02-15 21:34:47 +0300
commit9d57f4c3c454bc0dc2779fa39d61a667a7a383bc (patch)
tree2418403e1741652964a4dc671605051717cbd3b8
parent37f0216b1ce2f586750e048b8473a25443192e03 (diff)
Add option to export collections as .ics (#9)
* Refactored ics-generation, using ical4android now Closes #15 * Added option to export collections as .ics Fixed issue for exporting entries with attachments (affected also sync!) * Added test for getICSForCollection() * Closes #13 jtx: ICS generation always contains ORGANIZER although it is empty
-rw-r--r--src/androidTest/java/at/bitfire/ical4android/JtxCollectionTest.kt36
-rw-r--r--src/main/java/at/bitfire/ical4android/JtxCollection.kt28
-rw-r--r--src/main/java/at/bitfire/ical4android/JtxICalObject.kt5
3 files changed, 63 insertions, 6 deletions
diff --git a/src/androidTest/java/at/bitfire/ical4android/JtxCollectionTest.kt b/src/androidTest/java/at/bitfire/ical4android/JtxCollectionTest.kt
index e1478fe..807f1bc 100644
--- a/src/androidTest/java/at/bitfire/ical4android/JtxCollectionTest.kt
+++ b/src/androidTest/java/at/bitfire/ical4android/JtxCollectionTest.kt
@@ -14,8 +14,7 @@ import at.bitfire.ical4android.MiscUtils.ContentProviderClientHelper.closeCompat
import at.bitfire.ical4android.impl.TestJtxCollection
import at.techbee.jtx.JtxContract
import at.techbee.jtx.JtxContract.asSyncAdapter
-import junit.framework.TestCase.assertEquals
-import junit.framework.TestCase.assertNotNull
+import junit.framework.TestCase.*
import org.junit.After
import org.junit.Before
import org.junit.Test
@@ -25,7 +24,6 @@ class JtxCollectionTest {
private val testAccount = Account("TEST", JtxContract.JtxCollection.TEST_ACCOUNT_TYPE)
private lateinit var contentResolver: ContentResolver
private lateinit var client: ContentProviderClient
- var collection: JtxCollection<JtxICalObject>? = null
lateinit var context: Context
private val url = "https://jtx.techbee.at"
@@ -93,4 +91,36 @@ class JtxCollectionTest {
assertEquals(1, icalobjects.size)
}
+
+ @Test
+ fun getICSForCollection_test() {
+ val collectionUri = JtxCollection.create(testAccount, client, cv)
+ assertNotNull(collectionUri)
+
+ val collections = JtxCollection.find(testAccount, client, context, TestJtxCollection.Factory, null, null)
+ val items = collections[0].queryICalObjects(null, null)
+ assertEquals(0, items.size)
+
+ val cv1 = ContentValues().apply {
+ put(JtxContract.JtxICalObject.SUMMARY, "summary")
+ put(JtxContract.JtxICalObject.COMPONENT, JtxContract.JtxICalObject.Component.VJOURNAL.name)
+ put(JtxContract.JtxICalObject.ICALOBJECT_COLLECTIONID, collections[0].id)
+ }
+ val cv2 = ContentValues().apply {
+ put(JtxContract.JtxICalObject.SUMMARY, "entry2")
+ put(JtxContract.JtxICalObject.COMPONENT, JtxContract.JtxICalObject.Component.VTODO.name)
+ put(JtxContract.JtxICalObject.ICALOBJECT_COLLECTIONID, collections[0].id)
+ }
+ client.insert(JtxContract.JtxICalObject.CONTENT_URI.asSyncAdapter(testAccount), cv1)
+ client.insert(JtxContract.JtxICalObject.CONTENT_URI.asSyncAdapter(testAccount), cv2)
+
+ val ics = collections[0].getICSForCollection()
+
+ assertTrue(ics.contains(Regex("BEGIN:VCALENDAR(\\n*|\\r*|\\t*|.*)*END:VCALENDAR")))
+ assertTrue(ics.contains("PRODID:+//IDN bitfire.at//ical4android"))
+ assertTrue(ics.contains("SUMMARY:summary"))
+ assertTrue(ics.contains("SUMMARY:entry2"))
+ assertTrue(ics.contains(Regex("BEGIN:VJOURNAL(\\n*|\\r*|\\t*|.*)*END:VJOURNAL")))
+ assertTrue(ics.contains(Regex("BEGIN:VTODO(\\n*|\\r*|\\t*|.*)*END:VTODO")))
+ }
}
diff --git a/src/main/java/at/bitfire/ical4android/JtxCollection.kt b/src/main/java/at/bitfire/ical4android/JtxCollection.kt
index a10ee42..25277b9 100644
--- a/src/main/java/at/bitfire/ical4android/JtxCollection.kt
+++ b/src/main/java/at/bitfire/ical4android/JtxCollection.kt
@@ -13,6 +13,10 @@ import android.net.Uri
import at.bitfire.ical4android.MiscUtils.CursorHelper.toValues
import at.techbee.jtx.JtxContract
import at.techbee.jtx.JtxContract.asSyncAdapter
+import net.fortuna.ical4j.model.Calendar
+import net.fortuna.ical4j.model.component.VJournal
+import net.fortuna.ical4j.model.component.VToDo
+import net.fortuna.ical4j.model.property.Version
import java.util.*
open class JtxCollection<out T: JtxICalObject>(val account: Account,
@@ -262,4 +266,28 @@ open class JtxCollection<out T: JtxICalObject>(val account: Account,
}
}
+
+ /**
+ * @return a string with all JtxICalObjects within the collection as iCalendar
+ */
+ fun getICSForCollection(): String {
+ client.query(JtxContract.JtxICalObject.CONTENT_URI.asSyncAdapter(account), null, "${JtxContract.JtxICalObject.ICALOBJECT_COLLECTIONID} = ? AND ${JtxContract.JtxICalObject.DELETED} = ?", arrayOf(id.toString(), "0"), null).use { cursor ->
+ Ical4Android.log.fine("getICSForCollection: found ${cursor?.count} records in ${account.name}")
+
+ val ical = Calendar()
+ ical.properties += Version.VERSION_2_0
+ ical.properties += ICalendar.prodId
+
+ while (cursor?.moveToNext() == true) {
+ val jtxIcalObject = JtxICalObject(this)
+ jtxIcalObject.populateFromContentValues(cursor.toValues())
+ val singleICS = jtxIcalObject.getICalendarFormat()
+ singleICS?.components?.forEach { component ->
+ if(component is VToDo || component is VJournal)
+ ical.components += component
+ }
+ }
+ return ical.toString()
+ }
+ }
} \ No newline at end of file
diff --git a/src/main/java/at/bitfire/ical4android/JtxICalObject.kt b/src/main/java/at/bitfire/ical4android/JtxICalObject.kt
index 7a9218c..087ca00 100644
--- a/src/main/java/at/bitfire/ical4android/JtxICalObject.kt
+++ b/src/main/java/at/bitfire/ical4android/JtxICalObject.kt
@@ -675,8 +675,6 @@ open class JtxICalObject(
Ical4Android.log.log(Level.WARNING, "Ignoring invalid task URL: $url", e)
}
}
- //organizer?.let { props += it }
-
classification?.let { props += Clazz(it) }
status?.let { props += Status(it) }
@@ -1518,7 +1516,8 @@ duration?.let(props::add)
language = organizerContentValues?.getAsString(JtxContract.JtxOrganizer.LANGUAGE)
other = organizerContentValues?.getAsString(JtxContract.JtxOrganizer.OTHER)
}
- organizer = orgnzr
+ if(orgnzr.caladdress?.isNotEmpty() == true) // we only take the organizer if there was a caladdress (otherwise an empty ORGANIZER is created)
+ organizer = orgnzr
// Take care of attachments
val attachmentContentValues = getAttachmentsContentValues()