mirror of
https://github.com/bitfireAT/davx5-ose.git
synced 2026-02-05 20:51:21 -05:00
Compare commits
7 Commits
split-core
...
1737-enabl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d478deefc | ||
|
|
0362c72a11 | ||
|
|
7cd161f89d | ||
|
|
e61d4b9006 | ||
|
|
5b58facb41 | ||
|
|
425478baa8 | ||
|
|
6e0cde71aa |
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
|
||||
*/
|
||||
|
||||
package at.bitfire.davdroid.push
|
||||
|
||||
import android.content.Context
|
||||
import at.bitfire.davdroid.push.PushRegistrationManager.DistributorPreferences
|
||||
import at.bitfire.davdroid.settings.Settings.EXPLICIT_PUSH_DISABLE
|
||||
import at.bitfire.davdroid.settings.SettingsManager
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import org.unifiedpush.android.connector.UnifiedPush
|
||||
import java.util.logging.Logger
|
||||
import javax.inject.Inject
|
||||
|
||||
class PushDistributorManager @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val logger: Logger,
|
||||
private val settings: SettingsManager,
|
||||
private val distributorPreferences: DistributorPreferences,
|
||||
) {
|
||||
/**
|
||||
* 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)
|
||||
|
||||
/**
|
||||
* Sets or removes (disable push) the distributor.
|
||||
*
|
||||
* @param pushDistributor new distributor or `null` to disable Push
|
||||
*/
|
||||
fun setPushDistributor(pushDistributor: String?) {
|
||||
// Disable UnifiedPush and remove all subscriptions
|
||||
UnifiedPush.removeDistributor(context)
|
||||
update()
|
||||
|
||||
if (pushDistributor != null) {
|
||||
// If a distributor was passed, store it and create/register subscriptions
|
||||
UnifiedPush.saveDistributor(context, pushDistributor)
|
||||
update()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure a distributor is selected if Push is enabled.
|
||||
*
|
||||
* Uses preferences from [distributorPreferences].
|
||||
*/
|
||||
fun update() {
|
||||
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.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,6 @@ import at.bitfire.dav4jvm.ktor.toUrlOrNull
|
||||
import at.bitfire.dav4jvm.property.push.WebDAVPush
|
||||
import at.bitfire.davdroid.db.Collection
|
||||
import at.bitfire.davdroid.db.Service
|
||||
import at.bitfire.davdroid.di.IoDispatcher
|
||||
import at.bitfire.davdroid.network.HttpClientBuilder
|
||||
import at.bitfire.davdroid.push.PushRegistrationManager.Companion.mutex
|
||||
import at.bitfire.davdroid.repository.AccountRepository
|
||||
@@ -36,7 +35,6 @@ import io.ktor.http.HttpHeaders
|
||||
import io.ktor.http.Url
|
||||
import io.ktor.http.isSuccess
|
||||
import io.ktor.utils.io.ByteReadChannel
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import org.unifiedpush.android.connector.UnifiedPush
|
||||
@@ -63,46 +61,25 @@ class PushRegistrationManager @Inject constructor(
|
||||
private val collectionRepository: DavCollectionRepository,
|
||||
@ApplicationContext private val context: Context,
|
||||
private val httpClientBuilder: Provider<HttpClientBuilder>,
|
||||
@IoDispatcher private val ioDispatcher: CoroutineDispatcher,
|
||||
private val logger: Logger,
|
||||
private val serviceRepository: DavServiceRepository
|
||||
private val serviceRepository: DavServiceRepository,
|
||||
private val distributorManager: PushDistributorManager
|
||||
) {
|
||||
|
||||
/**
|
||||
* Sets or removes (disable push) the distributor and updates the subscriptions + worker.
|
||||
*
|
||||
* Uses [update] which is protected by [mutex] so creating/deleting subscriptions doesn't
|
||||
* interfere with other operations.
|
||||
*
|
||||
* @param pushDistributor new distributor or `null` to disable Push
|
||||
*/
|
||||
suspend fun setPushDistributor(pushDistributor: String?) {
|
||||
// Disable UnifiedPush and remove all subscriptions
|
||||
UnifiedPush.removeDistributor(context)
|
||||
update()
|
||||
|
||||
if (pushDistributor != null) {
|
||||
// If a distributor was passed, store it and create/register subscriptions
|
||||
UnifiedPush.saveDistributor(context, pushDistributor)
|
||||
update()
|
||||
}
|
||||
}
|
||||
|
||||
fun getCurrentDistributor() = UnifiedPush.getSavedDistributor(context)
|
||||
|
||||
fun getDistributors() = UnifiedPush.getDistributors(context)
|
||||
|
||||
|
||||
/**
|
||||
* Updates all push registrations and subscriptions so that if Push is available, it's up-to-date and
|
||||
* working for all database services. If Push is not available, existing subscriptions are unregistered.
|
||||
*
|
||||
* Also makes sure that the [PushRegistrationWorker] is enabled if there's a Push-enabled collection.
|
||||
*
|
||||
* Selects the distributor if none is selected yet and Push is not explicitly disabled in settings through the [PushDistributorManager].
|
||||
*
|
||||
* Acquires [mutex] so that this method can't be called twice at the same time, or at the same time
|
||||
* with [update(serviceId)].
|
||||
*/
|
||||
suspend fun update() = mutex.withLock {
|
||||
distributorManager.update()
|
||||
|
||||
for (service in serviceRepository.getAll())
|
||||
updateService(service.id)
|
||||
|
||||
@@ -116,6 +93,7 @@ class PushRegistrationManager @Inject constructor(
|
||||
* as [update()].
|
||||
*/
|
||||
suspend fun update(serviceId: Long) = mutex.withLock {
|
||||
distributorManager.update()
|
||||
updateService(serviceId)
|
||||
updatePeriodicWorker()
|
||||
}
|
||||
@@ -129,7 +107,7 @@ class PushRegistrationManager @Inject constructor(
|
||||
// use service ID from database as UnifiedPush instance name
|
||||
val instance = serviceId.toString()
|
||||
|
||||
val distributorAvailable = getCurrentDistributor() != null
|
||||
val distributorAvailable = distributorManager.getCurrentDistributor() != null
|
||||
if (distributorAvailable)
|
||||
try {
|
||||
val vapid = collectionRepository.getVapidKey(serviceId)
|
||||
@@ -353,6 +331,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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import androidx.lifecycle.viewModelScope
|
||||
import at.bitfire.cert4android.CustomCertStore
|
||||
import at.bitfire.davdroid.BuildConfig
|
||||
import at.bitfire.davdroid.di.IoDispatcher
|
||||
import at.bitfire.davdroid.push.PushDistributorManager
|
||||
import at.bitfire.davdroid.push.PushRegistrationManager
|
||||
import at.bitfire.davdroid.repository.PreferenceRepository
|
||||
import at.bitfire.davdroid.settings.Settings
|
||||
@@ -43,6 +44,7 @@ class AppSettingsModel @Inject constructor(
|
||||
@IoDispatcher private val ioDispatcher: CoroutineDispatcher,
|
||||
private val preferences: PreferenceRepository,
|
||||
private val pushRegistrationManager: PushRegistrationManager,
|
||||
private val pushDistributorManager: PushDistributorManager,
|
||||
private val settings: SettingsManager,
|
||||
tasksAppManager: TasksAppManager
|
||||
) : ViewModel() {
|
||||
@@ -138,10 +140,10 @@ class AppSettingsModel @Inject constructor(
|
||||
* - Makes sure the app is registered with UnifiedPush if there's already a distributor selected.
|
||||
*/
|
||||
private fun loadPushDistributors() {
|
||||
val currentPushDistributor = pushRegistrationManager.getCurrentDistributor()
|
||||
val currentPushDistributor = pushDistributorManager.getCurrentDistributor()
|
||||
_pushDistributor.value = currentPushDistributor
|
||||
|
||||
val pushDistributors = pushRegistrationManager.getDistributors()
|
||||
val pushDistributors = pushDistributorManager.getDistributors()
|
||||
.map { pushDistributor ->
|
||||
try {
|
||||
val applicationInfo = pm.getApplicationInfo(pushDistributor, 0)
|
||||
@@ -165,7 +167,14 @@ class AppSettingsModel @Inject constructor(
|
||||
*/
|
||||
fun updatePushDistributor(pushDistributor: String?) {
|
||||
viewModelScope.launch(ioDispatcher) {
|
||||
pushRegistrationManager.setPushDistributor(pushDistributor)
|
||||
pushDistributorManager.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
|
||||
}
|
||||
|
||||
@@ -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.AccountsDrawerHandler
|
||||
import at.bitfire.davdroid.ui.OseAccountsDrawerHandler
|
||||
import at.bitfire.davdroid.ui.about.AboutActivity
|
||||
@@ -46,6 +48,9 @@ interface OseModules {
|
||||
interface Global {
|
||||
@Binds
|
||||
fun introPageFactory(impl: OseIntroPageFactory): IntroPageFactory
|
||||
|
||||
@Binds
|
||||
fun pushDistributorPreferences(impl: DistributorPreferencesProvider): PushRegistrationManager.DistributorPreferences
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
Reference in New Issue
Block a user