From a77a6b88ee195a845af3c908a58b1db741312c6c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 30 Oct 2024 11:53:32 +0100 Subject: [PATCH] Now that FCM token can be rotated, let the `FirebaseTokenTest` observe the value. --- .../pushproviders/firebase/FirebaseStore.kt | 21 ++++++++++ .../troubleshoot/FirebaseTokenTest.kt | 38 +++++++++++-------- .../firebase/InMemoryFirebaseStore.kt | 5 +++ 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/FirebaseStore.kt b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/FirebaseStore.kt index 2058f716d4..4ad3619454 100644 --- a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/FirebaseStore.kt +++ b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/FirebaseStore.kt @@ -11,6 +11,10 @@ import android.content.SharedPreferences import androidx.core.content.edit import com.squareup.anvil.annotations.ContributesBinding import io.element.android.libraries.di.AppScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.onCompletion +import kotlinx.coroutines.flow.onStart import javax.inject.Inject /** @@ -18,6 +22,7 @@ import javax.inject.Inject */ interface FirebaseStore { fun getFcmToken(): String? + fun fcmTokenFlow(): Flow fun storeFcmToken(token: String?) } @@ -29,6 +34,22 @@ class SharedPreferencesFirebaseStore @Inject constructor( return sharedPreferences.getString(PREFS_KEY_FCM_TOKEN, null) } + override fun fcmTokenFlow(): Flow { + val flow = MutableStateFlow(getFcmToken()) + val listener = SharedPreferences.OnSharedPreferenceChangeListener { _, k -> + if (k == PREFS_KEY_FCM_TOKEN) { + try { + flow.value = getFcmToken() + } catch (e: Exception) { + flow.value = null + } + } + } + return flow + .onStart { sharedPreferences.registerOnSharedPreferenceChangeListener(listener) } + .onCompletion { sharedPreferences.unregisterOnSharedPreferenceChangeListener(listener) } + } + override fun storeFcmToken(token: String?) { sharedPreferences.edit { putString(PREFS_KEY_FCM_TOKEN, token) diff --git a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTest.kt b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTest.kt index 0c085e42fb..7d04239669 100644 --- a/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTest.kt +++ b/libraries/pushproviders/firebase/src/main/kotlin/io/element/android/libraries/pushproviders/firebase/troubleshoot/FirebaseTokenTest.kt @@ -19,7 +19,10 @@ import io.element.android.libraries.troubleshoot.api.test.NotificationTroublesho import io.element.android.libraries.troubleshoot.api.test.TestFilterData import io.element.android.services.toolbox.api.strings.StringProvider import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import javax.inject.Inject @ContributesMultibinding(AppScope::class) @@ -41,23 +44,28 @@ class FirebaseTokenTest @Inject constructor( return data.currentPushProviderName == FirebaseConfig.NAME } + private var currentJob: Job? = null override suspend fun run(coroutineScope: CoroutineScope) { + currentJob?.cancel() delegate.start() - val token = firebaseStore.getFcmToken() - if (token != null) { - delegate.updateState( - description = stringProvider.getString( - R.string.troubleshoot_notifications_test_firebase_token_success, - "*****${token.takeLast(8)}" - ), - status = NotificationTroubleshootTestState.Status.Success - ) - } else { - delegate.updateState( - description = stringProvider.getString(R.string.troubleshoot_notifications_test_firebase_token_failure), - status = NotificationTroubleshootTestState.Status.Failure(true) - ) - } + currentJob = firebaseStore.fcmTokenFlow() + .onEach { token -> + if (token != null) { + delegate.updateState( + description = stringProvider.getString( + R.string.troubleshoot_notifications_test_firebase_token_success, + "*****${token.takeLast(8)}" + ), + status = NotificationTroubleshootTestState.Status.Success + ) + } else { + delegate.updateState( + description = stringProvider.getString(R.string.troubleshoot_notifications_test_firebase_token_failure), + status = NotificationTroubleshootTestState.Status.Failure(true) + ) + } + } + .launchIn(coroutineScope) } override suspend fun reset() = delegate.reset() diff --git a/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/InMemoryFirebaseStore.kt b/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/InMemoryFirebaseStore.kt index 3a3e582f7f..6728fd0490 100644 --- a/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/InMemoryFirebaseStore.kt +++ b/libraries/pushproviders/firebase/src/test/kotlin/io/element/android/libraries/pushproviders/firebase/InMemoryFirebaseStore.kt @@ -7,11 +7,16 @@ package io.element.android.libraries.pushproviders.firebase +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf + class InMemoryFirebaseStore( private var token: String? = null ) : FirebaseStore { override fun getFcmToken(): String? = token + override fun fcmTokenFlow(): Flow = flowOf(token) + override fun storeFcmToken(token: String?) { this.token = token }