Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ce7ab572 authored by Fahim Salam Chowdhury's avatar Fahim Salam Chowdhury 👽
Browse files

Refactor syncAdapterServices

various syncAdapter services have similar implementation. To make the
implementation simple, we need to inherit these syncAdapter instead
copy-pasting same code.
parent b6c31cf6
Loading
Loading
Loading
Loading
Loading
+48 −14
Original line number Diff line number Diff line
@@ -28,17 +28,23 @@ import kotlin.collections.component1
import kotlin.collections.component2
import kotlin.collections.set

class CalendarsSyncAdapterService: SyncAdapterService() {
open class CalendarsSyncAdapterService : SyncAdapterService() {

    override fun syncAdapter() = CalendarsSyncAdapter(this, appDatabase)


    class CalendarsSyncAdapter(
        context: Context,
        appDatabase: AppDatabase
    ) : SyncAdapter(context, appDatabase) {

        override fun sync(account: Account, extras: Bundle, authority: String, httpClient: Lazy<HttpClient>, provider: ContentProviderClient, syncResult: SyncResult) {
        override fun sync(
            account: Account,
            extras: Bundle,
            authority: String,
            httpClient: Lazy<HttpClient>,
            provider: ContentProviderClient,
            syncResult: SyncResult
        ) {
            try {
                val accountSettings = AccountSettings(context, account)

@@ -46,7 +52,10 @@ class CalendarsSyncAdapterService: SyncAdapterService() {
                   - sync conditions (e.g. "sync only in WiFi") are not met AND
                   - this is is an automatic sync (i.e. manual syncs are run regardless of sync conditions)
                 */
                if (!extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL) && !checkSyncConditions(accountSettings))
                if (!extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL) && !checkSyncConditions(
                        accountSettings
                    )
                )
                    return

                if (accountSettings.getEventColors())
@@ -58,11 +67,26 @@ class CalendarsSyncAdapterService: SyncAdapterService() {

                val priorityCalendars = priorityCollections(extras)
                val calendars = AndroidCalendar
                        .find(account, provider, LocalCalendar.Factory, "${CalendarContract.Calendars.SYNC_EVENTS}!=0", null)
                    .find(
                        account,
                        provider,
                        LocalCalendar.Factory,
                        "${CalendarContract.Calendars.SYNC_EVENTS}!=0",
                        null
                    )
                    .sortedByDescending { priorityCalendars.contains(it.id) }
                for (calendar in calendars) {
                    Logger.log.info("Synchronizing calendar #${calendar.id}, URL: ${calendar.name}")
                    CalendarSyncManager(context, account, accountSettings, extras, httpClient.value, authority, syncResult, calendar).let {
                    CalendarSyncManager(
                        context,
                        account,
                        accountSettings,
                        extras,
                        httpClient.value,
                        authority,
                        syncResult,
                        calendar
                    ).let {
                        val authState = accountSettings.credentials().authState
                        if (authState != null) {
                            if (authState.needsTokenRefresh) {
@@ -88,16 +112,16 @@ class CalendarsSyncAdapterService: SyncAdapterService() {
                                    )
                                    object : AsyncTask<Void, Void, Void>() {
                                        override fun doInBackground(vararg params: Void): Void? {
                                            it.performSync()
                                            it.performSyncWithRetry()
                                            return null
                                        }
                                    }.execute()
                                }
                            } else {
                                it.performSync()
                                it.performSyncWithRetry()
                            }
                        } else {
                            it.performSync()
                            it.performSyncWithRetry()
                        }
                    }
                }
@@ -107,7 +131,11 @@ class CalendarsSyncAdapterService: SyncAdapterService() {
            Logger.log.info("Calendar sync complete")
        }

        private fun updateLocalCalendars(provider: ContentProviderClient, account: Account, settings: AccountSettings) {
        private fun updateLocalCalendars(
            provider: ContentProviderClient,
            account: Account,
            settings: AccountSettings
        ) {
            val service = db.serviceDao().getByAccountAndType(account.name, Service.TYPE_CALDAV)

            val remoteCalendars = mutableMapOf<HttpUrl, Collection>()
@@ -118,7 +146,13 @@ class CalendarsSyncAdapterService: SyncAdapterService() {

            // delete/update local calendars
            val updateColors = settings.getManageCalendarColors()
            for (calendar in AndroidCalendar.find(account, provider, LocalCalendar.Factory, null, null))
            for (calendar in AndroidCalendar.find(
                account,
                provider,
                LocalCalendar.Factory,
                null,
                null
            ))
                calendar.name?.let {
                    val url = it.toHttpUrl()
                    val info = remoteCalendars[url]
+47 −0
Original line number Diff line number Diff line
/*
 * Copyright MURENA SAS 2023
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package at.bitfire.davdroid.syncadapter

import android.accounts.Account
import android.content.ContentProviderClient
import android.content.Context
import android.content.SyncResult
import android.os.Bundle
import at.bitfire.davdroid.HttpClient
import at.bitfire.davdroid.db.AppDatabase

abstract class DummySyncAdapterService : SyncAdapterService() {

    override fun syncAdapter() = DummySyncAdapter(this, appDatabase)


    class DummySyncAdapter(
        context: Context,
        db: AppDatabase
    ) : SyncAdapter(context, db) {
        override fun sync(
            account: Account,
            extras: Bundle,
            authority: String,
            httpClient: Lazy<HttpClient>,
            provider: ContentProviderClient,
            syncResult: SyncResult
        ) {
            // Unused
        }
    }
}
+1 −28
Original line number Diff line number Diff line
@@ -16,31 +16,4 @@

package at.bitfire.davdroid.syncadapter

import android.accounts.Account
import android.content.*
import android.os.Bundle
import at.bitfire.davdroid.HttpClient
import at.bitfire.davdroid.db.AppDatabase

class EeloAppDataSyncAdapterService : SyncAdapterService() {

    override fun syncAdapter() = EeloAppDataSyncAdapter(this, appDatabase)

    class EeloAppDataSyncAdapter(
            context: Context,
            db: AppDatabase
    ): SyncAdapter(context, db) {

        override fun sync(
            account: Account,
            extras: Bundle,
            authority: String,
            httpClient: Lazy<HttpClient>,
            provider: ContentProviderClient,
            syncResult: SyncResult
        ) {
            // Unused
        }
    }
}
class EeloAppDataSyncAdapterService : DummySyncAdapterService()
 No newline at end of file
+1 −174
Original line number Diff line number Diff line
@@ -16,177 +16,4 @@

package at.bitfire.davdroid.syncadapter

import android.accounts.Account
import android.content.ContentProviderClient
import android.content.ContentResolver
import android.content.Context
import android.content.SyncResult
import android.os.AsyncTask
import android.os.Bundle
import android.provider.CalendarContract
import at.bitfire.davdroid.HttpClient
import at.bitfire.davdroid.db.AppDatabase
import at.bitfire.davdroid.db.Collection
import at.bitfire.davdroid.db.Credentials
import at.bitfire.davdroid.db.Service
import at.bitfire.davdroid.log.Logger
import at.bitfire.davdroid.resource.LocalCalendar
import at.bitfire.davdroid.settings.AccountSettings
import at.bitfire.ical4android.AndroidCalendar
import net.openid.appauth.AuthorizationService
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import java.util.logging.Level

class EeloCalendarsSyncAdapterService : SyncAdapterService() {

    override fun syncAdapter() = CalendarsSyncAdapter(this, appDatabase)

    class CalendarsSyncAdapter(
        context: Context,
        appDatabase: AppDatabase
    ) : SyncAdapter(context, appDatabase) {
        override fun sync(
            account: Account,
            extras: Bundle,
            authority: String,
            httpClient: Lazy<HttpClient>,
            provider: ContentProviderClient,
            syncResult: SyncResult
        ) {
            try {
                val accountSettings = AccountSettings(context, account)

                /* don't run sync if
                   - sync conditions (e.g. "sync only in WiFi") are not met AND
                   - this is is an automatic sync (i.e. manual syncs are run regardless of sync conditions)
                 */
                if (!extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL) && !checkSyncConditions(
                        accountSettings
                    )
                )
                    return

                if (accountSettings.getEventColors())
                    AndroidCalendar.insertColors(provider, account)
                else
                    AndroidCalendar.removeColors(provider, account)

                updateLocalCalendars(provider, account, accountSettings)

                val priorityCalendars = priorityCollections(extras)
                val calendars = AndroidCalendar
                    .find(
                        account,
                        provider,
                        LocalCalendar.Factory,
                        "${CalendarContract.Calendars.SYNC_EVENTS}!=0",
                        null
                    )
                    .sortedByDescending { priorityCalendars.contains(it.id) }
                for (calendar in calendars) {
                    Logger.log.info("Synchronizing calendar #${calendar.id}, URL: ${calendar.name}")
                    CalendarSyncManager(
                        context,
                        account,
                        accountSettings,
                        extras,
                        httpClient.value,
                        authority,
                        syncResult,
                        calendar
                    ).let {
                        val authState = accountSettings.credentials().authState
                        if (authState != null) {
                            if (authState.needsTokenRefresh) {
                                val tokenRequest = authState.createTokenRefreshRequest()

                                AuthorizationService(context).performTokenRequest(tokenRequest) { tokenResponse, ex ->
                                    authState.update(tokenResponse, ex)
                                    accountSettings.credentials(
                                        Credentials(
                                            account.name,
                                            null,
                                            authState,
                                            null
                                        )
                                    )
                                    it.accountSettings.credentials(
                                        Credentials(
                                            it.account.name,
                                            null,
                                            authState,
                                            null
                                        )
                                    )
                                    object : AsyncTask<Void, Void, Void>() {
                                        override fun doInBackground(vararg params: Void): Void? {
                                            it.performSyncWithRetry()
                                            return null
                                        }
                                    }.execute()
                                }
                            } else {
                                it.performSyncWithRetry()
                            }
                        } else {
                            it.performSyncWithRetry()
                        }
                    }
                }
            } catch (e: Exception) {
                Logger.log.log(Level.SEVERE, "Couldn't sync calendars", e)
            }
            Logger.log.info("Calendar sync complete")
        }

        private fun updateLocalCalendars(
            provider: ContentProviderClient,
            account: Account,
            settings: AccountSettings
        ) {
            val service = db.serviceDao().getByAccountAndType(account.name, Service.TYPE_CALDAV)

            val remoteCalendars = mutableMapOf<HttpUrl, Collection>()

            if (service != null) {
                for (collection in db.collectionDao().getSyncCalendars(service.id)) {
                    remoteCalendars[collection.url] = collection
                }
            }

            // delete/update local calendars
            val updateColors = settings.getManageCalendarColors()
            for (calendar in AndroidCalendar.find(
                account,
                provider,
                LocalCalendar.Factory,
                null,
                null
            ))
                calendar.name?.let {
                    val url = it.toHttpUrlOrNull()!!
                    val info = remoteCalendars[url]

                    if (info == null) {
                        Logger.log.log(Level.INFO, "Deleting obsolete local calendar", url)
                        calendar.delete()
                    } else {
                        // remote CollectionInfo found for this local collection, update data
                        Logger.log.log(Level.FINE, "Updating local calendar $url", info)
                        calendar.update(info, updateColors)
                        // we already have a local calendar for this remote collection, don't take into consideration anymore
                        remoteCalendars -= url
                    }
                }

            // create new local calendars
            for ((_, info) in remoteCalendars) {
                Logger.log.log(Level.INFO, "Adding local calendar", info)
                LocalCalendar.create(account, provider, info)
            }
        }

    }
}
class EeloCalendarsSyncAdapterService : CalendarsSyncAdapterService()
+1 −29
Original line number Diff line number Diff line
@@ -16,32 +16,4 @@

package at.bitfire.davdroid.syncadapter

import android.accounts.Account
import android.content.*
import android.os.Bundle
import at.bitfire.davdroid.HttpClient
import at.bitfire.davdroid.MailAccountSyncHelper
import at.bitfire.davdroid.db.AppDatabase

class EeloEmailSyncAdapterService : SyncAdapterService() {

    override fun syncAdapter() = EeloEmailSyncAdapter(this, appDatabase)


    class EeloEmailSyncAdapter(
            context: Context,
            db: AppDatabase
    ): SyncAdapter(context, db) {
        override fun sync(
            account: Account,
            extras: Bundle,
            authority: String,
            httpClient: Lazy<HttpClient>,
            provider: ContentProviderClient,
            syncResult: SyncResult
        ) {
            MailAccountSyncHelper.syncMailAccounts(context.applicationContext)
        }
    }
}
class EeloEmailSyncAdapterService : EmailSyncAdapterService()
Loading