ActiveSessionHolder to more things related to other @Singleton, and especially some missing cleanup

Such as calling `removeListener()` and `callSignalingService().removeCallListener()`
`Session.configureAndStart()` do less thing now
This commit is contained in:
Benoit Marty 2020-07-03 15:42:31 +02:00
parent 6569ee5d10
commit 811cbb2e20
10 changed files with 87 additions and 77 deletions

View File

@ -44,15 +44,12 @@ import im.vector.riotx.core.di.HasVectorInjector
import im.vector.riotx.core.di.VectorComponent import im.vector.riotx.core.di.VectorComponent
import im.vector.riotx.core.extensions.configureAndStart import im.vector.riotx.core.extensions.configureAndStart
import im.vector.riotx.core.rx.RxConfig import im.vector.riotx.core.rx.RxConfig
import im.vector.riotx.features.call.WebRtcPeerConnectionManager
import im.vector.riotx.features.configuration.VectorConfiguration import im.vector.riotx.features.configuration.VectorConfiguration
import im.vector.riotx.features.lifecycle.VectorActivityLifecycleCallbacks import im.vector.riotx.features.lifecycle.VectorActivityLifecycleCallbacks
import im.vector.riotx.features.notifications.NotificationDrawerManager import im.vector.riotx.features.notifications.NotificationDrawerManager
import im.vector.riotx.features.notifications.NotificationUtils import im.vector.riotx.features.notifications.NotificationUtils
import im.vector.riotx.features.notifications.PushRuleTriggerListener
import im.vector.riotx.features.popup.PopupAlertManager import im.vector.riotx.features.popup.PopupAlertManager
import im.vector.riotx.features.rageshake.VectorUncaughtExceptionHandler import im.vector.riotx.features.rageshake.VectorUncaughtExceptionHandler
import im.vector.riotx.features.session.SessionListener
import im.vector.riotx.features.settings.VectorPreferences import im.vector.riotx.features.settings.VectorPreferences
import im.vector.riotx.features.version.VersionProvider import im.vector.riotx.features.version.VersionProvider
import im.vector.riotx.push.fcm.FcmHelper import im.vector.riotx.push.fcm.FcmHelper
@ -79,16 +76,13 @@ class VectorApplication :
@Inject lateinit var emojiCompatWrapper: EmojiCompatWrapper @Inject lateinit var emojiCompatWrapper: EmojiCompatWrapper
@Inject lateinit var vectorUncaughtExceptionHandler: VectorUncaughtExceptionHandler @Inject lateinit var vectorUncaughtExceptionHandler: VectorUncaughtExceptionHandler
@Inject lateinit var activeSessionHolder: ActiveSessionHolder @Inject lateinit var activeSessionHolder: ActiveSessionHolder
@Inject lateinit var sessionListener: SessionListener
@Inject lateinit var notificationDrawerManager: NotificationDrawerManager @Inject lateinit var notificationDrawerManager: NotificationDrawerManager
@Inject lateinit var pushRuleTriggerListener: PushRuleTriggerListener
@Inject lateinit var vectorPreferences: VectorPreferences @Inject lateinit var vectorPreferences: VectorPreferences
@Inject lateinit var versionProvider: VersionProvider @Inject lateinit var versionProvider: VersionProvider
@Inject lateinit var notificationUtils: NotificationUtils @Inject lateinit var notificationUtils: NotificationUtils
@Inject lateinit var appStateHandler: AppStateHandler @Inject lateinit var appStateHandler: AppStateHandler
@Inject lateinit var rxConfig: RxConfig @Inject lateinit var rxConfig: RxConfig
@Inject lateinit var popupAlertManager: PopupAlertManager @Inject lateinit var popupAlertManager: PopupAlertManager
@Inject lateinit var webRtcPeerConnectionManager: WebRtcPeerConnectionManager
lateinit var vectorComponent: VectorComponent lateinit var vectorComponent: VectorComponent
@ -137,12 +131,7 @@ class VectorApplication :
if (authenticationService.hasAuthenticatedSessions() && !activeSessionHolder.hasActiveSession()) { if (authenticationService.hasAuthenticatedSessions() && !activeSessionHolder.hasActiveSession()) {
val lastAuthenticatedSession = authenticationService.getLastAuthenticatedSession()!! val lastAuthenticatedSession = authenticationService.getLastAuthenticatedSession()!!
activeSessionHolder.setActiveSession(lastAuthenticatedSession) activeSessionHolder.setActiveSession(lastAuthenticatedSession)
lastAuthenticatedSession.configureAndStart( lastAuthenticatedSession.configureAndStart(applicationContext)
applicationContext,
pushRuleTriggerListener,
webRtcPeerConnectionManager,
sessionListener
)
} }
ProcessLifecycleOwner.get().lifecycle.addObserver(object : LifecycleObserver { ProcessLifecycleOwner.get().lifecycle.addObserver(object : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME) @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)

View File

@ -20,8 +20,12 @@ import arrow.core.Option
import im.vector.matrix.android.api.auth.AuthenticationService import im.vector.matrix.android.api.auth.AuthenticationService
import im.vector.matrix.android.api.session.Session import im.vector.matrix.android.api.session.Session
import im.vector.riotx.ActiveSessionDataSource import im.vector.riotx.ActiveSessionDataSource
import im.vector.riotx.features.call.WebRtcPeerConnectionManager
import im.vector.riotx.features.crypto.keysrequest.KeyRequestHandler import im.vector.riotx.features.crypto.keysrequest.KeyRequestHandler
import im.vector.riotx.features.crypto.verification.IncomingVerificationRequestHandler import im.vector.riotx.features.crypto.verification.IncomingVerificationRequestHandler
import im.vector.riotx.features.notifications.PushRuleTriggerListener
import im.vector.riotx.features.session.SessionListener
import timber.log.Timber
import java.util.concurrent.atomic.AtomicReference import java.util.concurrent.atomic.AtomicReference
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@ -30,23 +34,40 @@ import javax.inject.Singleton
class ActiveSessionHolder @Inject constructor(private val authenticationService: AuthenticationService, class ActiveSessionHolder @Inject constructor(private val authenticationService: AuthenticationService,
private val sessionObservableStore: ActiveSessionDataSource, private val sessionObservableStore: ActiveSessionDataSource,
private val keyRequestHandler: KeyRequestHandler, private val keyRequestHandler: KeyRequestHandler,
private val incomingVerificationRequestHandler: IncomingVerificationRequestHandler private val incomingVerificationRequestHandler: IncomingVerificationRequestHandler,
private val webRtcPeerConnectionManager: WebRtcPeerConnectionManager,
private val pushRuleTriggerListener: PushRuleTriggerListener,
private val sessionListener: SessionListener
) { ) {
private var activeSession: AtomicReference<Session?> = AtomicReference() private var activeSession: AtomicReference<Session?> = AtomicReference()
fun setActiveSession(session: Session) { fun setActiveSession(session: Session) {
Timber.w("setActiveSession of ${session.myUserId}")
activeSession.set(session) activeSession.set(session)
sessionObservableStore.post(Option.just(session)) sessionObservableStore.post(Option.just(session))
keyRequestHandler.start(session) keyRequestHandler.start(session)
incomingVerificationRequestHandler.start(session) incomingVerificationRequestHandler.start(session)
session.addListener(sessionListener)
pushRuleTriggerListener.startWithSession(session)
session.callSignalingService().addCallListener(webRtcPeerConnectionManager)
} }
fun clearActiveSession() { fun clearActiveSession() {
// Do some cleanup first
getSafeActiveSession()?.let {
Timber.w("clearActiveSession of ${it.myUserId}")
it.callSignalingService().removeCallListener(webRtcPeerConnectionManager)
it.removeListener(sessionListener)
}
activeSession.set(null) activeSession.set(null)
sessionObservableStore.post(Option.empty()) sessionObservableStore.post(Option.empty())
keyRequestHandler.stop() keyRequestHandler.stop()
incomingVerificationRequestHandler.stop() incomingVerificationRequestHandler.stop()
pushRuleTriggerListener.stop()
} }
fun hasActiveSession(): Boolean { fun hasActiveSession(): Boolean {

View File

@ -24,23 +24,14 @@ import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupState import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupState
import im.vector.matrix.android.api.session.sync.FilterService import im.vector.matrix.android.api.session.sync.FilterService
import im.vector.riotx.core.services.VectorSyncService import im.vector.riotx.core.services.VectorSyncService
import im.vector.riotx.features.call.WebRtcPeerConnectionManager
import im.vector.riotx.features.notifications.PushRuleTriggerListener
import im.vector.riotx.features.session.SessionListener
import timber.log.Timber import timber.log.Timber
fun Session.configureAndStart(context: Context, fun Session.configureAndStart(context: Context) {
pushRuleTriggerListener: PushRuleTriggerListener, Timber.i("Configure and start session for $myUserId")
webRtcPeerConnectionManager: WebRtcPeerConnectionManager,
sessionListener: SessionListener) {
open() open()
addListener(sessionListener)
setFilter(FilterService.FilterPreset.RiotFilter) setFilter(FilterService.FilterPreset.RiotFilter)
Timber.i("Configure and start session for ${this.myUserId}")
startSyncing(context) startSyncing(context)
refreshPushers() refreshPushers()
pushRuleTriggerListener.startWithSession(this)
callSignalingService().addCallListener(webRtcPeerConnectionManager)
} }
fun Session.startSyncing(context: Context) { fun Session.startSyncing(context: Context) {

View File

@ -36,6 +36,9 @@ open class BehaviorDataSource<T>(private val defaultValue: T? = null) : MutableD
private val behaviorRelay = createRelay() private val behaviorRelay = createRelay()
val currentValue: T?
get() = behaviorRelay.value
override fun observe(): Observable<T> { override fun observe(): Observable<T> {
return behaviorRelay.hide().observeOn(AndroidSchedulers.mainThread()) return behaviorRelay.hide().observeOn(AndroidSchedulers.mainThread())
} }

View File

@ -22,6 +22,7 @@ import android.os.Build
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.extensions.tryThis import im.vector.matrix.android.api.extensions.tryThis
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.call.CallState import im.vector.matrix.android.api.session.call.CallState
import im.vector.matrix.android.api.session.call.CallsListener import im.vector.matrix.android.api.session.call.CallsListener
import im.vector.matrix.android.api.session.call.EglUtils import im.vector.matrix.android.api.session.call.EglUtils
@ -31,7 +32,7 @@ import im.vector.matrix.android.api.session.room.model.call.CallAnswerContent
import im.vector.matrix.android.api.session.room.model.call.CallCandidatesContent import im.vector.matrix.android.api.session.room.model.call.CallCandidatesContent
import im.vector.matrix.android.api.session.room.model.call.CallHangupContent import im.vector.matrix.android.api.session.room.model.call.CallHangupContent
import im.vector.matrix.android.api.session.room.model.call.CallInviteContent import im.vector.matrix.android.api.session.room.model.call.CallInviteContent
import im.vector.riotx.core.di.ActiveSessionHolder import im.vector.riotx.ActiveSessionDataSource
import im.vector.riotx.core.services.BluetoothHeadsetReceiver import im.vector.riotx.core.services.BluetoothHeadsetReceiver
import im.vector.riotx.core.services.CallService import im.vector.riotx.core.services.CallService
import im.vector.riotx.core.services.WiredHeadsetStateReceiver import im.vector.riotx.core.services.WiredHeadsetStateReceiver
@ -71,9 +72,12 @@ import javax.inject.Singleton
@Singleton @Singleton
class WebRtcPeerConnectionManager @Inject constructor( class WebRtcPeerConnectionManager @Inject constructor(
private val context: Context, private val context: Context,
private val sessionHolder: ActiveSessionHolder private val activeSessionDataSource: ActiveSessionDataSource
) : CallsListener { ) : CallsListener {
private val currentSession: Session?
get() = activeSessionDataSource.currentValue?.orNull()
interface CurrentCallListener { interface CurrentCallListener {
fun onCurrentCallChange(call: MxCall?) fun onCurrentCallChange(call: MxCall?)
fun onCaptureStateChanged(mgr: WebRtcPeerConnectionManager) {} fun onCaptureStateChanged(mgr: WebRtcPeerConnectionManager) {}
@ -288,15 +292,16 @@ class WebRtcPeerConnectionManager @Inject constructor(
} }
private fun getTurnServer(callback: ((TurnServerResponse?) -> Unit)) { private fun getTurnServer(callback: ((TurnServerResponse?) -> Unit)) {
sessionHolder.getActiveSession().callSignalingService().getTurnServer(object : MatrixCallback<TurnServerResponse?> { currentSession?.callSignalingService()
override fun onSuccess(data: TurnServerResponse?) { ?.getTurnServer(object : MatrixCallback<TurnServerResponse?> {
callback(data) override fun onSuccess(data: TurnServerResponse?) {
} callback(data)
}
override fun onFailure(failure: Throwable) { override fun onFailure(failure: Throwable) {
callback(null) callback(null)
} }
}) })
} }
fun attachViewRenderers(localViewRenderer: SurfaceViewRenderer?, remoteViewRenderer: SurfaceViewRenderer, mode: String?) { fun attachViewRenderers(localViewRenderer: SurfaceViewRenderer?, remoteViewRenderer: SurfaceViewRenderer, mode: String?) {
@ -310,7 +315,7 @@ class WebRtcPeerConnectionManager @Inject constructor(
currentCall?.mxCall currentCall?.mxCall
?.takeIf { it.state is CallState.Connected } ?.takeIf { it.state is CallState.Connected }
?.let { mxCall -> ?.let { mxCall ->
val name = sessionHolder.getSafeActiveSession()?.getUser(mxCall.otherUserId)?.getBestName() val name = currentSession?.getUser(mxCall.otherUserId)?.getBestName()
?: mxCall.roomId ?: mxCall.roomId
// Start background service with notification // Start background service with notification
CallService.onPendingCall( CallService.onPendingCall(
@ -318,7 +323,7 @@ class WebRtcPeerConnectionManager @Inject constructor(
isVideo = mxCall.isVideoCall, isVideo = mxCall.isVideoCall,
roomName = name, roomName = name,
roomId = mxCall.roomId, roomId = mxCall.roomId,
matrixId = sessionHolder.getSafeActiveSession()?.myUserId ?: "", matrixId = currentSession?.myUserId ?: "",
callId = mxCall.callId) callId = mxCall.callId)
} }
@ -373,14 +378,14 @@ class WebRtcPeerConnectionManager @Inject constructor(
val mxCall = callContext.mxCall val mxCall = callContext.mxCall
// Update service state // Update service state
val name = sessionHolder.getSafeActiveSession()?.getUser(mxCall.otherUserId)?.getBestName() val name = currentSession?.getUser(mxCall.otherUserId)?.getBestName()
?: mxCall.roomId ?: mxCall.roomId
CallService.onPendingCall( CallService.onPendingCall(
context = context, context = context,
isVideo = mxCall.isVideoCall, isVideo = mxCall.isVideoCall,
roomName = name, roomName = name,
roomId = mxCall.roomId, roomId = mxCall.roomId,
matrixId = sessionHolder.getSafeActiveSession()?.myUserId ?: "", matrixId = currentSession?.myUserId ?: "",
callId = mxCall.callId callId = mxCall.callId
) )
executor.execute { executor.execute {
@ -563,14 +568,14 @@ class WebRtcPeerConnectionManager @Inject constructor(
?.let { mxCall -> ?.let { mxCall ->
// Start background service with notification // Start background service with notification
val name = sessionHolder.getSafeActiveSession()?.getUser(mxCall.otherUserId)?.getBestName() val name = currentSession?.getUser(mxCall.otherUserId)?.getBestName()
?: mxCall.otherUserId ?: mxCall.otherUserId
CallService.onOnGoingCallBackground( CallService.onOnGoingCallBackground(
context = context, context = context,
isVideo = mxCall.isVideoCall, isVideo = mxCall.isVideoCall,
roomName = name, roomName = name,
roomId = mxCall.roomId, roomId = mxCall.roomId,
matrixId = sessionHolder.getSafeActiveSession()?.myUserId ?: "", matrixId = currentSession?.myUserId ?: "",
callId = mxCall.callId callId = mxCall.callId
) )
} }
@ -631,20 +636,20 @@ class WebRtcPeerConnectionManager @Inject constructor(
} }
Timber.v("## VOIP startOutgoingCall in room $signalingRoomId to $otherUserId isVideo $isVideoCall") Timber.v("## VOIP startOutgoingCall in room $signalingRoomId to $otherUserId isVideo $isVideoCall")
val createdCall = sessionHolder.getSafeActiveSession()?.callSignalingService()?.createOutgoingCall(signalingRoomId, otherUserId, isVideoCall) ?: return val createdCall = currentSession?.callSignalingService()?.createOutgoingCall(signalingRoomId, otherUserId, isVideoCall) ?: return
val callContext = CallContext(createdCall) val callContext = CallContext(createdCall)
audioManager.startForCall(createdCall) audioManager.startForCall(createdCall)
currentCall = callContext currentCall = callContext
val name = sessionHolder.getSafeActiveSession()?.getUser(createdCall.otherUserId)?.getBestName() val name = currentSession?.getUser(createdCall.otherUserId)?.getBestName()
?: createdCall.otherUserId ?: createdCall.otherUserId
CallService.onOutgoingCallRinging( CallService.onOutgoingCallRinging(
context = context.applicationContext, context = context.applicationContext,
isVideo = createdCall.isVideoCall, isVideo = createdCall.isVideoCall,
roomName = name, roomName = name,
roomId = createdCall.roomId, roomId = createdCall.roomId,
matrixId = sessionHolder.getSafeActiveSession()?.myUserId ?: "", matrixId = currentSession?.myUserId ?: "",
callId = createdCall.callId) callId = createdCall.callId)
executor.execute { executor.execute {
@ -693,14 +698,14 @@ class WebRtcPeerConnectionManager @Inject constructor(
} }
// Start background service with notification // Start background service with notification
val name = sessionHolder.getSafeActiveSession()?.getUser(mxCall.otherUserId)?.getBestName() val name = currentSession?.getUser(mxCall.otherUserId)?.getBestName()
?: mxCall.otherUserId ?: mxCall.otherUserId
CallService.onIncomingCallRinging( CallService.onIncomingCallRinging(
context = context, context = context,
isVideo = mxCall.isVideoCall, isVideo = mxCall.isVideoCall,
roomName = name, roomName = name,
roomId = mxCall.roomId, roomId = mxCall.roomId,
matrixId = sessionHolder.getSafeActiveSession()?.myUserId ?: "", matrixId = currentSession?.myUserId ?: "",
callId = mxCall.callId callId = mxCall.callId
) )
@ -818,14 +823,14 @@ class WebRtcPeerConnectionManager @Inject constructor(
} }
val mxCall = call.mxCall val mxCall = call.mxCall
// Update service state // Update service state
val name = sessionHolder.getSafeActiveSession()?.getUser(mxCall.otherUserId)?.getBestName() val name = currentSession?.getUser(mxCall.otherUserId)?.getBestName()
?: mxCall.otherUserId ?: mxCall.otherUserId
CallService.onPendingCall( CallService.onPendingCall(
context = context, context = context,
isVideo = mxCall.isVideoCall, isVideo = mxCall.isVideoCall,
roomName = name, roomName = name,
roomId = mxCall.roomId, roomId = mxCall.roomId,
matrixId = sessionHolder.getSafeActiveSession()?.myUserId ?: "", matrixId = currentSession?.myUserId ?: "",
callId = mxCall.callId callId = mxCall.callId
) )
executor.execute { executor.execute {

View File

@ -40,17 +40,20 @@ import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.matrix.android.api.session.widgets.model.WidgetContent import im.vector.matrix.android.api.session.widgets.model.WidgetContent
import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
import im.vector.matrix.android.internal.crypto.model.event.EncryptionEventContent import im.vector.matrix.android.internal.crypto.model.event.EncryptionEventContent
import im.vector.riotx.ActiveSessionDataSource
import im.vector.riotx.R import im.vector.riotx.R
import im.vector.riotx.core.di.ActiveSessionHolder
import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.core.resources.StringProvider
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
class NoticeEventFormatter @Inject constructor(private val sessionHolder: ActiveSessionHolder, class NoticeEventFormatter @Inject constructor(private val activeSessionDataSource: ActiveSessionDataSource,
private val roomHistoryVisibilityFormatter: RoomHistoryVisibilityFormatter, private val roomHistoryVisibilityFormatter: RoomHistoryVisibilityFormatter,
private val sp: StringProvider) { private val sp: StringProvider) {
private fun Event.isSentByCurrentUser() = senderId != null && senderId == sessionHolder.getSafeActiveSession()?.myUserId private val currentUserId: String?
get() = activeSessionDataSource.currentValue?.orNull()?.myUserId
private fun Event.isSentByCurrentUser() = senderId != null && senderId == currentUserId
fun format(timelineEvent: TimelineEvent): CharSequence? { fun format(timelineEvent: TimelineEvent): CharSequence? {
return when (val type = timelineEvent.root.getClearType()) { return when (val type = timelineEvent.root.getClearType()) {
@ -449,7 +452,6 @@ class NoticeEventFormatter @Inject constructor(private val sessionHolder: Active
val targetDisplayName = eventContent?.displayName ?: prevEventContent?.displayName ?: event.stateKey ?: "" val targetDisplayName = eventContent?.displayName ?: prevEventContent?.displayName ?: event.stateKey ?: ""
return when (eventContent?.membership) { return when (eventContent?.membership) {
Membership.INVITE -> { Membership.INVITE -> {
val selfUserId = sessionHolder.getSafeActiveSession()?.myUserId
when { when {
eventContent.thirdPartyInvite != null -> { eventContent.thirdPartyInvite != null -> {
val userWhoHasAccepted = eventContent.thirdPartyInvite?.signed?.mxid ?: event.stateKey val userWhoHasAccepted = eventContent.thirdPartyInvite?.signed?.mxid ?: event.stateKey
@ -466,7 +468,7 @@ class NoticeEventFormatter @Inject constructor(private val sessionHolder: Active
sp.getString(R.string.notice_room_third_party_registered_invite, userWhoHasAccepted, threePidDisplayName) sp.getString(R.string.notice_room_third_party_registered_invite, userWhoHasAccepted, threePidDisplayName)
} }
} }
event.stateKey == selfUserId -> event.stateKey == currentUserId ->
eventContent.safeReason?.let { reason -> eventContent.safeReason?.let { reason ->
sp.getString(R.string.notice_room_invite_you_with_reason, senderDisplayName, reason) sp.getString(R.string.notice_room_invite_you_with_reason, senderDisplayName, reason)
} ?: sp.getString(R.string.notice_room_invite_you, senderDisplayName) } ?: sp.getString(R.string.notice_room_invite_you, senderDisplayName)

View File

@ -49,9 +49,6 @@ import im.vector.riotx.core.extensions.exhaustive
import im.vector.riotx.core.platform.VectorViewModel import im.vector.riotx.core.platform.VectorViewModel
import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.core.resources.StringProvider
import im.vector.riotx.core.utils.ensureTrailingSlash import im.vector.riotx.core.utils.ensureTrailingSlash
import im.vector.riotx.features.call.WebRtcPeerConnectionManager
import im.vector.riotx.features.notifications.PushRuleTriggerListener
import im.vector.riotx.features.session.SessionListener
import im.vector.riotx.features.signout.soft.SoftLogoutActivity import im.vector.riotx.features.signout.soft.SoftLogoutActivity
import timber.log.Timber import timber.log.Timber
import java.util.concurrent.CancellationException import java.util.concurrent.CancellationException
@ -64,13 +61,10 @@ class LoginViewModel @AssistedInject constructor(
private val applicationContext: Context, private val applicationContext: Context,
private val authenticationService: AuthenticationService, private val authenticationService: AuthenticationService,
private val activeSessionHolder: ActiveSessionHolder, private val activeSessionHolder: ActiveSessionHolder,
private val pushRuleTriggerListener: PushRuleTriggerListener,
private val homeServerConnectionConfigFactory: HomeServerConnectionConfigFactory, private val homeServerConnectionConfigFactory: HomeServerConnectionConfigFactory,
private val sessionListener: SessionListener,
private val reAuthHelper: ReAuthHelper, private val reAuthHelper: ReAuthHelper,
private val stringProvider: StringProvider, private val stringProvider: StringProvider
private val webRtcPeerConnectionManager: WebRtcPeerConnectionManager) ) : VectorViewModel<LoginViewState, LoginAction, LoginViewEvents>(initialState) {
: VectorViewModel<LoginViewState, LoginAction, LoginViewEvents>(initialState) {
@AssistedInject.Factory @AssistedInject.Factory
interface Factory { interface Factory {
@ -667,11 +661,7 @@ class LoginViewModel @AssistedInject constructor(
private fun onSessionCreated(session: Session) { private fun onSessionCreated(session: Session) {
activeSessionHolder.setActiveSession(session) activeSessionHolder.setActiveSession(session)
session.configureAndStart( session.configureAndStart(applicationContext)
applicationContext,
pushRuleTriggerListener,
webRtcPeerConnectionManager,
sessionListener)
setState { setState {
copy( copy(
asyncLoginAction = Success(Unit) asyncLoginAction = Success(Unit)

View File

@ -22,10 +22,11 @@ import android.os.HandlerThread
import androidx.annotation.WorkerThread import androidx.annotation.WorkerThread
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.app.Person import androidx.core.app.Person
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.content.ContentUrlResolver import im.vector.matrix.android.api.session.content.ContentUrlResolver
import im.vector.riotx.ActiveSessionDataSource
import im.vector.riotx.BuildConfig import im.vector.riotx.BuildConfig
import im.vector.riotx.R import im.vector.riotx.R
import im.vector.riotx.core.di.ActiveSessionHolder
import im.vector.riotx.core.resources.StringProvider import im.vector.riotx.core.resources.StringProvider
import im.vector.riotx.features.settings.VectorPreferences import im.vector.riotx.features.settings.VectorPreferences
import me.gujun.android.span.span import me.gujun.android.span.span
@ -46,7 +47,7 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
private val notificationUtils: NotificationUtils, private val notificationUtils: NotificationUtils,
private val vectorPreferences: VectorPreferences, private val vectorPreferences: VectorPreferences,
private val stringProvider: StringProvider, private val stringProvider: StringProvider,
private val activeSessionHolder: ActiveSessionHolder, private val activeSessionDataSource: ActiveSessionDataSource,
private val iconLoader: IconLoader, private val iconLoader: IconLoader,
private val bitmapLoader: BitmapLoader, private val bitmapLoader: BitmapLoader,
private val outdatedDetector: OutdatedEventDetector?) { private val outdatedDetector: OutdatedEventDetector?) {
@ -68,6 +69,10 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
private var currentRoomId: String? = null private var currentRoomId: String? = null
// TODO Multi-session: this will have to be improved
private val currentSession: Session?
get() = activeSessionDataSource.currentValue?.orNull()
/** /**
Should be called as soon as a new event is ready to be displayed. Should be called as soon as a new event is ready to be displayed.
The notification corresponding to this event will not be displayed until The notification corresponding to this event will not be displayed until
@ -204,7 +209,7 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
private fun refreshNotificationDrawerBg() { private fun refreshNotificationDrawerBg() {
Timber.v("refreshNotificationDrawerBg()") Timber.v("refreshNotificationDrawerBg()")
val session = activeSessionHolder.getSafeActiveSession() ?: return val session = currentSession ?: return
val user = session.getUser(session.myUserId) val user = session.getUser(session.myUserId)
// myUserDisplayName cannot be empty else NotificationCompat.MessagingStyle() will crash // myUserDisplayName cannot be empty else NotificationCompat.MessagingStyle() will crash
@ -474,7 +479,7 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
val file = File(context.applicationContext.cacheDir, ROOMS_NOTIFICATIONS_FILE_NAME) val file = File(context.applicationContext.cacheDir, ROOMS_NOTIFICATIONS_FILE_NAME)
if (!file.exists()) file.createNewFile() if (!file.exists()) file.createNewFile()
FileOutputStream(file).use { FileOutputStream(file).use {
activeSessionHolder.getSafeActiveSession()?.securelyStoreObject(eventList, KEY_ALIAS_SECRET_STORAGE, it) currentSession?.securelyStoreObject(eventList, KEY_ALIAS_SECRET_STORAGE, it)
} }
} catch (e: Throwable) { } catch (e: Throwable) {
Timber.e(e, "## Failed to save cached notification info") Timber.e(e, "## Failed to save cached notification info")
@ -487,7 +492,7 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
val file = File(context.applicationContext.cacheDir, ROOMS_NOTIFICATIONS_FILE_NAME) val file = File(context.applicationContext.cacheDir, ROOMS_NOTIFICATIONS_FILE_NAME)
if (file.exists()) { if (file.exists()) {
FileInputStream(file).use { FileInputStream(file).use {
val events: ArrayList<NotifiableEvent>? = activeSessionHolder.getSafeActiveSession()?.loadSecureSecret(it, KEY_ALIAS_SECRET_STORAGE) val events: ArrayList<NotifiableEvent>? = currentSession?.loadSecureSecret(it, KEY_ALIAS_SECRET_STORAGE)
if (events != null) { if (events != null) {
return events.toMutableList() return events.toMutableList()
} }

View File

@ -15,10 +15,12 @@
*/ */
package im.vector.riotx.features.notifications package im.vector.riotx.features.notifications
import im.vector.riotx.core.di.ActiveSessionHolder import im.vector.riotx.ActiveSessionDataSource
import javax.inject.Inject import javax.inject.Inject
class OutdatedEventDetector @Inject constructor(private val activeSessionHolder: ActiveSessionHolder) { class OutdatedEventDetector @Inject constructor(
private val activeSessionDataSource: ActiveSessionDataSource
) {
/** /**
* Returns true if the given event is outdated. * Returns true if the given event is outdated.
@ -26,10 +28,12 @@ class OutdatedEventDetector @Inject constructor(private val activeSessionHolder:
* other device. * other device.
*/ */
fun isMessageOutdated(notifiableEvent: NotifiableEvent): Boolean { fun isMessageOutdated(notifiableEvent: NotifiableEvent): Boolean {
val session = activeSessionDataSource.currentValue?.orNull() ?: return false
if (notifiableEvent is NotifiableMessageEvent) { if (notifiableEvent is NotifiableMessageEvent) {
val eventID = notifiableEvent.eventId val eventID = notifiableEvent.eventId
val roomID = notifiableEvent.roomId val roomID = notifiableEvent.roomId
val room = activeSessionHolder.getSafeActiveSession()?.getRoom(roomID) ?: return false val room = session.getRoom(roomID) ?: return false
return room.isEventRead(eventID) return room.isEventRead(eventID)
} }
return false return false

View File

@ -30,17 +30,17 @@ class PushRuleTriggerListener @Inject constructor(
private val notificationDrawerManager: NotificationDrawerManager private val notificationDrawerManager: NotificationDrawerManager
) : PushRuleService.PushRuleListener { ) : PushRuleService.PushRuleListener {
var session: Session? = null private var session: Session? = null
override fun onMatchRule(event: Event, actions: List<Action>) { override fun onMatchRule(event: Event, actions: List<Action>) {
Timber.v("Push rule match for event ${event.eventId}") Timber.v("Push rule match for event ${event.eventId}")
if (session == null) { val safeSession = session ?: return Unit.also {
Timber.e("Called without active session") Timber.e("Called without active session")
return
} }
val notificationAction = actions.toNotificationAction() val notificationAction = actions.toNotificationAction()
if (notificationAction.shouldNotify) { if (notificationAction.shouldNotify) {
val notifiableEvent = resolver.resolveEvent(event, session!!) val notifiableEvent = resolver.resolveEvent(event, safeSession)
if (notifiableEvent == null) { if (notifiableEvent == null) {
Timber.v("## Failed to resolve event") Timber.v("## Failed to resolve event")
// TODO // TODO