Add the Migrate session screen (#1145)
This commit is contained in:
parent
7a602790ab
commit
c2cfa4a606
10 changed files with 328 additions and 7 deletions
|
|
@ -33,6 +33,7 @@ dependencies {
|
||||||
implementation(projects.anvilannotations)
|
implementation(projects.anvilannotations)
|
||||||
anvil(projects.anvilcodegen)
|
anvil(projects.anvilcodegen)
|
||||||
api(projects.features.ftue.api)
|
api(projects.features.ftue.api)
|
||||||
|
implementation(projects.libraries.androidutils)
|
||||||
implementation(projects.libraries.core)
|
implementation(projects.libraries.core)
|
||||||
implementation(projects.libraries.architecture)
|
implementation(projects.libraries.architecture)
|
||||||
implementation(projects.libraries.matrix.api)
|
implementation(projects.libraries.matrix.api)
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ import dagger.assisted.AssistedInject
|
||||||
import io.element.android.anvilannotations.ContributesNode
|
import io.element.android.anvilannotations.ContributesNode
|
||||||
import io.element.android.features.analytics.api.AnalyticsEntryPoint
|
import io.element.android.features.analytics.api.AnalyticsEntryPoint
|
||||||
import io.element.android.features.ftue.api.FtueEntryPoint
|
import io.element.android.features.ftue.api.FtueEntryPoint
|
||||||
|
import io.element.android.features.ftue.impl.migration.MigrationScreenNode
|
||||||
import io.element.android.features.ftue.impl.state.DefaultFtueState
|
import io.element.android.features.ftue.impl.state.DefaultFtueState
|
||||||
import io.element.android.features.ftue.impl.state.FtueStep
|
import io.element.android.features.ftue.impl.state.FtueStep
|
||||||
import io.element.android.features.ftue.impl.welcome.WelcomeNode
|
import io.element.android.features.ftue.impl.welcome.WelcomeNode
|
||||||
|
|
@ -41,6 +42,7 @@ import io.element.android.libraries.architecture.BackstackNode
|
||||||
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
|
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
|
||||||
import io.element.android.libraries.architecture.createNode
|
import io.element.android.libraries.architecture.createNode
|
||||||
import io.element.android.libraries.di.AppScope
|
import io.element.android.libraries.di.AppScope
|
||||||
|
import io.element.android.libraries.di.SessionScope
|
||||||
import io.element.android.services.analytics.api.AnalyticsService
|
import io.element.android.services.analytics.api.AnalyticsService
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
@ -50,7 +52,7 @@ import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
@ContributesNode(AppScope::class)
|
@ContributesNode(SessionScope::class)
|
||||||
class FtueFlowNode @AssistedInject constructor(
|
class FtueFlowNode @AssistedInject constructor(
|
||||||
@Assisted buildContext: BuildContext,
|
@Assisted buildContext: BuildContext,
|
||||||
@Assisted plugins: List<Plugin>,
|
@Assisted plugins: List<Plugin>,
|
||||||
|
|
@ -71,6 +73,9 @@ class FtueFlowNode @AssistedInject constructor(
|
||||||
@Parcelize
|
@Parcelize
|
||||||
object Placeholder : NavTarget
|
object Placeholder : NavTarget
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
data object MigrationScreen : NavTarget
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
object WelcomeScreen : NavTarget
|
object WelcomeScreen : NavTarget
|
||||||
|
|
||||||
|
|
@ -102,6 +107,14 @@ class FtueFlowNode @AssistedInject constructor(
|
||||||
NavTarget.Placeholder -> {
|
NavTarget.Placeholder -> {
|
||||||
createNode<PlaceholderNode>(buildContext)
|
createNode<PlaceholderNode>(buildContext)
|
||||||
}
|
}
|
||||||
|
NavTarget.MigrationScreen -> {
|
||||||
|
val callback = object : MigrationScreenNode.Callback {
|
||||||
|
override fun onMigrationFinished() {
|
||||||
|
lifecycleScope.launch { moveToNextStep() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
createNode<MigrationScreenNode>(buildContext, listOf(callback))
|
||||||
|
}
|
||||||
NavTarget.WelcomeScreen -> {
|
NavTarget.WelcomeScreen -> {
|
||||||
val callback = object : WelcomeNode.Callback {
|
val callback = object : WelcomeNode.Callback {
|
||||||
override fun onContinueClicked() {
|
override fun onContinueClicked() {
|
||||||
|
|
@ -117,12 +130,15 @@ class FtueFlowNode @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun moveToNextStep() {
|
private fun moveToNextStep() {
|
||||||
when (ftueState.getNextStep()) {
|
when (ftueState.getNextStep()) {
|
||||||
is FtueStep.WelcomeScreen -> {
|
FtueStep.MigrationScreen -> {
|
||||||
|
backstack.newRoot(NavTarget.MigrationScreen)
|
||||||
|
}
|
||||||
|
FtueStep.WelcomeScreen -> {
|
||||||
backstack.newRoot(NavTarget.WelcomeScreen)
|
backstack.newRoot(NavTarget.WelcomeScreen)
|
||||||
}
|
}
|
||||||
is FtueStep.AnalyticsOptIn -> {
|
FtueStep.AnalyticsOptIn -> {
|
||||||
backstack.replace(NavTarget.AnalyticsOptIn)
|
backstack.replace(NavTarget.AnalyticsOptIn)
|
||||||
}
|
}
|
||||||
null -> callback?.onFtueFlowFinished()
|
null -> callback?.onFtueFlowFinished()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.ftue.impl.migration
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
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 dagger.assisted.Assisted
|
||||||
|
import dagger.assisted.AssistedInject
|
||||||
|
import io.element.android.anvilannotations.ContributesNode
|
||||||
|
import io.element.android.libraries.di.SessionScope
|
||||||
|
|
||||||
|
@ContributesNode(SessionScope::class)
|
||||||
|
class MigrationScreenNode @AssistedInject constructor(
|
||||||
|
@Assisted buildContext: BuildContext,
|
||||||
|
@Assisted plugins: List<Plugin>,
|
||||||
|
private val presenter: MigrationScreenPresenter,
|
||||||
|
) : Node(buildContext, plugins = plugins) {
|
||||||
|
|
||||||
|
interface Callback : Plugin {
|
||||||
|
fun onMigrationFinished()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onMigrationFinished() {
|
||||||
|
plugins.filterIsInstance<Callback>().forEach { it.onMigrationFinished() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun View(modifier: Modifier) {
|
||||||
|
val state = presenter.present()
|
||||||
|
MigrationScreenView(
|
||||||
|
state,
|
||||||
|
onMigrationFinished = ::onMigrationFinished,
|
||||||
|
modifier = modifier
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.ftue.impl.migration
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import io.element.android.libraries.architecture.Presenter
|
||||||
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
|
import io.element.android.libraries.matrix.api.roomlist.RoomListService
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class MigrationScreenPresenter @Inject constructor(
|
||||||
|
private val matrixClient: MatrixClient,
|
||||||
|
private val migrationScreenStore: MigrationScreenStore,
|
||||||
|
) : Presenter<MigrationScreenState> {
|
||||||
|
@Composable
|
||||||
|
override fun present(): MigrationScreenState {
|
||||||
|
val roomListState by matrixClient.roomListService.state.collectAsState()
|
||||||
|
if (roomListState == RoomListService.State.Running) {
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
migrationScreenStore.setMigrationScreenShown(matrixClient.sessionId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MigrationScreenState(
|
||||||
|
isMigrating = roomListState != RoomListService.State.Running
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.ftue.impl.migration
|
||||||
|
|
||||||
|
data class MigrationScreenState(
|
||||||
|
val isMigrating: Boolean
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.ftue.impl.migration
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
|
|
||||||
|
interface MigrationScreenStore {
|
||||||
|
fun isMigrationScreenNeeded(sessionId: SessionId): Boolean
|
||||||
|
fun setMigrationScreenShown(sessionId: SessionId)
|
||||||
|
fun reset()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.ftue.impl.migration
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import io.element.android.features.ftue.impl.R
|
||||||
|
import io.element.android.libraries.designsystem.atomic.pages.SunsetPage
|
||||||
|
import io.element.android.libraries.designsystem.preview.DayNightPreviews
|
||||||
|
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MigrationScreenView(
|
||||||
|
migrationState: MigrationScreenState,
|
||||||
|
onMigrationFinished: () -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
if (migrationState.isMigrating.not()) {
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
onMigrationFinished()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SunsetPage(
|
||||||
|
modifier = modifier,
|
||||||
|
isLoading = true,
|
||||||
|
title = stringResource(id = R.string.screen_migration_title),
|
||||||
|
subtitle = stringResource(id = R.string.screen_migration_message),
|
||||||
|
overallContent = {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@DayNightPreviews
|
||||||
|
@Composable
|
||||||
|
internal fun MigrationViewPreview() = ElementPreview {
|
||||||
|
MigrationScreenView(
|
||||||
|
migrationState = MigrationScreenState(isMigrating = true),
|
||||||
|
onMigrationFinished = {})
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.ftue.impl.migration
|
||||||
|
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import androidx.core.content.edit
|
||||||
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
|
import io.element.android.libraries.androidutils.hash.md5
|
||||||
|
import io.element.android.libraries.di.AppScope
|
||||||
|
import io.element.android.libraries.di.DefaultPreferences
|
||||||
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ContributesBinding(AppScope::class)
|
||||||
|
class SharedPrefsMigrationScreenStore @Inject constructor(
|
||||||
|
@DefaultPreferences private val sharedPreferences: SharedPreferences,
|
||||||
|
) : MigrationScreenStore {
|
||||||
|
|
||||||
|
override fun isMigrationScreenNeeded(sessionId: SessionId): Boolean {
|
||||||
|
return sharedPreferences.getBoolean(sessionId.toKey(), false).not()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setMigrationScreenShown(sessionId: SessionId) {
|
||||||
|
sharedPreferences.edit().putBoolean(sessionId.toKey(), true).apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun reset() {
|
||||||
|
sharedPreferences.edit {
|
||||||
|
sharedPreferences.all.keys
|
||||||
|
.filter { it.startsWith(IS_MIGRATION_SCREEN_SHOWN_PREFIX) }
|
||||||
|
.forEach {
|
||||||
|
remove(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun SessionId.toKey(): String {
|
||||||
|
return IS_MIGRATION_SCREEN_SHOWN_PREFIX + value.md5()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val IS_MIGRATION_SCREEN_SHOWN_PREFIX = "is_migration_screen_shown_"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -19,8 +19,10 @@ package io.element.android.features.ftue.impl.state
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import com.squareup.anvil.annotations.ContributesBinding
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
import io.element.android.features.ftue.api.state.FtueState
|
import io.element.android.features.ftue.api.state.FtueState
|
||||||
|
import io.element.android.features.ftue.impl.migration.MigrationScreenStore
|
||||||
import io.element.android.features.ftue.impl.welcome.state.WelcomeScreenState
|
import io.element.android.features.ftue.impl.welcome.state.WelcomeScreenState
|
||||||
import io.element.android.libraries.di.AppScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.services.analytics.api.AnalyticsService
|
import io.element.android.services.analytics.api.AnalyticsService
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
@ -30,11 +32,13 @@ import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ContributesBinding(AppScope::class)
|
@ContributesBinding(SessionScope::class)
|
||||||
class DefaultFtueState @Inject constructor(
|
class DefaultFtueState @Inject constructor(
|
||||||
private val coroutineScope: CoroutineScope,
|
private val coroutineScope: CoroutineScope,
|
||||||
private val analyticsService: AnalyticsService,
|
private val analyticsService: AnalyticsService,
|
||||||
private val welcomeScreenState: WelcomeScreenState,
|
private val welcomeScreenState: WelcomeScreenState,
|
||||||
|
private val migrationScreenStore: MigrationScreenStore,
|
||||||
|
private val matrixClient: MatrixClient,
|
||||||
) : FtueState {
|
) : FtueState {
|
||||||
|
|
||||||
override val shouldDisplayFlow = MutableStateFlow(isAnyStepIncomplete())
|
override val shouldDisplayFlow = MutableStateFlow(isAnyStepIncomplete())
|
||||||
|
|
@ -42,6 +46,7 @@ class DefaultFtueState @Inject constructor(
|
||||||
override suspend fun reset() {
|
override suspend fun reset() {
|
||||||
welcomeScreenState.reset()
|
welcomeScreenState.reset()
|
||||||
analyticsService.reset()
|
analyticsService.reset()
|
||||||
|
migrationScreenStore.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
@ -52,7 +57,10 @@ class DefaultFtueState @Inject constructor(
|
||||||
|
|
||||||
fun getNextStep(currentStep: FtueStep? = null): FtueStep? =
|
fun getNextStep(currentStep: FtueStep? = null): FtueStep? =
|
||||||
when (currentStep) {
|
when (currentStep) {
|
||||||
null -> if (shouldDisplayWelcomeScreen()) FtueStep.WelcomeScreen else getNextStep(
|
null -> if (shouldDisplayMigrationScreen()) FtueStep.MigrationScreen else getNextStep(
|
||||||
|
FtueStep.MigrationScreen
|
||||||
|
)
|
||||||
|
FtueStep.MigrationScreen -> if (shouldDisplayWelcomeScreen()) FtueStep.WelcomeScreen else getNextStep(
|
||||||
FtueStep.WelcomeScreen
|
FtueStep.WelcomeScreen
|
||||||
)
|
)
|
||||||
FtueStep.WelcomeScreen -> if (needsAnalyticsOptIn()) FtueStep.AnalyticsOptIn else getNextStep(
|
FtueStep.WelcomeScreen -> if (needsAnalyticsOptIn()) FtueStep.AnalyticsOptIn else getNextStep(
|
||||||
|
|
@ -63,11 +71,16 @@ class DefaultFtueState @Inject constructor(
|
||||||
|
|
||||||
private fun isAnyStepIncomplete(): Boolean {
|
private fun isAnyStepIncomplete(): Boolean {
|
||||||
return listOf(
|
return listOf(
|
||||||
|
shouldDisplayMigrationScreen(),
|
||||||
shouldDisplayWelcomeScreen(),
|
shouldDisplayWelcomeScreen(),
|
||||||
needsAnalyticsOptIn()
|
needsAnalyticsOptIn()
|
||||||
).any { it }
|
).any { it }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun shouldDisplayMigrationScreen(): Boolean {
|
||||||
|
return migrationScreenStore.isMigrationScreenNeeded(matrixClient.sessionId)
|
||||||
|
}
|
||||||
|
|
||||||
private fun needsAnalyticsOptIn(): Boolean {
|
private fun needsAnalyticsOptIn(): Boolean {
|
||||||
// We need this function to not be suspend, so we need to load the value through runBlocking
|
// We need this function to not be suspend, so we need to load the value through runBlocking
|
||||||
return runBlocking { analyticsService.didAskUserConsent().first().not() }
|
return runBlocking { analyticsService.didAskUserConsent().first().not() }
|
||||||
|
|
@ -89,6 +102,7 @@ class DefaultFtueState @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed interface FtueStep {
|
sealed interface FtueStep {
|
||||||
|
data object MigrationScreen : FtueStep
|
||||||
object WelcomeScreen : FtueStep
|
object WelcomeScreen : FtueStep
|
||||||
object AnalyticsOptIn : FtueStep
|
object AnalyticsOptIn : FtueStep
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.androidutils.hash
|
||||||
|
|
||||||
|
import java.security.MessageDigest
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute a Hash of a String, using md5 algorithm.
|
||||||
|
*/
|
||||||
|
fun String.md5() = try {
|
||||||
|
val digest = MessageDigest.getInstance("md5")
|
||||||
|
digest.update(toByteArray())
|
||||||
|
digest.digest()
|
||||||
|
.joinToString("") { String.format("%02X", it) }
|
||||||
|
.lowercase(Locale.ROOT)
|
||||||
|
} catch (exc: Exception) {
|
||||||
|
// Should not happen, but just in case
|
||||||
|
hashCode().toString()
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue