Merge pull request #575 from vector-im/feature/fga/fix_crash_on_restore
Feature/fga/fix crash on restore
This commit is contained in:
commit
afb3e33f84
5 changed files with 55 additions and 39 deletions
|
|
@ -23,6 +23,7 @@ import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
|
|
@ -39,7 +40,7 @@ private val loggerTag = LoggerTag("MainActivity")
|
||||||
|
|
||||||
class MainActivity : NodeComponentActivity() {
|
class MainActivity : NodeComponentActivity() {
|
||||||
|
|
||||||
lateinit var mainNode: MainNode
|
private lateinit var mainNode: MainNode
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
Timber.tag(loggerTag.value).w("onCreate, with savedInstanceState: ${savedInstanceState != null}")
|
Timber.tag(loggerTag.value).w("onCreate, with savedInstanceState: ${savedInstanceState != null}")
|
||||||
|
|
@ -49,26 +50,32 @@ class MainActivity : NodeComponentActivity() {
|
||||||
appBindings.matrixClientsHolder().restore(savedInstanceState)
|
appBindings.matrixClientsHolder().restore(savedInstanceState)
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
setContent {
|
setContent {
|
||||||
ElementTheme {
|
MainContent(appBindings)
|
||||||
Box(
|
}
|
||||||
modifier = Modifier
|
}
|
||||||
.fillMaxSize()
|
|
||||||
.background(MaterialTheme.colorScheme.background),
|
@Composable
|
||||||
) {
|
private fun MainContent(appBindings: AppBindings) {
|
||||||
NodeHost(integrationPoint = appyxIntegrationPoint) {
|
ElementTheme {
|
||||||
MainNode(
|
Box(
|
||||||
it,
|
modifier = Modifier
|
||||||
appBindings.mainDaggerComponentOwner(),
|
.fillMaxSize()
|
||||||
plugins = listOf(
|
.background(MaterialTheme.colorScheme.background),
|
||||||
object : NodeReadyObserver<MainNode> {
|
) {
|
||||||
override fun init(node: MainNode) {
|
NodeHost(integrationPoint = appyxIntegrationPoint) {
|
||||||
mainNode = node
|
MainNode(
|
||||||
mainNode.handleIntent(intent)
|
it,
|
||||||
}
|
appBindings.mainDaggerComponentOwner(),
|
||||||
|
plugins = listOf(
|
||||||
|
object : NodeReadyObserver<MainNode> {
|
||||||
|
override fun init(node: MainNode) {
|
||||||
|
Timber.tag(loggerTag.value).w("onMainNodeInit")
|
||||||
|
mainNode = node
|
||||||
|
mainNode.handleIntent(intent)
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -80,11 +87,17 @@ class MainActivity : NodeComponentActivity() {
|
||||||
* - a notification is clicked.
|
* - a notification is clicked.
|
||||||
* - the app is going to background (<- this is strange)
|
* - the app is going to background (<- this is strange)
|
||||||
*/
|
*/
|
||||||
override fun onNewIntent(intent: Intent?) {
|
override fun onNewIntent(intent: Intent) {
|
||||||
super.onNewIntent(intent)
|
super.onNewIntent(intent)
|
||||||
Timber.tag(loggerTag.value).w("onNewIntent")
|
Timber.tag(loggerTag.value).w("onNewIntent")
|
||||||
intent ?: return
|
// If the mainNode is not init yet, keep the intent for later.
|
||||||
mainNode.handleIntent(intent)
|
// It can happen when the activity is killed by the system. The methods are called in this order :
|
||||||
|
// onCreate(savedInstanceState=true) -> onNewIntent -> onResume -> onMainNodeInit
|
||||||
|
if (::mainNode.isInitialized) {
|
||||||
|
mainNode.handleIntent(intent)
|
||||||
|
} else {
|
||||||
|
setIntent(intent)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
|
|
|
||||||
|
|
@ -57,24 +57,24 @@ class MainNode(
|
||||||
DaggerComponentOwner by mainDaggerComponentOwner {
|
DaggerComponentOwner by mainDaggerComponentOwner {
|
||||||
|
|
||||||
private val loggedInFlowNodeCallback = object : LoggedInFlowNode.LifecycleCallback {
|
private val loggedInFlowNodeCallback = object : LoggedInFlowNode.LifecycleCallback {
|
||||||
override fun onFlowCreated(client: MatrixClient) {
|
override fun onFlowCreated(identifier: String, client: MatrixClient) {
|
||||||
val component = bindings<SessionComponent.ParentBindings>().sessionComponentBuilder().client(client).build()
|
val component = bindings<SessionComponent.ParentBindings>().sessionComponentBuilder().client(client).build()
|
||||||
mainDaggerComponentOwner.addComponent(client.sessionId.value, component)
|
mainDaggerComponentOwner.addComponent(identifier, component)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFlowReleased(client: MatrixClient) {
|
override fun onFlowReleased(identifier: String, client: MatrixClient) {
|
||||||
mainDaggerComponentOwner.removeComponent(client.sessionId.value)
|
mainDaggerComponentOwner.removeComponent(identifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val roomFlowNodeCallback = object : RoomFlowNode.LifecycleCallback {
|
private val roomFlowNodeCallback = object : RoomFlowNode.LifecycleCallback {
|
||||||
override fun onFlowCreated(room: MatrixRoom) {
|
override fun onFlowCreated(identifier: String, room: MatrixRoom) {
|
||||||
val component = bindings<RoomComponent.ParentBindings>().roomComponentBuilder().room(room).build()
|
val component = bindings<RoomComponent.ParentBindings>().roomComponentBuilder().room(room).build()
|
||||||
mainDaggerComponentOwner.addComponent(room.roomId.value, component)
|
mainDaggerComponentOwner.addComponent(identifier, component)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFlowReleased(room: MatrixRoom) {
|
override fun onFlowReleased(identifier: String, room: MatrixRoom) {
|
||||||
mainDaggerComponentOwner.removeComponent(room.roomId.value)
|
mainDaggerComponentOwner.removeComponent(identifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,10 @@ class MainDaggerComponentsOwner @Inject constructor(@ApplicationContext context:
|
||||||
daggerComponents.remove(identifier)
|
daggerComponents.remove(identifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We expose the dagger components in the opposite order they arrived.
|
||||||
|
* So we pick the most recent component when searching with the [io.element.android.libraries.architecture.bindings] methods.
|
||||||
|
*/
|
||||||
override val daggerComponent: Any
|
override val daggerComponent: Any
|
||||||
get() = daggerComponents.values.reversed()
|
get() = daggerComponents.values.reversed()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,6 @@ import io.element.android.services.analytics.api.AnalyticsService
|
||||||
import io.element.android.services.appnavstate.api.AppNavigationStateService
|
import io.element.android.services.appnavstate.api.AppNavigationStateService
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.flowOf
|
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
@ -118,9 +117,9 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LifecycleCallback : NodeLifecycleCallback {
|
interface LifecycleCallback : NodeLifecycleCallback {
|
||||||
fun onFlowCreated(client: MatrixClient) = Unit
|
fun onFlowCreated(identifier: String, client: MatrixClient) = Unit
|
||||||
|
|
||||||
fun onFlowReleased(client: MatrixClient) = Unit
|
fun onFlowReleased(identifier: String, client: MatrixClient) = Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
data class Inputs(
|
data class Inputs(
|
||||||
|
|
@ -139,7 +138,7 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||||
observeAnalyticsState()
|
observeAnalyticsState()
|
||||||
lifecycle.subscribe(
|
lifecycle.subscribe(
|
||||||
onCreate = {
|
onCreate = {
|
||||||
plugins<LifecycleCallback>().forEach { it.onFlowCreated(inputs.matrixClient) }
|
plugins<LifecycleCallback>().forEach { it.onFlowCreated(id, inputs.matrixClient) }
|
||||||
val imageLoaderFactory = bindings<MatrixUIBindings>().loggedInImageLoaderFactory()
|
val imageLoaderFactory = bindings<MatrixUIBindings>().loggedInImageLoaderFactory()
|
||||||
Coil.setImageLoader(imageLoaderFactory)
|
Coil.setImageLoader(imageLoaderFactory)
|
||||||
inputs.matrixClient.startSync()
|
inputs.matrixClient.startSync()
|
||||||
|
|
@ -151,7 +150,7 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||||
onDestroy = {
|
onDestroy = {
|
||||||
val imageLoaderFactory = bindings<MatrixUIBindings>().notLoggedInImageLoaderFactory()
|
val imageLoaderFactory = bindings<MatrixUIBindings>().notLoggedInImageLoaderFactory()
|
||||||
Coil.setImageLoader(imageLoaderFactory)
|
Coil.setImageLoader(imageLoaderFactory)
|
||||||
plugins<LifecycleCallback>().forEach { it.onFlowReleased(inputs.matrixClient) }
|
plugins<LifecycleCallback>().forEach { it.onFlowReleased(id, inputs.matrixClient) }
|
||||||
appNavigationStateService.onLeavingSpace(id)
|
appNavigationStateService.onLeavingSpace(id)
|
||||||
appNavigationStateService.onLeavingSession(id)
|
appNavigationStateService.onLeavingSession(id)
|
||||||
loggedInFlowProcessor.stopObserving()
|
loggedInFlowProcessor.stopObserving()
|
||||||
|
|
|
||||||
|
|
@ -68,8 +68,8 @@ class RoomFlowNode @AssistedInject constructor(
|
||||||
) {
|
) {
|
||||||
|
|
||||||
interface LifecycleCallback : NodeLifecycleCallback {
|
interface LifecycleCallback : NodeLifecycleCallback {
|
||||||
fun onFlowCreated(room: MatrixRoom) = Unit
|
fun onFlowCreated(identifier: String, room: MatrixRoom) = Unit
|
||||||
fun onFlowReleased(room: MatrixRoom) = Unit
|
fun onFlowReleased(identifier: String, room: MatrixRoom) = Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
data class Inputs(
|
data class Inputs(
|
||||||
|
|
@ -83,14 +83,14 @@ class RoomFlowNode @AssistedInject constructor(
|
||||||
lifecycle.subscribe(
|
lifecycle.subscribe(
|
||||||
onCreate = {
|
onCreate = {
|
||||||
Timber.v("OnCreate")
|
Timber.v("OnCreate")
|
||||||
plugins<LifecycleCallback>().forEach { it.onFlowCreated(inputs.room) }
|
plugins<LifecycleCallback>().forEach { it.onFlowCreated(id, inputs.room) }
|
||||||
appNavigationStateService.onNavigateToRoom(id, inputs.room.roomId)
|
appNavigationStateService.onNavigateToRoom(id, inputs.room.roomId)
|
||||||
fetchRoomMembers()
|
fetchRoomMembers()
|
||||||
},
|
},
|
||||||
onDestroy = {
|
onDestroy = {
|
||||||
Timber.v("OnDestroy")
|
Timber.v("OnDestroy")
|
||||||
inputs.room.close()
|
inputs.room.close()
|
||||||
plugins<LifecycleCallback>().forEach { it.onFlowReleased(inputs.room) }
|
plugins<LifecycleCallback>().forEach { it.onFlowReleased(id, inputs.room) }
|
||||||
appNavigationStateService.onLeavingRoom(id)
|
appNavigationStateService.onLeavingRoom(id)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue