Added automatic push distributor selection

This commit is contained in:
Arnau Mora
2025-10-25 12:55:14 +02:00
committed by Ricki Hirner
parent a938b511cd
commit 6e0cde71aa
5 changed files with 78 additions and 1 deletions

View File

@@ -26,6 +26,8 @@ import at.bitfire.davdroid.push.PushRegistrationManager.Companion.mutex
import at.bitfire.davdroid.repository.AccountRepository
import at.bitfire.davdroid.repository.DavCollectionRepository
import at.bitfire.davdroid.repository.DavServiceRepository
import at.bitfire.davdroid.settings.Settings.EXPLICIT_PUSH_DISABLE
import at.bitfire.davdroid.settings.SettingsManager
import at.bitfire.davdroid.sync.account.InvalidAccountException
import dagger.Lazy
import dagger.hilt.android.qualifiers.ApplicationContext
@@ -64,7 +66,9 @@ class PushRegistrationManager @Inject constructor(
private val httpClientBuilder: Provider<HttpClientBuilder>,
@IoDispatcher private val ioDispatcher: CoroutineDispatcher,
private val logger: Logger,
private val serviceRepository: DavServiceRepository
private val serviceRepository: DavServiceRepository,
private val settings: SettingsManager,
private val distributorPreferences: DistributorPreferences,
) {
/**
@@ -87,8 +91,16 @@ class PushRegistrationManager @Inject constructor(
}
}
/**
* Get the distributor registered by the user.
* @return The distributor package name if any, else `null`.
*/
fun getCurrentDistributor() = UnifiedPush.getSavedDistributor(context)
/**
* Get a list of available distributors installed on the system.
* @return The list of distributor's package name.
*/
fun getDistributors() = UnifiedPush.getDistributors(context)
@@ -102,6 +114,27 @@ class PushRegistrationManager @Inject constructor(
* with [update(serviceId)].
*/
suspend fun update() = mutex.withLock {
val currentDistributor = getCurrentDistributor()
val isPushDisabled = settings.getBooleanOrNull(EXPLICIT_PUSH_DISABLE)
if (currentDistributor == null) {
if (isPushDisabled == true) {
logger.info("Push is explicitly disabled, no distributor will be selected.")
} else {
val availableDistributors = getDistributors()
if (availableDistributors.isNotEmpty()) {
logger.fine("No Push distributor selected, but ${availableDistributors.size} distributors are available.")
// select preferred distributor if available, otherwise first available
val distributor = distributorPreferences.packageNames.firstNotNullOfOrNull { preferredPackageName ->
availableDistributors.find { it == preferredPackageName }
} ?: availableDistributors.first()
logger.fine("Automatically selecting Push distributor: $distributor")
UnifiedPush.saveDistributor(context, distributor)
} else {
logger.fine("No Push distributor selected and no distributors are available.")
}
}
}
for (service in serviceRepository.getAll())
updateService(service.id)
@@ -352,6 +385,19 @@ class PushRegistrationManager @Inject constructor(
}
/**
* Allows preferring certain distributors over others.
*/
interface DistributorPreferences {
/**
* A list of package names ordered by preference.
* If any of those is available, it will be automatically selected.
* Otherwise, another available distributor will be chosen automatically.
*/
val packageNames: List<String>
}
companion object {
private const val WORKER_UNIQUE_NAME = "push-registration"

View File

@@ -65,5 +65,12 @@ object Settings {
/** max. number of accounts */
const val MAX_ACCOUNTS = "max_accounts"
/**
* By default, a push distributor is automatically selected when needed. However, the user can choose to disable push completely.
* This setting reflects that choice.
*/
const val EXPLICIT_PUSH_DISABLE = "push_disable"
}

View File

@@ -164,6 +164,13 @@ class AppSettingsModel @Inject constructor(
viewModelScope.launch(ioDispatcher) {
pushRegistrationManager.setPushDistributor(pushDistributor)
if (pushDistributor == null) {
// Disable push explicitly, this will disable the automatic distributor selector
settings.putBoolean(Settings.EXPLICIT_PUSH_DISABLE, true)
} else {
settings.remove(Settings.EXPLICIT_PUSH_DISABLE)
}
_pushDistributor.value = pushDistributor
}
}

View File

@@ -4,6 +4,8 @@
package at.bitfire.davdroid.di
import at.bitfire.davdroid.push.DistributorPreferencesProvider
import at.bitfire.davdroid.push.PushRegistrationManager
import at.bitfire.davdroid.ui.intro.OseIntroPageFactory
import at.bitfire.davdroid.ui.AboutActivity
@@ -47,6 +49,9 @@ interface OseModules {
interface Global {
@Binds
fun introPageFactory(impl: OseIntroPageFactory): IntroPageFactory
@Binds
fun pushDistributorPreferences(impl: DistributorPreferencesProvider): PushRegistrationManager.DistributorPreferences
}
}

View File

@@ -0,0 +1,12 @@
/*
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
*/
package at.bitfire.davdroid.push
import javax.inject.Inject
class DistributorPreferencesProvider @Inject constructor() : PushRegistrationManager.DistributorPreferences {
// No special preferences for OSE flavor, select the first distributor available
override val packageNames: List<String> = emptyList()
}