Ensure that disabling (resp. enabling) notification unregisters (resp. registers) the pusher

This commit is contained in:
Benoit Marty 2025-11-13 17:46:49 +01:00
parent c7d4689473
commit d3339872ff
11 changed files with 441 additions and 355 deletions

View file

@ -15,8 +15,10 @@ import dev.zacsweers.metro.binding
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
import io.element.android.libraries.push.api.GetCurrentPushProvider
import io.element.android.libraries.push.api.PushService
import io.element.android.libraries.push.api.PusherRegistrationFailure
import io.element.android.libraries.push.api.history.PushHistoryItem
import io.element.android.libraries.push.impl.push.MutableBatteryOptimizationStore
import io.element.android.libraries.push.impl.store.PushDataStore
@ -24,11 +26,13 @@ import io.element.android.libraries.push.impl.test.TestPush
import io.element.android.libraries.push.impl.unregistration.ServiceUnregisteredHandler
import io.element.android.libraries.pushproviders.api.Distributor
import io.element.android.libraries.pushproviders.api.PushProvider
import io.element.android.libraries.pushproviders.api.RegistrationFailure
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecretStore
import io.element.android.libraries.sessionstorage.api.observer.SessionListener
import io.element.android.libraries.sessionstorage.api.observer.SessionObserver
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import timber.log.Timber
@ContributesBinding(AppScope::class, binding = binding<PushService>())
@ -84,6 +88,59 @@ class DefaultPushService(
return pushProvider.registerWith(matrixClient, distributor)
}
override suspend fun ensurePusherIsRegistered(matrixClient: MatrixClient): Result<Unit> {
val verificationStatus = matrixClient.sessionVerificationService.sessionVerifiedStatus.first()
if (verificationStatus != SessionVerifiedStatus.Verified) {
return Result.failure<Unit>(PusherRegistrationFailure.AccountNotVerified())
.also { Timber.w("Account is not verified") }
}
Timber.d("Ensure pusher is registered")
val currentPushProvider = getCurrentPushProvider(matrixClient.sessionId)
val result = if (currentPushProvider == null) {
Timber.d("Register with the first available push provider with at least one distributor")
val pushProvider = getAvailablePushProviders()
.firstOrNull { it.getDistributors().isNotEmpty() }
// Else fallback to the first available push provider (the list should never be empty)
?: getAvailablePushProviders().firstOrNull()
?: return Result.failure<Unit>(PusherRegistrationFailure.NoProvidersAvailable())
.also { Timber.w("No push providers available") }
val distributor = pushProvider.getDistributors().firstOrNull()
?: return Result.failure<Unit>(PusherRegistrationFailure.NoDistributorsAvailable())
.also { Timber.w("No distributors available") }
.also {
// In this case, consider the push provider is chosen.
selectPushProvider(matrixClient.sessionId, pushProvider)
}
registerWith(matrixClient, pushProvider, distributor)
} else {
val currentPushDistributor = currentPushProvider.getCurrentDistributor(matrixClient.sessionId)
if (currentPushDistributor == null) {
Timber.d("Register with the first available distributor")
val distributor = currentPushProvider.getDistributors().firstOrNull()
?: return Result.failure<Unit>(PusherRegistrationFailure.NoDistributorsAvailable())
.also { Timber.w("No distributors available") }
registerWith(matrixClient, currentPushProvider, distributor)
} else {
Timber.d("Re-register with the current distributor")
registerWith(matrixClient, currentPushProvider, currentPushDistributor)
}
}
return result.fold(
onSuccess = {
Timber.d("Pusher registered")
Result.success(Unit)
},
onFailure = {
Timber.e(it, "Failed to register pusher")
if (it is RegistrationFailure) {
Result.failure(PusherRegistrationFailure.RegistrationFailure(it.clientException, it.isRegisteringAgain))
} else {
Result.failure(it)
}
}
)
}
override suspend fun selectPushProvider(
sessionId: SessionId,
pushProvider: PushProvider,