Add ability to not show the pusher registration again.
This commit is contained in:
@@ -17,5 +17,5 @@
|
||||
package io.element.android.appnav.loggedin
|
||||
|
||||
sealed interface LoggedInEvents {
|
||||
data object CloseErrorDialog : LoggedInEvents
|
||||
data class CloseErrorDialog(val doNotShowAgain: Boolean) : LoggedInEvents
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import im.vector.app.features.analytics.plan.CryptoSessionStateChange
|
||||
import im.vector.app.features.analytics.plan.UserProperties
|
||||
import io.element.android.features.networkmonitor.api.NetworkMonitor
|
||||
@@ -41,6 +42,7 @@ import io.element.android.libraries.push.api.PushService
|
||||
import io.element.android.libraries.pushproviders.api.RegistrationFailure
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -56,9 +58,13 @@ class LoggedInPresenter @Inject constructor(
|
||||
) : Presenter<LoggedInState> {
|
||||
@Composable
|
||||
override fun present(): LoggedInState {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val isVerified by remember {
|
||||
sessionVerificationService.sessionVerifiedStatus.map { it == SessionVerifiedStatus.Verified }
|
||||
}.collectAsState(initial = false)
|
||||
val ignoreRegistrationError by remember {
|
||||
pushService.ignoreRegistrationError(matrixClient.sessionId)
|
||||
}.collectAsState(initial = false)
|
||||
val pusherRegistrationState = remember<MutableState<AsyncData<Unit>>> { mutableStateOf(AsyncData.Uninitialized) }
|
||||
if (isVerified) {
|
||||
LaunchedEffect(Unit) {
|
||||
@@ -84,13 +90,21 @@ class LoggedInPresenter @Inject constructor(
|
||||
|
||||
fun handleEvent(event: LoggedInEvents) {
|
||||
when (event) {
|
||||
LoggedInEvents.CloseErrorDialog -> pusherRegistrationState.value = AsyncData.Uninitialized
|
||||
is LoggedInEvents.CloseErrorDialog -> {
|
||||
pusherRegistrationState.value = AsyncData.Uninitialized
|
||||
if (event.doNotShowAgain) {
|
||||
coroutineScope.launch {
|
||||
pushService.setIgnoreRegistrationError(matrixClient.sessionId, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return LoggedInState(
|
||||
showSyncSpinner = showSyncSpinner,
|
||||
pusherRegistrationState = pusherRegistrationState.value,
|
||||
ignoreRegistrationError = ignoreRegistrationError,
|
||||
eventSink = ::handleEvent
|
||||
)
|
||||
}
|
||||
|
||||
@@ -21,5 +21,6 @@ import io.element.android.libraries.architecture.AsyncData
|
||||
data class LoggedInState(
|
||||
val showSyncSpinner: Boolean,
|
||||
val pusherRegistrationState: AsyncData<Unit>,
|
||||
val ignoreRegistrationError: Boolean,
|
||||
val eventSink: (LoggedInEvents) -> Unit,
|
||||
)
|
||||
|
||||
@@ -34,5 +34,6 @@ fun aLoggedInState(
|
||||
) = LoggedInState(
|
||||
showSyncSpinner = showSyncSpinner,
|
||||
pusherRegistrationState = pusherRegistrationState,
|
||||
ignoreRegistrationError = false,
|
||||
eventSink = {},
|
||||
)
|
||||
|
||||
@@ -25,7 +25,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
|
||||
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialogWithDoNotShowAgain
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||
import io.element.android.libraries.matrix.api.exception.isNetworkError
|
||||
@@ -52,11 +52,12 @@ fun LoggedInView(
|
||||
is AsyncData.Success -> Unit
|
||||
is AsyncData.Failure -> {
|
||||
state.pusherRegistrationState.errorOrNull()
|
||||
?.takeIf { !state.ignoreRegistrationError }
|
||||
?.getReason()
|
||||
?.let { reason ->
|
||||
ErrorDialog(
|
||||
ErrorDialogWithDoNotShowAgain(
|
||||
content = stringResource(id = CommonStrings.common_error_registering_pusher_android, reason),
|
||||
onDismiss = { state.eventSink(LoggedInEvents.CloseErrorDialog) },
|
||||
onDismiss = { state.eventSink(LoggedInEvents.CloseErrorDialog(it)) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ class LoggedInPresenterTest {
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.showSyncSpinner).isFalse()
|
||||
assertThat(initialState.pusherRegistrationState.isUninitialized()).isTrue()
|
||||
assertThat(initialState.ignoreRegistrationError).isFalse()
|
||||
skipItems(1)
|
||||
}
|
||||
}
|
||||
@@ -356,6 +357,12 @@ class LoggedInPresenterTest {
|
||||
.isInstanceOf(PusherRegistrationFailure.NoProvidersAvailable::class.java)
|
||||
lambda.assertions()
|
||||
.isNeverCalled()
|
||||
// Reset the error and do not show again
|
||||
finalState.eventSink(LoggedInEvents.CloseErrorDialog(doNotShowAgain = true))
|
||||
skipItems(1)
|
||||
val lastState = awaitItem()
|
||||
assertThat(lastState.pusherRegistrationState.isUninitialized()).isTrue()
|
||||
assertThat(lastState.ignoreRegistrationError).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -390,7 +397,7 @@ class LoggedInPresenterTest {
|
||||
lambda.assertions()
|
||||
.isNeverCalled()
|
||||
// Reset the error
|
||||
finalState.eventSink(LoggedInEvents.CloseErrorDialog)
|
||||
finalState.eventSink(LoggedInEvents.CloseErrorDialog(doNotShowAgain = false))
|
||||
val lastState = awaitItem()
|
||||
assertThat(lastState.pusherRegistrationState.isUninitialized()).isTrue()
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.di.SessionScope
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.push.api.PushService
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.OkHttpClient
|
||||
import javax.inject.Inject
|
||||
@@ -47,6 +48,7 @@ class DefaultClearCacheUseCase @Inject constructor(
|
||||
private val okHttpClient: Provider<OkHttpClient>,
|
||||
private val ftueService: FtueService,
|
||||
private val migrationScreenStore: MigrationScreenStore,
|
||||
private val pushService: PushService,
|
||||
) : ClearCacheUseCase {
|
||||
override suspend fun invoke() = withContext(coroutineDispatchers.io) {
|
||||
// Clear Matrix cache
|
||||
@@ -66,5 +68,7 @@ class DefaultClearCacheUseCase @Inject constructor(
|
||||
migrationScreenStore.reset()
|
||||
// Ensure the app is restarted
|
||||
defaultCacheIndexProvider.onClearedCache(matrixClient.sessionId)
|
||||
// Ensure any error will be displayed again
|
||||
pushService.setIgnoreRegistrationError(matrixClient.sessionId, false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
package io.element.android.libraries.push.api
|
||||
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.pushproviders.api.Distributor
|
||||
import io.element.android.libraries.pushproviders.api.PushProvider
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface PushService {
|
||||
/**
|
||||
@@ -43,6 +45,9 @@ interface PushService {
|
||||
distributor: Distributor,
|
||||
): Result<Unit>
|
||||
|
||||
fun ignoreRegistrationError(sessionId: SessionId): Flow<Boolean>
|
||||
suspend fun setIgnoreRegistrationError(sessionId: SessionId, ignore: Boolean)
|
||||
|
||||
/**
|
||||
* Return false in case of early error.
|
||||
*/
|
||||
|
||||
@@ -19,12 +19,14 @@ package io.element.android.libraries.push.impl
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.push.api.GetCurrentPushProvider
|
||||
import io.element.android.libraries.push.api.PushService
|
||||
import io.element.android.libraries.push.impl.test.TestPush
|
||||
import io.element.android.libraries.pushproviders.api.Distributor
|
||||
import io.element.android.libraries.pushproviders.api.PushProvider
|
||||
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@@ -72,6 +74,14 @@ class DefaultPushService @Inject constructor(
|
||||
return pushProvider.registerWith(matrixClient, distributor)
|
||||
}
|
||||
|
||||
override fun ignoreRegistrationError(sessionId: SessionId): Flow<Boolean> {
|
||||
return userPushStoreFactory.getOrCreate(sessionId).ignoreRegistrationError()
|
||||
}
|
||||
|
||||
override suspend fun setIgnoreRegistrationError(sessionId: SessionId, ignore: Boolean) {
|
||||
userPushStoreFactory.getOrCreate(sessionId).setIgnoreRegistrationError(ignore)
|
||||
}
|
||||
|
||||
override suspend fun testPush(): Boolean {
|
||||
val pushProvider = getCurrentPushProvider() ?: return false
|
||||
val config = pushProvider.getCurrentUserPushConfig() ?: return false
|
||||
|
||||
@@ -17,10 +17,13 @@
|
||||
package io.element.android.libraries.push.test
|
||||
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.push.api.PushService
|
||||
import io.element.android.libraries.pushproviders.api.Distributor
|
||||
import io.element.android.libraries.pushproviders.api.PushProvider
|
||||
import io.element.android.tests.testutils.simulateLongTask
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
class FakePushService(
|
||||
private val testPushBlock: suspend () -> Boolean = { true },
|
||||
@@ -53,6 +56,16 @@ class FakePushService(
|
||||
}
|
||||
}
|
||||
|
||||
private val ignoreRegistrationError = MutableStateFlow(false)
|
||||
|
||||
override fun ignoreRegistrationError(sessionId: SessionId): Flow<Boolean> {
|
||||
return ignoreRegistrationError
|
||||
}
|
||||
|
||||
override suspend fun setIgnoreRegistrationError(sessionId: SessionId, ignore: Boolean) {
|
||||
ignoreRegistrationError.value = ignore
|
||||
}
|
||||
|
||||
override suspend fun testPush(): Boolean = simulateLongTask {
|
||||
testPushBlock()
|
||||
}
|
||||
|
||||
@@ -29,6 +29,9 @@ interface UserPushStore {
|
||||
fun getNotificationEnabledForDevice(): Flow<Boolean>
|
||||
suspend fun setNotificationEnabledForDevice(enabled: Boolean)
|
||||
|
||||
fun ignoreRegistrationError(): Flow<Boolean>
|
||||
suspend fun setIgnoreRegistrationError(ignore: Boolean)
|
||||
|
||||
/**
|
||||
* Return true if Pin code is disabled, or if user set the settings to see full notification content.
|
||||
*/
|
||||
|
||||
@@ -25,6 +25,7 @@ import androidx.datastore.preferences.core.stringPreferencesKey
|
||||
import androidx.datastore.preferences.preferencesDataStore
|
||||
import androidx.datastore.preferences.preferencesDataStoreFile
|
||||
import io.element.android.libraries.androidutils.hash.hash
|
||||
import io.element.android.libraries.core.bool.orFalse
|
||||
import io.element.android.libraries.core.bool.orTrue
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.pushstore.api.UserPushStore
|
||||
@@ -61,6 +62,7 @@ class UserPushStoreDataStore(
|
||||
private val pushProviderName = stringPreferencesKey("pushProviderName")
|
||||
private val currentPushKey = stringPreferencesKey("currentPushKey")
|
||||
private val notificationEnabled = booleanPreferencesKey("notificationEnabled")
|
||||
private val ignoreRegistrationError = booleanPreferencesKey("ignoreRegistrationError")
|
||||
|
||||
override suspend fun getPushProviderName(): String? {
|
||||
return context.dataStore.data.first()[pushProviderName]
|
||||
@@ -100,6 +102,16 @@ class UserPushStoreDataStore(
|
||||
return true
|
||||
}
|
||||
|
||||
override fun ignoreRegistrationError(): Flow<Boolean> {
|
||||
return context.dataStore.data.map { it[ignoreRegistrationError].orFalse() }
|
||||
}
|
||||
|
||||
override suspend fun setIgnoreRegistrationError(ignore: Boolean) {
|
||||
context.dataStore.edit {
|
||||
it[ignoreRegistrationError] = ignore
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun reset() {
|
||||
context.dataStore.edit {
|
||||
it.clear()
|
||||
|
||||
@@ -25,6 +25,7 @@ class FakeUserPushStore(
|
||||
) : UserPushStore {
|
||||
private var currentRegisteredPushKey: String? = null
|
||||
private val notificationEnabledForDevice = MutableStateFlow(true)
|
||||
private val ignoreRegistrationError = MutableStateFlow(false)
|
||||
override suspend fun getPushProviderName(): String? {
|
||||
return pushProviderName
|
||||
}
|
||||
@@ -53,6 +54,14 @@ class FakeUserPushStore(
|
||||
return true
|
||||
}
|
||||
|
||||
override fun ignoreRegistrationError(): Flow<Boolean> {
|
||||
return ignoreRegistrationError
|
||||
}
|
||||
|
||||
override suspend fun setIgnoreRegistrationError(ignore: Boolean) {
|
||||
ignoreRegistrationError.value = ignore
|
||||
}
|
||||
|
||||
override suspend fun reset() {
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user