diff --git a/app/src/main/kotlin/at/bitfire/davdroid/push/PushRegistrationManager.kt b/app/src/main/kotlin/at/bitfire/davdroid/push/PushRegistrationManager.kt index 3f9cd7a9ef..e710b89504 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/push/PushRegistrationManager.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/push/PushRegistrationManager.kt @@ -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, @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 + } + + companion object { private const val WORKER_UNIQUE_NAME = "push-registration" diff --git a/app/src/main/kotlin/at/bitfire/davdroid/settings/Settings.kt b/app/src/main/kotlin/at/bitfire/davdroid/settings/Settings.kt index 985ee858bf..f94e54aa82 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/settings/Settings.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/settings/Settings.kt @@ -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" } \ No newline at end of file diff --git a/app/src/main/kotlin/at/bitfire/davdroid/ui/AppSettingsModel.kt b/app/src/main/kotlin/at/bitfire/davdroid/ui/AppSettingsModel.kt index 579379b9b3..43c7161516 100644 --- a/app/src/main/kotlin/at/bitfire/davdroid/ui/AppSettingsModel.kt +++ b/app/src/main/kotlin/at/bitfire/davdroid/ui/AppSettingsModel.kt @@ -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 } } diff --git a/app/src/ose/kotlin/at/bitfire/davdroid/di/OseFlavorModule.kt b/app/src/ose/kotlin/at/bitfire/davdroid/di/OseFlavorModule.kt index 6db4362ad6..57d5d6b160 100644 --- a/app/src/ose/kotlin/at/bitfire/davdroid/di/OseFlavorModule.kt +++ b/app/src/ose/kotlin/at/bitfire/davdroid/di/OseFlavorModule.kt @@ -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 } } \ No newline at end of file diff --git a/app/src/ose/kotlin/at/bitfire/davdroid/push/DistributorPreferencesProvider.kt b/app/src/ose/kotlin/at/bitfire/davdroid/push/DistributorPreferencesProvider.kt new file mode 100644 index 0000000000..c83b7b9e61 --- /dev/null +++ b/app/src/ose/kotlin/at/bitfire/davdroid/push/DistributorPreferencesProvider.kt @@ -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 = emptyList() +}