Skip to content
This repository was archived by the owner on Jun 9, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions src/androidTest/java/at/bitfire/ical4android/JtxICalObjectTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ package at.bitfire.ical4android

import android.accounts.Account
import android.content.ContentProviderClient
import android.content.ContentResolver
import android.content.ContentValues
import android.content.Context
import android.database.DatabaseUtils
import android.os.ParcelFileDescriptor
import androidx.test.platform.app.InstrumentationRegistry
Expand Down Expand Up @@ -38,14 +40,14 @@ class JtxICalObjectTest {

companion object {

val context = InstrumentationRegistry.getInstrumentation().targetContext
val contentResolver = context.contentResolver
private val context: Context = InstrumentationRegistry.getInstrumentation().targetContext
private val contentResolver: ContentResolver = context.contentResolver

private lateinit var client: ContentProviderClient

@JvmField
@ClassRule
val permissionRule = GrantPermissionRule.grant(*TaskProvider.PERMISSIONS_JTX)
val permissionRule: GrantPermissionRule = GrantPermissionRule.grant(*TaskProvider.PERMISSIONS_JTX)

@BeforeClass
@JvmStatic
Expand All @@ -65,8 +67,8 @@ class JtxICalObjectTest {
}

private val testAccount = Account("TEST", JtxContract.JtxCollection.TEST_ACCOUNT_TYPE)
var collection: JtxCollection<at.bitfire.ical4android.JtxICalObject>? = null
var sample: at.bitfire.ical4android.JtxICalObject? = null
private var collection: JtxCollection<at.bitfire.ical4android.JtxICalObject>? = null
private var sample: at.bitfire.ical4android.JtxICalObject? = null

private val url = "https://jtx.techbee.at"
private val displayname = "jtxTest"
Expand Down Expand Up @@ -95,13 +97,15 @@ class JtxICalObjectTest {
this.dtend = System.currentTimeMillis()
this.dtendTimezone = "Europe/Paris"
this.status = JtxICalObject.StatusJournal.FINAL.name
this.xstatus = "my status"
this.classification = JtxICalObject.Classification.PUBLIC.name
this.url = "https://jtx.techbee.at"
this.contact = "jtx@techbee.at"
this.geoLat = 48.2082
this.geoLong = 16.3738
this.location = "Vienna"
this.locationAltrep = "Wien"
this.geofenceRadius = 10
this.percent = 99
this.priority = 1
this.due = System.currentTimeMillis()
Expand Down Expand Up @@ -144,13 +148,25 @@ class JtxICalObjectTest {
@Test fun check_DTEND() = insertRetrieveAssertLong(JtxICalObject.DTEND, sample?.dtend, Component.VJOURNAL.name)
@Test fun check_DTEND_TIMEZONE() = insertRetrieveAssertString(JtxICalObject.DTEND_TIMEZONE, sample?.dtendTimezone, Component.VJOURNAL.name)
@Test fun check_STATUS() = insertRetrieveAssertString(JtxICalObject.STATUS, sample?.status, Component.VJOURNAL.name)
@Test fun check_XSTATUS() {
val jtxVersionCode = context.packageManager.getPackageInfo("at.techbee.jtx", 0).longVersionCode
Assume.assumeTrue(jtxVersionCode > 204020003)
insertRetrieveAssertString(JtxICalObject.EXTENDED_STATUS, sample?.xstatus, Component.VJOURNAL.name)
}

@Test fun check_CLASSIFICATION() = insertRetrieveAssertString(JtxICalObject.CLASSIFICATION, sample?.classification, Component.VJOURNAL.name)
@Test fun check_URL() = insertRetrieveAssertString(JtxICalObject.URL, sample?.url, Component.VJOURNAL.name)
@Test fun check_CONTACT() = insertRetrieveAssertString(JtxICalObject.CONTACT, sample?.contact, Component.VJOURNAL.name)
@Test fun check_GEO_LAT() = insertRetrieveAssertDouble(JtxICalObject.GEO_LAT, sample?.geoLat, Component.VJOURNAL.name)
@Test fun check_GEO_LONG() = insertRetrieveAssertDouble(JtxICalObject.GEO_LONG, sample?.geoLong, Component.VJOURNAL.name)
@Test fun check_LOCATION() = insertRetrieveAssertString(JtxICalObject.LOCATION, sample?.location, Component.VJOURNAL.name)
@Test fun check_LOCATION_ALTREP() = insertRetrieveAssertString(JtxICalObject.LOCATION_ALTREP, sample?.locationAltrep, Component.VJOURNAL.name)
@Test fun check_GEOFENCE_RADIUS() {
val jtxVersionCode = context.packageManager.getPackageInfo("at.techbee.jtx", 0).longVersionCode
Assume.assumeTrue(jtxVersionCode > 204020003)
insertRetrieveAssertInt(JtxICalObject.GEOFENCE_RADIUS, sample?.geofenceRadius, Component.VJOURNAL.name)
}

@Test fun check_PERCENT() = insertRetrieveAssertInt(JtxICalObject.PERCENT, sample?.percent, Component.VJOURNAL.name)
@Test fun check_PRIORITY() = insertRetrieveAssertInt(JtxICalObject.PRIORITY, sample?.priority, Component.VJOURNAL.name)
@Test fun check_DUE() = insertRetrieveAssertLong(JtxICalObject.DUE, sample?.due, Component.VJOURNAL.name)
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/at/bitfire/ical4android/JtxICalObject.kt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ open class JtxICalObject(
var geoLong: Double? = null
var location: String? = null
var locationAltrep: String? = null
var geofenceRadius: Int? = null

var uid: String = UUID.randomUUID().toString()

Expand Down Expand Up @@ -229,6 +230,7 @@ open class JtxICalObject(
const val X_PARAM_ATTACH_LABEL = "X-LABEL" // used for filename in KOrganizer
const val X_PARAM_FILENAME = "FILENAME" // used for filename in GNOME Evolution
const val X_PROP_XSTATUS = "X-STATUS" // used to define an extended status (additionally to standard status)
const val X_PROP_GEOFENCE_RADIUS = "X-GEOFENCE-RADIUS" // used to define a Geofence-Radius to notifiy the user when close

/**
* Parses an iCalendar resource and extracts the VTODOs and/or VJOURNALS.
Expand Down Expand Up @@ -543,6 +545,7 @@ open class JtxICalObject(
else -> when(prop.name) {
X_PROP_COMPLETEDTIMEZONE -> iCalObject.completedTimezone = prop.value
X_PROP_XSTATUS -> iCalObject.xstatus = prop.value
X_PROP_GEOFENCE_RADIUS -> iCalObject.geofenceRadius = try { prop.value.toInt() } catch (e: NumberFormatException) { Ical4Android.log.warning("Wrong format for geofenceRadius: ${prop.value}"); null }
else -> iCalObject.unknown.add(Unknown(value = UnknownProperty.toJsonString(prop))) // save the whole property for unknown properties
}
}
Expand Down Expand Up @@ -718,6 +721,9 @@ open class JtxICalObject(
if (geoLat != null && geoLong != null) {
props += Geo(geoLat!!.toBigDecimal(), geoLong!!.toBigDecimal())
}
geofenceRadius?.let { geofenceRadius ->
props += XProperty(X_PROP_GEOFENCE_RADIUS, geofenceRadius.toString())
}
color?.let { props += Color(null, Css3Color.nearestMatch(it).name) }
url?.let {
try {
Expand Down Expand Up @@ -1398,6 +1404,7 @@ duration?.let(props::add)
this.locationAltrep = newData.locationAltrep
this.geoLat = newData.geoLat
this.geoLong = newData.geoLong
this.geofenceRadius = newData.geofenceRadius
this.percent = newData.percent
this.classification = newData.classification
this.status = newData.status
Expand Down Expand Up @@ -1457,6 +1464,7 @@ duration?.let(props::add)
values.getAsDouble(JtxContract.JtxICalObject.GEO_LONG)?.let { geoLong -> this.geoLong = geoLong }
values.getAsString(JtxContract.JtxICalObject.LOCATION)?.let { location -> this.location = location }
values.getAsString(JtxContract.JtxICalObject.LOCATION_ALTREP)?.let { locationAltrep -> this.locationAltrep = locationAltrep }
values.getAsInteger(JtxContract.JtxICalObject.GEOFENCE_RADIUS)?.let { geofenceRadius -> this.geofenceRadius = geofenceRadius }
values.getAsInteger(JtxContract.JtxICalObject.PERCENT)?.let { percent -> this.percent = percent }
values.getAsInteger(JtxContract.JtxICalObject.PRIORITY)?.let { priority -> this.priority = priority }
values.getAsLong(JtxContract.JtxICalObject.DUE)?.let { due -> this.due = due }
Expand Down Expand Up @@ -1682,6 +1690,7 @@ duration?.let(props::add)
put(JtxContract.JtxICalObject.GEO_LONG, geoLong)
put(JtxContract.JtxICalObject.LOCATION, location)
put(JtxContract.JtxICalObject.LOCATION_ALTREP, locationAltrep)
put(JtxContract.JtxICalObject.GEOFENCE_RADIUS, geofenceRadius)
put(JtxContract.JtxICalObject.PERCENT, percent)
put(JtxContract.JtxICalObject.DTSTAMP, dtstamp)
put(JtxContract.JtxICalObject.DTSTART, dtstart)
Expand Down
9 changes: 8 additions & 1 deletion src/main/java/at/techbee/jtx/JtxContract.kt
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ object JtxContract {
const val AUTHORITY = "at.techbee.jtx.provider"

/** The version of this SyncContentProviderContract */
const val VERSION = 4
const val VERSION = 5

/** Constructs an Uri for the Jtx Sync Adapter with the given Account
* @param [account] The account that should be appended to the Base Uri
Expand Down Expand Up @@ -279,6 +279,13 @@ object JtxContract {
*/
const val EXTENDED_STATUS = "xstatus"

/**
* Purpose: Defines the radius for a geofence in meters
* This is put into an extended property in the iCalendar-file
* Type: [String]
*/
const val GEOFENCE_RADIUS = "geofenceRadius"

/**
* Purpose: This property defines the access classification for a calendar component.
* The possible values of a status are defined in the enum [Classification].
Expand Down