Merge pull request #5440 from element-hq/feature/bma/injectSessionId

Remove CurrentSessionIdHolder and inject SessionId instead.
This commit is contained in:
Benoit Marty 2025-10-02 18:06:17 +02:00 committed by GitHub
commit f5864f9f90
11 changed files with 31 additions and 47 deletions

View file

@ -13,6 +13,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRtcNotificationContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.timeline.item.event.CallNotifyContent import io.element.android.libraries.matrix.api.timeline.item.event.CallNotifyContent
import io.element.android.libraries.matrix.api.timeline.item.event.EventContent import io.element.android.libraries.matrix.api.timeline.item.event.EventContent
@ -31,7 +32,6 @@ import io.element.android.libraries.matrix.api.timeline.item.event.StickerConten
import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent
import io.element.android.libraries.matrix.api.timeline.item.event.UnknownContent import io.element.android.libraries.matrix.api.timeline.item.event.UnknownContent
import io.element.android.libraries.matrix.api.timeline.item.event.getDisambiguatedDisplayName import io.element.android.libraries.matrix.api.timeline.item.event.getDisambiguatedDisplayName
import io.element.android.libraries.matrix.api.user.CurrentSessionIdHolder
@Inject @Inject
class TimelineItemContentFactory( class TimelineItemContentFactory(
@ -45,7 +45,7 @@ class TimelineItemContentFactory(
private val stateFactory: TimelineItemContentStateFactory, private val stateFactory: TimelineItemContentStateFactory,
private val failedToParseMessageFactory: TimelineItemContentFailedToParseMessageFactory, private val failedToParseMessageFactory: TimelineItemContentFailedToParseMessageFactory,
private val failedToParseStateFactory: TimelineItemContentFailedToParseStateFactory, private val failedToParseStateFactory: TimelineItemContentFailedToParseStateFactory,
private val currentSessionIdHolder: CurrentSessionIdHolder, private val sessionId: SessionId,
) { ) {
suspend fun create(eventTimelineItem: EventTimelineItem): TimelineItemEventContent { suspend fun create(eventTimelineItem: EventTimelineItem): TimelineItemEventContent {
return create( return create(
@ -64,7 +64,7 @@ class TimelineItemContentFactory(
sender: UserId, sender: UserId,
senderProfile: ProfileTimelineDetails, senderProfile: ProfileTimelineDetails,
): TimelineItemEventContent { ): TimelineItemEventContent {
val isOutgoing = currentSessionIdHolder.current == sender val isOutgoing = sessionId == sender
return when (itemContent) { return when (itemContent) {
is FailedToParseMessageLikeContent -> failedToParseMessageFactory.create(itemContent) is FailedToParseMessageLikeContent -> failedToParseMessageFactory.create(itemContent)
is FailedToParseStateContent -> failedToParseStateFactory.create(itemContent) is FailedToParseStateContent -> failedToParseStateFactory.create(itemContent)

View file

@ -33,7 +33,6 @@ import io.element.android.libraries.dateformatter.test.FakeDateFormatter
import io.element.android.libraries.eventformatter.api.TimelineEventFormatter import io.element.android.libraries.eventformatter.api.TimelineEventFormatter
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.timeline.item.event.EventContent import io.element.android.libraries.matrix.api.timeline.item.event.EventContent
import io.element.android.libraries.matrix.api.user.CurrentSessionIdHolder
import io.element.android.libraries.matrix.test.FakeMatrixClient import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser import io.element.android.libraries.matrix.test.permalink.FakePermalinkParser
import io.element.android.libraries.mediaviewer.test.util.FileExtensionExtractorWithoutValidation import io.element.android.libraries.mediaviewer.test.util.FileExtensionExtractorWithoutValidation
@ -78,7 +77,7 @@ internal fun TestScope.aTimelineItemsFactory(
stateFactory = TimelineItemContentStateFactory(timelineEventFormatter), stateFactory = TimelineItemContentStateFactory(timelineEventFormatter),
failedToParseMessageFactory = TimelineItemContentFailedToParseMessageFactory(), failedToParseMessageFactory = TimelineItemContentFailedToParseMessageFactory(),
failedToParseStateFactory = TimelineItemContentFailedToParseStateFactory(), failedToParseStateFactory = TimelineItemContentFailedToParseStateFactory(),
currentSessionIdHolder = CurrentSessionIdHolder(matrixClient), sessionId = matrixClient.sessionId,
), ),
matrixClient = matrixClient, matrixClient = matrixClient,
dateFormatter = FakeDateFormatter(), dateFormatter = FakeDateFormatter(),

View file

@ -32,7 +32,7 @@ class SignedOutNode(
) : NodeInputs ) : NodeInputs
private val inputs: Inputs = inputs() private val inputs: Inputs = inputs()
private val presenter = presenterFactory.create(inputs.sessionId.value) private val presenter = presenterFactory.create(inputs.sessionId)
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {

View file

@ -9,7 +9,6 @@ package io.element.android.features.signedout.impl
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
@ -18,35 +17,35 @@ import dev.zacsweers.metro.AssistedFactory
import dev.zacsweers.metro.AssistedInject import dev.zacsweers.metro.AssistedInject
import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.core.meta.BuildMeta
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.sessionstorage.api.SessionStore import io.element.android.libraries.sessionstorage.api.SessionStore
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@AssistedInject @AssistedInject
class SignedOutPresenter( class SignedOutPresenter(
// Cannot inject SessionId @Assisted private val sessionId: SessionId,
@Assisted private val sessionId: String,
private val sessionStore: SessionStore, private val sessionStore: SessionStore,
private val buildMeta: BuildMeta, private val buildMeta: BuildMeta,
) : Presenter<SignedOutState> { ) : Presenter<SignedOutState> {
@AssistedFactory @AssistedFactory
fun interface Factory { fun interface Factory {
fun create(sessionId: String): SignedOutPresenter fun create(sessionId: SessionId): SignedOutPresenter
} }
@Composable @Composable
override fun present(): SignedOutState { override fun present(): SignedOutState {
val sessions by remember {
sessionStore.sessionsFlow()
}.collectAsState(initial = emptyList())
val signedOutSession by remember { val signedOutSession by remember {
derivedStateOf { sessions.firstOrNull { it.userId == sessionId } } sessionStore.sessionsFlow().map { sessions ->
} sessions.firstOrNull { it.userId == sessionId.value }
}
}.collectAsState(initial = null)
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
fun handleEvents(event: SignedOutEvents) { fun handleEvents(event: SignedOutEvents) {
when (event) { when (event) {
SignedOutEvents.SignInAgain -> coroutineScope.launch { SignedOutEvents.SignInAgain -> coroutineScope.launch {
sessionStore.removeSession(sessionId) sessionStore.removeSession(sessionId.value)
} }
} }
} }

View file

@ -28,7 +28,7 @@ class DefaultSignedOutEntryPointTest {
buildContext = buildContext, buildContext = buildContext,
plugins = plugins, plugins = plugins,
presenterFactory = { sessionId -> presenterFactory = { sessionId ->
assertThat(sessionId).isEqualTo(A_SESSION_ID.value) assertThat(sessionId).isEqualTo(A_SESSION_ID)
createSignedOutPresenter() createSignedOutPresenter()
} }
) )

View file

@ -70,7 +70,7 @@ internal fun createSignedOutPresenter(
sessionStore: SessionStore = InMemorySessionStore(), sessionStore: SessionStore = InMemorySessionStore(),
): SignedOutPresenter { ): SignedOutPresenter {
return SignedOutPresenter( return SignedOutPresenter(
sessionId = sessionId.value, sessionId = sessionId,
sessionStore = sessionStore, sessionStore = sessionStore,
buildMeta = aBuildMeta(applicationName = AN_APPLICATION_NAME), buildMeta = aBuildMeta(applicationName = AN_APPLICATION_NAME),
) )

View file

@ -33,8 +33,8 @@ import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.user.CurrentSessionIdHolder
import io.element.android.libraries.matrix.api.verification.VerificationRequest import io.element.android.libraries.matrix.api.verification.VerificationRequest
import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
@ -45,7 +45,7 @@ class UserProfileFlowNode(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
private val elementCallEntryPoint: ElementCallEntryPoint, private val elementCallEntryPoint: ElementCallEntryPoint,
private val sessionIdHolder: CurrentSessionIdHolder, private val sessionId: SessionId,
private val mediaViewerEntryPoint: MediaViewerEntryPoint, private val mediaViewerEntryPoint: MediaViewerEntryPoint,
private val outgoingVerificationEntryPoint: OutgoingVerificationEntryPoint, private val outgoingVerificationEntryPoint: OutgoingVerificationEntryPoint,
) : BaseFlowNode<UserProfileFlowNode.NavTarget>( ) : BaseFlowNode<UserProfileFlowNode.NavTarget>(
@ -82,7 +82,7 @@ class UserProfileFlowNode(
} }
override fun onStartCall(dmRoomId: RoomId) { override fun onStartCall(dmRoomId: RoomId) {
elementCallEntryPoint.startCall(CallType.RoomCall(sessionId = sessionIdHolder.current, roomId = dmRoomId)) elementCallEntryPoint.startCall(CallType.RoomCall(sessionId = sessionId, roomId = dmRoomId))
} }
override fun onVerifyUser(userId: UserId) { override fun onVerifyUser(userId: UserId) {
@ -99,7 +99,7 @@ class UserProfileFlowNode(
} }
override fun onViewInTimeline(eventId: EventId) { override fun onViewInTimeline(eventId: EventId) {
// Cannot happen // Cannot happen
} }
} }
mediaViewerEntryPoint.nodeBuilder(this, buildContext) mediaViewerEntryPoint.nodeBuilder(this, buildContext)

View file

@ -19,9 +19,8 @@ import io.element.android.features.verifysession.api.OutgoingVerificationEntryPo
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.user.CurrentSessionIdHolder import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.matrix.test.A_USER_ID import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint
import io.element.android.tests.testutils.lambda.lambdaError import io.element.android.tests.testutils.lambda.lambdaError
import io.element.android.tests.testutils.node.TestParentNode import io.element.android.tests.testutils.node.TestParentNode
@ -43,7 +42,7 @@ class DefaultUserProfileEntryPointTest {
UserProfileFlowNode( UserProfileFlowNode(
buildContext = buildContext, buildContext = buildContext,
plugins = plugins, plugins = plugins,
sessionIdHolder = CurrentSessionIdHolder(FakeMatrixClient()), sessionId = A_SESSION_ID,
elementCallEntryPoint = object : ElementCallEntryPoint { elementCallEntryPoint = object : ElementCallEntryPoint {
override fun startCall(callType: CallType) = lambdaError() override fun startCall(callType: CallType) = lambdaError()
override suspend fun handleIncomingCall( override suspend fun handleIncomingCall(

View file

@ -1,19 +0,0 @@
/*
* Copyright 2023, 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.api.user
import dev.zacsweers.metro.Inject
import dev.zacsweers.metro.SingleIn
import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.matrix.api.MatrixClient
@SingleIn(SessionScope::class)
@Inject
class CurrentSessionIdHolder(matrixClient: MatrixClient) {
val current = matrixClient.sessionId
}

View file

@ -13,6 +13,7 @@ import dev.zacsweers.metro.Provides
import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.di.annotations.SessionCoroutineScope
import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.encryption.EncryptionService import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.media.MatrixMediaLoader import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
import io.element.android.libraries.matrix.api.media.MediaPreviewService import io.element.android.libraries.matrix.api.media.MediaPreviewService
@ -27,6 +28,11 @@ import kotlinx.coroutines.CoroutineScope
@BindingContainer @BindingContainer
@ContributesTo(SessionScope::class) @ContributesTo(SessionScope::class)
object SessionMatrixModule { object SessionMatrixModule {
@Provides
fun providesSessionId(matrixClient: MatrixClient): SessionId {
return matrixClient.sessionId
}
@Provides @Provides
fun providesSessionVerificationService(matrixClient: MatrixClient): SessionVerificationService { fun providesSessionVerificationService(matrixClient: MatrixClient): SessionVerificationService {
return matrixClient.sessionVerificationService() return matrixClient.sessionVerificationService()

View file

@ -12,7 +12,7 @@ import dev.zacsweers.metro.ContributesTo
import dev.zacsweers.metro.Provides import dev.zacsweers.metro.Provides
import io.element.android.libraries.di.SessionScope import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.di.annotations.SessionCoroutineScope
import io.element.android.libraries.matrix.api.user.CurrentSessionIdHolder import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.preferences.api.store.SessionPreferencesStore import io.element.android.libraries.preferences.api.store.SessionPreferencesStore
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -22,10 +22,10 @@ object SessionPreferencesModule {
@Provides @Provides
fun providesSessionPreferencesStore( fun providesSessionPreferencesStore(
defaultSessionPreferencesStoreFactory: DefaultSessionPreferencesStoreFactory, defaultSessionPreferencesStoreFactory: DefaultSessionPreferencesStoreFactory,
currentSessionIdHolder: CurrentSessionIdHolder, sessionId: SessionId,
@SessionCoroutineScope sessionCoroutineScope: CoroutineScope, @SessionCoroutineScope sessionCoroutineScope: CoroutineScope,
): SessionPreferencesStore { ): SessionPreferencesStore {
return defaultSessionPreferencesStoreFactory return defaultSessionPreferencesStoreFactory
.get(currentSessionIdHolder.current, sessionCoroutineScope) .get(sessionId, sessionCoroutineScope)
} }
} }