From 4e2640ca017f53fd2cfb75f777c6c11bbf7aaca3 Mon Sep 17 00:00:00 2001 From: Ricki Hirner Date: Wed, 9 Jul 2025 16:35:27 +0200 Subject: [PATCH] Synctools: AndroidEvent companion object moved (#1572) * Update synctools * Refactor LocalCalendar to use Hilt * Update synctools --- .../davdroid/resource/LocalCalendarTest.kt | 43 +++++++--------- .../davdroid/resource/LocalEventTest.kt | 49 ++++++++++--------- .../repository/DavCollectionRepository.kt | 7 ++- .../davdroid/resource/LocalCalendar.kt | 22 ++++++--- .../davdroid/resource/LocalCalendarStore.kt | 5 +- gradle/libs.versions.toml | 2 +- 6 files changed, 67 insertions(+), 61 deletions(-) diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalCalendarTest.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalCalendarTest.kt index 06ed862c7..e6e75b467 100644 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalCalendarTest.kt +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalCalendarTest.kt @@ -18,56 +18,51 @@ import at.bitfire.ical4android.util.MiscUtils.asSyncAdapter import at.bitfire.ical4android.util.MiscUtils.closeCompat import at.bitfire.synctools.storage.calendar.AndroidCalendarProvider import at.bitfire.synctools.test.InitCalendarProviderRule +import dagger.hilt.android.testing.HiltAndroidRule +import dagger.hilt.android.testing.HiltAndroidTest import net.fortuna.ical4j.model.property.DtStart import net.fortuna.ical4j.model.property.RRule import net.fortuna.ical4j.model.property.RecurrenceId import net.fortuna.ical4j.model.property.Status import org.junit.After -import org.junit.AfterClass import org.junit.Assert.assertEquals import org.junit.Before -import org.junit.BeforeClass -import org.junit.ClassRule +import org.junit.Rule import org.junit.Test import org.junit.rules.TestRule +import javax.inject.Inject +@HiltAndroidTest class LocalCalendarTest { - companion object { + @get:Rule + val hiltRule = HiltAndroidRule(this) - @JvmField - @ClassRule - val initCalendarProviderRule: TestRule = InitCalendarProviderRule.initialize() + @get:Rule + val initCalendarProviderRule: TestRule = InitCalendarProviderRule.initialize() - private lateinit var client: ContentProviderClient - - @BeforeClass - @JvmStatic - fun setUpClass() { - val context = InstrumentationRegistry.getInstrumentation().targetContext - client = context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)!! - } - - @AfterClass - @JvmStatic - fun tearDownClass() { - client.closeCompat() - } - - } + @Inject + lateinit var localCalendarFactory: LocalCalendar.Factory private val account = Account("LocalCalendarTest", ACCOUNT_TYPE_LOCAL) + private lateinit var client: ContentProviderClient private lateinit var calendar: LocalCalendar @Before fun setUp() { + hiltRule.inject() + + val context = InstrumentationRegistry.getInstrumentation().targetContext + client = context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)!! + val provider = AndroidCalendarProvider(account, client) - calendar = LocalCalendar(provider.createAndGetCalendar(ContentValues())) + calendar = localCalendarFactory.create(provider.createAndGetCalendar(ContentValues())) } @After fun tearDown() { calendar.androidCalendar.delete() + client.closeCompat() } diff --git a/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalEventTest.kt b/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalEventTest.kt index a126104e1..25183dcc4 100644 --- a/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalEventTest.kt +++ b/app/src/androidTest/kotlin/at/bitfire/davdroid/resource/LocalEventTest.kt @@ -4,6 +4,7 @@ package at.bitfire.davdroid.resource +import android.Manifest import android.accounts.Account import android.content.ContentProviderClient import android.content.ContentUris @@ -12,37 +13,57 @@ import android.provider.CalendarContract import android.provider.CalendarContract.ACCOUNT_TYPE_LOCAL import android.provider.CalendarContract.Events import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.rule.GrantPermissionRule import at.bitfire.ical4android.AndroidEvent import at.bitfire.ical4android.Event import at.bitfire.ical4android.util.MiscUtils.closeCompat import at.bitfire.synctools.storage.calendar.AndroidCalendarProvider import at.techbee.jtx.JtxContract.asSyncAdapter +import dagger.hilt.android.testing.HiltAndroidRule +import dagger.hilt.android.testing.HiltAndroidTest import net.fortuna.ical4j.model.property.DtStart import net.fortuna.ical4j.model.property.RRule import net.fortuna.ical4j.model.property.RecurrenceId import net.fortuna.ical4j.model.property.Status import org.junit.After -import org.junit.AfterClass import org.junit.Assert.assertEquals import org.junit.Before -import org.junit.BeforeClass +import org.junit.Rule import org.junit.Test import java.util.UUID +import javax.inject.Inject +@HiltAndroidTest class LocalEventTest { + @get:Rule + val hiltRule = HiltAndroidRule(this) + + @get:Rule + val permissionRule = GrantPermissionRule.grant(Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR) + + @Inject + lateinit var localCalendarFactory: LocalCalendar.Factory + private val account = Account("LocalCalendarTest", ACCOUNT_TYPE_LOCAL) + private lateinit var client: ContentProviderClient private lateinit var calendar: LocalCalendar @Before fun setUp() { + hiltRule.inject() + + val context = InstrumentationRegistry.getInstrumentation().targetContext + client = context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)!! + val provider = AndroidCalendarProvider(account, client) - calendar = LocalCalendar(provider.createAndGetCalendar(ContentValues())) + calendar = localCalendarFactory.create(provider.createAndGetCalendar(ContentValues())) } @After - fun removeCalendar() { + fun tearDown() { calendar.androidCalendar.delete() + client.closeCompat() } @@ -211,24 +232,4 @@ class LocalEventTest { } } - - companion object { - - private lateinit var client: ContentProviderClient - - @BeforeClass - @JvmStatic - fun setUpClass() { - val context = InstrumentationRegistry.getInstrumentation().targetContext - client = context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)!! - } - - @AfterClass - @JvmStatic - fun tearDownClass() { - client.closeCompat() - } - - } - } \ No newline at end of file diff --git a/app/src/main/kotlin/at/bitfire/davdroid/repository/DavCollectionRepository.kt b/app/src/main/kotlin/at/bitfire/davdroid/repository/DavCollectionRepository.kt index bb796b2c7..5bc4fea0b 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/repository/DavCollectionRepository.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/repository/DavCollectionRepository.kt @@ -33,7 +33,6 @@ import at.bitfire.davdroid.di.IoDispatcher import at.bitfire.davdroid.network.HttpClient import at.bitfire.davdroid.servicedetection.RefreshCollectionsWorker import at.bitfire.davdroid.util.DavUtils -import at.bitfire.ical4android.util.DateUtils import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.runInterruptible @@ -42,6 +41,7 @@ import net.fortuna.ical4j.model.Component import net.fortuna.ical4j.model.ComponentList import net.fortuna.ical4j.model.Property import net.fortuna.ical4j.model.PropertyList +import net.fortuna.ical4j.model.TimeZoneRegistryFactory import net.fortuna.ical4j.model.component.VTimeZone import net.fortuna.ical4j.model.property.Version import okhttp3.HttpUrl @@ -417,6 +417,9 @@ class DavCollectionRepository @Inject constructor( return writer.toString() } - private fun getVTimeZone(tzId: String): VTimeZone? = DateUtils.ical4jTimeZone(tzId)?.vTimeZone + private fun getVTimeZone(tzId: String): VTimeZone? { + val tzRegistry = TimeZoneRegistryFactory.getInstance().createRegistry() + return tzRegistry.getTimeZone(tzId)?.vTimeZone + } } \ No newline at end of file diff --git a/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalCalendar.kt b/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalCalendar.kt index 098776c67..6f3b0907c 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalCalendar.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalCalendar.kt @@ -14,6 +14,9 @@ import at.bitfire.ical4android.util.MiscUtils.asSyncAdapter import at.bitfire.synctools.storage.BatchOperation import at.bitfire.synctools.storage.calendar.AndroidCalendar import at.bitfire.synctools.storage.calendar.CalendarBatchOperation +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject import java.util.LinkedList import java.util.logging.Level import java.util.logging.Logger @@ -23,12 +26,15 @@ import java.util.logging.Logger * * [Calendars._SYNC_ID] corresponds to the database collection ID ([at.bitfire.davdroid.db.Collection.id]). */ -class LocalCalendar( - val androidCalendar: AndroidCalendar +class LocalCalendar @AssistedInject constructor( + @Assisted val androidCalendar: AndroidCalendar, + private val logger: Logger ) : LocalCollection { - private val logger: Logger - get() = Logger.getLogger(javaClass.name) + @AssistedFactory + interface Factory { + fun create(androidCalendar: AndroidCalendar): LocalCalendar + } override val dbCollectionId: Long? @@ -198,15 +204,15 @@ class LocalCalendar( "${Events.DIRTY} AND NOT ${Events.DELETED} AND ${Events.ORIGINAL_ID} IS NULL", null ) { values -> - val eventID = values.getAsLong(Events._ID) + val eventId = values.getAsLong(Events._ID) // get number of instances - val numEventInstances = AndroidEvent.numInstances(androidCalendar.client, androidCalendar.account, eventID) + val numEventInstances = androidCalendar.numInstances(eventId) // delete event if there are no instances if (numEventInstances == 0) { - logger.fine("Marking event #$eventID without instances as deleted") - AndroidEvent.markAsDeleted(androidCalendar.client, androidCalendar.account, eventID) + logger.fine("Marking event #$eventId without instances as deleted") + androidCalendar.updateEvent(eventId, contentValuesOf(Events.DELETED to 1)) } } } diff --git a/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalCalendarStore.kt b/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalCalendarStore.kt index bf7fad24c..ff019f684 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalCalendarStore.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/resource/LocalCalendarStore.kt @@ -31,6 +31,7 @@ import javax.inject.Inject class LocalCalendarStore @Inject constructor( @ApplicationContext private val context: Context, private val accountSettingsFactory: AccountSettings.Factory, + private val localCalendarFactory: LocalCalendar.Factory, private val logger: Logger, private val serviceRepository: DavServiceRepository ): LocalDataStore { @@ -71,13 +72,13 @@ class LocalCalendarStore @Inject constructor( logger.log(Level.INFO, "Adding local calendar", values) val provider = AndroidCalendarProvider(account, client) - return LocalCalendar(provider.createAndGetCalendar(values)) + return localCalendarFactory.create(provider.createAndGetCalendar(values)) } override fun getAll(account: Account, client: ContentProviderClient) = AndroidCalendarProvider(account, client) .findCalendars("${Calendars.SYNC_EVENTS}!=0", null) - .map { LocalCalendar(it) } + .map { localCalendarFactory.create(it) } override fun update(client: ContentProviderClient, localCollection: LocalCalendar, fromCollection: Collection) { val accountSettings = accountSettingsFactory.create(localCollection.androidCalendar.account) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 46fd2e050..ccb171cd6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -20,7 +20,7 @@ androidx-test-junit = "1.2.1" androidx-work = "2.10.2" bitfire-cert4android = "b67ba86d31" bitfire-dav4jvm = "acbfbacbaf" -bitfire-synctools = "a365b91c04" +bitfire-synctools = "2bef0eee14" compose-accompanist = "0.37.3" compose-bom = "2025.06.01" dnsjava = "3.6.3"