Move session verification to FTUE flow, make it mandatory (#2594)

* Move session verification to the FTUE
* Allow session verification flow to be restarted
* Use `EncryptionService` to display session verification faster
* Remove session verification item from settings
* Remove session verification banner from room list
* Remove 'verification needed' variant from the `TimelineEncryptedHistoryBanner`
* Improve verification flow UI and UX
* Remove 'verification successful' snackbar message
* Only register push provider after the session has been verified
* Hide room list while the session hasn't been verified
* Prevent deep links from changing the navigation if the session isn't verified
* Update screenshots
* Renamed `FtueState` to `FtueService`, created an actual `FtueState`.

---------

Co-authored-by: ElementBot <benoitm+elementbot@element.io>
This commit is contained in:
Jorge Martin Espinosa 2024-04-03 16:53:17 +02:00 committed by GitHub
parent 05f6770d35
commit 41287c5f59
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
198 changed files with 822 additions and 761 deletions

View file

@ -36,6 +36,11 @@ class DefaultSecureBackupEntryPoint @Inject constructor() : SecureBackupEntryPoi
return this
}
override fun callback(callback: SecureBackupEntryPoint.Callback): SecureBackupEntryPoint.NodeBuilder {
plugins += callback
return this
}
override fun build(): Node {
return parentNode.createNode<SecureBackupFlowNode>(buildContext, plugins)
}

View file

@ -22,7 +22,9 @@ import androidx.compose.ui.Modifier
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import com.bumble.appyx.core.plugin.plugins
import com.bumble.appyx.navmodel.backstack.BackStack
import com.bumble.appyx.navmodel.backstack.operation.pop
import com.bumble.appyx.navmodel.backstack.operation.push
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
@ -74,6 +76,8 @@ class SecureBackupFlowNode @AssistedInject constructor(
data object EnterRecoveryKey : NavTarget
}
private val callback = plugins<SecureBackupEntryPoint.Callback>().firstOrNull()
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
return when (navTarget) {
NavTarget.Root -> {
@ -119,7 +123,16 @@ class SecureBackupFlowNode @AssistedInject constructor(
createNode<SecureBackupEnableNode>(buildContext)
}
NavTarget.EnterRecoveryKey -> {
createNode<SecureBackupEnterRecoveryKeyNode>(buildContext)
val callback = object : SecureBackupEnterRecoveryKeyNode.Callback {
override fun onEnterRecoveryKeySuccess() {
if (callback != null) {
callback.onDone()
} else {
backstack.pop()
}
}
}
createNode<SecureBackupEnterRecoveryKeyNode>(buildContext, plugins = listOf(callback))
}
}
}

View file

@ -17,48 +17,36 @@
package io.element.android.features.securebackup.impl.enter
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import com.bumble.appyx.core.plugin.plugins
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode
import io.element.android.features.securebackup.impl.R
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
import io.element.android.libraries.di.SessionScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@ContributesNode(SessionScope::class)
class SecureBackupEnterRecoveryKeyNode @AssistedInject constructor(
@Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>,
private val presenter: SecureBackupEnterRecoveryKeyPresenter,
private val snackbarDispatcher: SnackbarDispatcher,
) : Node(buildContext, plugins = plugins) {
interface Callback : Plugin {
fun onEnterRecoveryKeySuccess()
}
private val callback = plugins<Callback>().first()
@Composable
override fun View(modifier: Modifier) {
val coroutineScope = rememberCoroutineScope()
val state = presenter.present()
SecureBackupEnterRecoveryKeyView(
state = state,
modifier = modifier,
onDone = {
coroutineScope.postSuccessSnackbar()
navigateUp()
},
onDone = callback::onEnterRecoveryKeySuccess,
onBackClicked = ::navigateUp,
)
}
private fun CoroutineScope.postSuccessSnackbar() = launch {
snackbarDispatcher.post(
SnackbarMessage(
messageResId = R.string.screen_recovery_key_confirm_success
)
)
}
}