|
|
@ -40,12 +40,11 @@ import io.element.android.anvilannotations.ContributesNode |
|
|
|
import io.element.android.appnav.di.MatrixClientsHolder |
|
|
|
import io.element.android.appnav.di.MatrixClientsHolder |
|
|
|
import io.element.android.appnav.intent.IntentResolver |
|
|
|
import io.element.android.appnav.intent.IntentResolver |
|
|
|
import io.element.android.appnav.intent.ResolvedIntent |
|
|
|
import io.element.android.appnav.intent.ResolvedIntent |
|
|
|
|
|
|
|
import io.element.android.appnav.root.RootNavStateFlowFactory |
|
|
|
import io.element.android.appnav.root.RootPresenter |
|
|
|
import io.element.android.appnav.root.RootPresenter |
|
|
|
import io.element.android.appnav.root.RootView |
|
|
|
import io.element.android.appnav.root.RootView |
|
|
|
import io.element.android.features.login.api.LoginUserStory |
|
|
|
|
|
|
|
import io.element.android.features.login.api.oidc.OidcAction |
|
|
|
import io.element.android.features.login.api.oidc.OidcAction |
|
|
|
import io.element.android.features.login.api.oidc.OidcActionFlow |
|
|
|
import io.element.android.features.login.api.oidc.OidcActionFlow |
|
|
|
import io.element.android.features.preferences.api.CacheService |
|
|
|
|
|
|
|
import io.element.android.features.rageshake.api.bugreport.BugReportEntryPoint |
|
|
|
import io.element.android.features.rageshake.api.bugreport.BugReportEntryPoint |
|
|
|
import io.element.android.libraries.architecture.BackstackNode |
|
|
|
import io.element.android.libraries.architecture.BackstackNode |
|
|
|
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler |
|
|
|
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler |
|
|
@ -57,29 +56,22 @@ import io.element.android.libraries.di.AppScope |
|
|
|
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService |
|
|
|
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService |
|
|
|
import io.element.android.libraries.matrix.api.core.SessionId |
|
|
|
import io.element.android.libraries.matrix.api.core.SessionId |
|
|
|
import kotlinx.coroutines.flow.distinctUntilChanged |
|
|
|
import kotlinx.coroutines.flow.distinctUntilChanged |
|
|
|
|
|
|
|
|
|
|
|
import kotlinx.coroutines.flow.Flow |
|
|
|
|
|
|
|
import kotlinx.coroutines.flow.combine |
|
|
|
|
|
|
|
import kotlinx.coroutines.flow.launchIn |
|
|
|
import kotlinx.coroutines.flow.launchIn |
|
|
|
import kotlinx.coroutines.flow.map |
|
|
|
|
|
|
|
import kotlinx.coroutines.flow.onEach |
|
|
|
import kotlinx.coroutines.flow.onEach |
|
|
|
import kotlinx.coroutines.flow.onStart |
|
|
|
|
|
|
|
import kotlinx.parcelize.Parcelize |
|
|
|
import kotlinx.parcelize.Parcelize |
|
|
|
import timber.log.Timber |
|
|
|
import timber.log.Timber |
|
|
|
import java.util.UUID |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ContributesNode(AppScope::class) |
|
|
|
@ContributesNode(AppScope::class) |
|
|
|
class RootFlowNode @AssistedInject constructor( |
|
|
|
class RootFlowNode @AssistedInject constructor( |
|
|
|
@Assisted val buildContext: BuildContext, |
|
|
|
@Assisted val buildContext: BuildContext, |
|
|
|
@Assisted plugins: List<Plugin>, |
|
|
|
@Assisted plugins: List<Plugin>, |
|
|
|
private val authenticationService: MatrixAuthenticationService, |
|
|
|
private val authenticationService: MatrixAuthenticationService, |
|
|
|
private val cacheService: CacheService, |
|
|
|
private val navStateFlowFactory: RootNavStateFlowFactory, |
|
|
|
private val matrixClientsHolder: MatrixClientsHolder, |
|
|
|
private val matrixClientsHolder: MatrixClientsHolder, |
|
|
|
private val presenter: RootPresenter, |
|
|
|
private val presenter: RootPresenter, |
|
|
|
private val bugReportEntryPoint: BugReportEntryPoint, |
|
|
|
private val bugReportEntryPoint: BugReportEntryPoint, |
|
|
|
private val intentResolver: IntentResolver, |
|
|
|
private val intentResolver: IntentResolver, |
|
|
|
private val oidcActionFlow: OidcActionFlow, |
|
|
|
private val oidcActionFlow: OidcActionFlow, |
|
|
|
private val loginUserStory: LoginUserStory, |
|
|
|
|
|
|
|
) : |
|
|
|
) : |
|
|
|
BackstackNode<RootFlowNode.NavTarget>( |
|
|
|
BackstackNode<RootFlowNode.NavTarget>( |
|
|
|
backstack = BackStack( |
|
|
|
backstack = BackStack( |
|
|
@ -91,26 +83,25 @@ class RootFlowNode @AssistedInject constructor( |
|
|
|
) { |
|
|
|
) { |
|
|
|
|
|
|
|
|
|
|
|
override fun onBuilt() { |
|
|
|
override fun onBuilt() { |
|
|
|
matrixClientsHolder.restore(buildContext.savedStateMap) |
|
|
|
matrixClientsHolder.restoreWithSavedState(buildContext.savedStateMap) |
|
|
|
super.onBuilt() |
|
|
|
super.onBuilt() |
|
|
|
observeLoggedInState() |
|
|
|
observeNavState() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
override fun onSaveInstanceState(state: MutableSavedStateMap) { |
|
|
|
override fun onSaveInstanceState(state: MutableSavedStateMap) { |
|
|
|
super.onSaveInstanceState(state) |
|
|
|
super.onSaveInstanceState(state) |
|
|
|
matrixClientsHolder.save(state) |
|
|
|
matrixClientsHolder.saveIntoSavedState(state) |
|
|
|
|
|
|
|
navStateFlowFactory.saveIntoSavedState(state) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private fun observeLoggedInState() { |
|
|
|
private fun observeNavState() { |
|
|
|
combine( |
|
|
|
navStateFlowFactory.create(buildContext.savedStateMap) |
|
|
|
cacheService.onClearedCacheEventFlow(), |
|
|
|
.distinctUntilChanged() |
|
|
|
isUserLoggedInFlow(), |
|
|
|
.onEach { navState -> |
|
|
|
) { _, isLoggedIn -> isLoggedIn } |
|
|
|
Timber.v("navState=$navState") |
|
|
|
.onEach { isLoggedIn -> |
|
|
|
if (navState.isLoggedIn) { |
|
|
|
Timber.v("isLoggedIn=$isLoggedIn") |
|
|
|
|
|
|
|
if (isLoggedIn) { |
|
|
|
|
|
|
|
tryToRestoreLatestSession( |
|
|
|
tryToRestoreLatestSession( |
|
|
|
onSuccess = { switchToLoggedInFlow(it) }, |
|
|
|
onSuccess = { sessionId -> switchToLoggedInFlow(sessionId, navState.cacheIndex) }, |
|
|
|
onFailure = { switchToNotLoggedInFlow() } |
|
|
|
onFailure = { switchToNotLoggedInFlow() } |
|
|
|
) |
|
|
|
) |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -120,19 +111,8 @@ class RootFlowNode @AssistedInject constructor( |
|
|
|
.launchIn(lifecycleScope) |
|
|
|
.launchIn(lifecycleScope) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private fun switchToLoggedInFlow(sessionId: SessionId, navId: Int) { |
|
|
|
private fun switchToLoggedInFlow(sessionId: SessionId) { |
|
|
|
backstack.safeRoot(NavTarget.LoggedInFlow(sessionId, navId)) |
|
|
|
backstack.safeRoot(NavTarget.LoggedInFlow(sessionId)) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private fun isUserLoggedInFlow(): Flow<Boolean> { |
|
|
|
|
|
|
|
return combine( |
|
|
|
|
|
|
|
authenticationService.isLoggedIn(), |
|
|
|
|
|
|
|
loginUserStory.loginFlowIsDone |
|
|
|
|
|
|
|
) { isLoggedIn, loginFlowIsDone -> |
|
|
|
|
|
|
|
isLoggedIn && loginFlowIsDone |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
.distinctUntilChanged() |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private fun switchToNotLoggedInFlow() { |
|
|
|
private fun switchToNotLoggedInFlow() { |
|
|
@ -145,14 +125,8 @@ class RootFlowNode @AssistedInject constructor( |
|
|
|
onFailure: () -> Unit = {}, |
|
|
|
onFailure: () -> Unit = {}, |
|
|
|
onSuccess: (SessionId) -> Unit = {}, |
|
|
|
onSuccess: (SessionId) -> Unit = {}, |
|
|
|
) { |
|
|
|
) { |
|
|
|
// If the session is already known it'll be restored by the node hierarchy |
|
|
|
matrixClientsHolder.getOrRestore(sessionId) |
|
|
|
if (matrixClientsHolder.knowSession(sessionId)) { |
|
|
|
.onSuccess { |
|
|
|
Timber.v("Session $sessionId already alive, no need to restore.") |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
authenticationService.restoreSession(sessionId) |
|
|
|
|
|
|
|
.onSuccess { matrixClient -> |
|
|
|
|
|
|
|
matrixClientsHolder.add(matrixClient) |
|
|
|
|
|
|
|
Timber.v("Succeed to restore session $sessionId") |
|
|
|
Timber.v("Succeed to restore session $sessionId") |
|
|
|
onSuccess(sessionId) |
|
|
|
onSuccess(sessionId) |
|
|
|
} |
|
|
|
} |
|
|
@ -204,7 +178,7 @@ class RootFlowNode @AssistedInject constructor( |
|
|
|
@Parcelize |
|
|
|
@Parcelize |
|
|
|
data class LoggedInFlow( |
|
|
|
data class LoggedInFlow( |
|
|
|
val sessionId: SessionId, |
|
|
|
val sessionId: SessionId, |
|
|
|
val navId: UUID = UUID.randomUUID(), |
|
|
|
val navId: Int |
|
|
|
) : NavTarget |
|
|
|
) : NavTarget |
|
|
|
|
|
|
|
|
|
|
|
@Parcelize |
|
|
|
@Parcelize |
|
|
@ -278,11 +252,5 @@ class RootFlowNode @AssistedInject constructor( |
|
|
|
navTarget is NavTarget.LoggedInFlow && navTarget.sessionId == sessionId |
|
|
|
navTarget is NavTarget.LoggedInFlow && navTarget.sessionId == sessionId |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private fun CacheService.onClearedCacheEventFlow(): Flow<Unit> { |
|
|
|
|
|
|
|
return clearedCacheEventFlow |
|
|
|
|
|
|
|
.onEach { sessionId -> matrixClientsHolder.remove(sessionId) } |
|
|
|
|
|
|
|
.map { } |
|
|
|
|
|
|
|
.onStart { emit((Unit)) } |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|