Delegate the creation of the Session to MainActivity instead of VectorApplication to unblock the main thread.

This fix is not necessary anymore, since the session is restored either in `MainActivity` or in `VectorMessagingReceiver`.
Ref: b7a54ead68
This commit is contained in:
Benoit Marty 2022-07-13 21:40:48 +02:00 committed by Benoit Marty
parent 6b0f8318b7
commit 0dd9e943c7
6 changed files with 136 additions and 18 deletions

View file

@ -0,0 +1,66 @@
/*
* Copyright (c) 2022 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 im.vector.app.features
import com.airbnb.mvrx.MavericksViewModelFactory
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.di.ActiveSessionSetter
import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.VectorDummyViewState
import im.vector.app.core.platform.VectorViewEvents
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.platform.VectorViewModelAction
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
sealed interface MainViewAction : VectorViewModelAction {
object StartApp : MainViewAction
}
sealed interface MainViewEvent : VectorViewEvents {
object AppStarted : MainViewEvent
}
class MainViewModel @AssistedInject constructor(
@Assisted val initialState: VectorDummyViewState,
private val activeSessionSetter: ActiveSessionSetter,
) : VectorViewModel<VectorDummyViewState, MainViewAction, MainViewEvent>(initialState) {
@AssistedFactory
interface Factory : MavericksAssistedViewModelFactory<MainViewModel, VectorDummyViewState> {
override fun create(initialState: VectorDummyViewState): MainViewModel
}
companion object : MavericksViewModelFactory<MainViewModel, VectorDummyViewState> by hiltMavericksViewModelFactory()
override fun handle(action: MainViewAction) {
when (action) {
MainViewAction.StartApp -> handleStartApp()
}
}
private fun handleStartApp() {
viewModelScope.launch(Dispatchers.IO) {
// This can take time because of DB migration(s), so do it in a background task.
activeSessionSetter.tryToSetActiveSession(startSync = true)
_viewEvents.post(MainViewEvent.AppStarted)
}
}
}

View file

@ -41,8 +41,6 @@ import com.vanniktech.emoji.EmojiManager
import com.vanniktech.emoji.google.GoogleEmojiProvider import com.vanniktech.emoji.google.GoogleEmojiProvider
import dagger.hilt.android.HiltAndroidApp import dagger.hilt.android.HiltAndroidApp
import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.extensions.configureAndStart
import im.vector.app.core.extensions.startSyncing
import im.vector.app.features.analytics.VectorAnalytics import im.vector.app.features.analytics.VectorAnalytics
import im.vector.app.features.call.webrtc.WebRtcCallManager import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.configuration.VectorConfiguration import im.vector.app.features.configuration.VectorConfiguration
@ -165,14 +163,6 @@ class VectorApplication :
doNotShowDisclaimerDialog(this) doNotShowDisclaimerDialog(this)
} }
if (authenticationService.hasAuthenticatedSessions() && !activeSessionHolder.hasActiveSession()) {
val lastAuthenticatedSession = authenticationService.getLastAuthenticatedSession()!!
activeSessionHolder.setActiveSession(lastAuthenticatedSession)
lastAuthenticatedSession.configureAndStart(applicationContext, startSyncing = false)
}
ProcessLifecycleOwner.get().lifecycle.addObserver(startSyncOnFirstStart)
ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver { ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onResume(owner: LifecycleOwner) { override fun onResume(owner: LifecycleOwner) {
Timber.i("App entered foreground") Timber.i("App entered foreground")
@ -205,14 +195,6 @@ class VectorApplication :
Mapbox.getInstance(this) Mapbox.getInstance(this)
} }
private val startSyncOnFirstStart = object : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) {
Timber.i("App process started")
authenticationService.getLastAuthenticatedSession()?.startSyncing(appContext)
ProcessLifecycleOwner.get().lifecycle.removeObserver(this)
}
}
private fun enableStrictModeIfNeeded() { private fun enableStrictModeIfNeeded() {
if (BuildConfig.ENABLE_STRICT_MODE_LOGS) { if (BuildConfig.ENABLE_STRICT_MODE_LOGS) {
StrictMode.setThreadPolicy( StrictMode.setThreadPolicy(

View file

@ -0,0 +1,37 @@
/*
* Copyright 2022 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 im.vector.app.core.di
import android.content.Context
import im.vector.app.core.extensions.configureAndStart
import org.matrix.android.sdk.api.auth.AuthenticationService
import javax.inject.Inject
class ActiveSessionSetter @Inject constructor(
private val activeSessionHolder: ActiveSessionHolder,
private val authenticationService: AuthenticationService,
private val applicationContext: Context,
) {
fun tryToSetActiveSession(startSync: Boolean) {
if (authenticationService.hasAuthenticatedSessions() && !activeSessionHolder.hasActiveSession()) {
val lastAuthenticatedSession = authenticationService.getLastAuthenticatedSession()!!
activeSessionHolder.setActiveSession(lastAuthenticatedSession)
lastAuthenticatedSession.configureAndStart(applicationContext, startSyncing = startSync)
activeSessionHolder.setActiveSession(lastAuthenticatedSession)
}
}
}

View file

@ -20,6 +20,7 @@ import dagger.Binds
import dagger.Module import dagger.Module
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
import dagger.multibindings.IntoMap import dagger.multibindings.IntoMap
import im.vector.app.features.MainViewModel
import im.vector.app.features.analytics.accountdata.AnalyticsAccountDataViewModel import im.vector.app.features.analytics.accountdata.AnalyticsAccountDataViewModel
import im.vector.app.features.analytics.ui.consent.AnalyticsConsentViewModel import im.vector.app.features.analytics.ui.consent.AnalyticsConsentViewModel
import im.vector.app.features.auth.ReAuthViewModel import im.vector.app.features.auth.ReAuthViewModel
@ -483,6 +484,11 @@ interface MavericksViewModelModule {
@MavericksViewModelKey(AnalyticsAccountDataViewModel::class) @MavericksViewModelKey(AnalyticsAccountDataViewModel::class)
fun analyticsAccountDataViewModelFactory(factory: AnalyticsAccountDataViewModel.Factory): MavericksAssistedViewModelFactory<*, *> fun analyticsAccountDataViewModelFactory(factory: AnalyticsAccountDataViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds
@IntoMap
@MavericksViewModelKey(MainViewModel::class)
fun mainViewModelFactory(factory: MainViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
@Binds @Binds
@IntoMap @IntoMap
@MavericksViewModelKey(HomeServerCapabilitiesViewModel::class) @MavericksViewModelKey(HomeServerCapabilitiesViewModel::class)

View file

@ -27,6 +27,7 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.BuildConfig import im.vector.app.BuildConfig
import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.di.ActiveSessionSetter
import im.vector.app.core.network.WifiDetector import im.vector.app.core.network.WifiDetector
import im.vector.app.core.pushers.model.PushData import im.vector.app.core.pushers.model.PushData
import im.vector.app.core.services.GuardServiceStarter import im.vector.app.core.services.GuardServiceStarter
@ -59,6 +60,7 @@ class VectorMessagingReceiver : MessagingReceiver() {
@Inject lateinit var notificationDrawerManager: NotificationDrawerManager @Inject lateinit var notificationDrawerManager: NotificationDrawerManager
@Inject lateinit var notifiableEventResolver: NotifiableEventResolver @Inject lateinit var notifiableEventResolver: NotifiableEventResolver
@Inject lateinit var pushersManager: PushersManager @Inject lateinit var pushersManager: PushersManager
@Inject lateinit var activeSessionSetter: ActiveSessionSetter
@Inject lateinit var activeSessionHolder: ActiveSessionHolder @Inject lateinit var activeSessionHolder: ActiveSessionHolder
@Inject lateinit var vectorPreferences: VectorPreferences @Inject lateinit var vectorPreferences: VectorPreferences
@Inject lateinit var vectorDataStore: VectorDataStore @Inject lateinit var vectorDataStore: VectorDataStore
@ -177,6 +179,11 @@ class VectorMessagingReceiver : MessagingReceiver() {
} }
val session = activeSessionHolder.getSafeActiveSession() val session = activeSessionHolder.getSafeActiveSession()
?: run {
// Active session may not exist yet, if MainActivity has not been launched
activeSessionSetter.tryToSetActiveSession(startSync = false)
activeSessionHolder.getSafeActiveSession()
}
if (session == null) { if (session == null) {
Timber.tag(loggerTag.value).w("## Can't sync from push, no current session") Timber.tag(loggerTag.value).w("## Can't sync from push, no current session")

View file

@ -22,6 +22,7 @@ import android.os.Bundle
import android.os.Parcelable import android.os.Parcelable
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.airbnb.mvrx.viewModel
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
@ -47,6 +48,8 @@ import im.vector.app.features.signout.hard.SignedOutActivity
import im.vector.app.features.themes.ActivityOtherThemes import im.vector.app.features.themes.ActivityOtherThemes
import im.vector.app.features.ui.UiStateRepository import im.vector.app.features.ui.UiStateRepository
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
@ -84,6 +87,8 @@ class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity
} }
} }
private val mainViewModel: MainViewModel by viewModel()
override fun getBinding() = ActivityMainBinding.inflate(layoutInflater) override fun getBinding() = ActivityMainBinding.inflate(layoutInflater)
override fun getOtherThemes() = ActivityOtherThemes.Launcher override fun getOtherThemes() = ActivityOtherThemes.Launcher
@ -103,6 +108,21 @@ class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
mainViewModel.viewEvents.stream()
.onEach(::handleViewEvents)
.launchIn(lifecycleScope)
mainViewModel.handle(MainViewAction.StartApp)
}
private fun handleViewEvents(event: MainViewEvent) {
when (event) {
MainViewEvent.AppStarted -> handleAppStarted()
}
}
private fun handleAppStarted() {
args = parseArgs() args = parseArgs()
if (args.clearCredentials || args.isUserLoggedOut || args.clearCache) { if (args.clearCredentials || args.isUserLoggedOut || args.clearCache) {
clearNotifications() clearNotifications()