feature (room upgrade) : manage navigation and clean code.

This commit is contained in:
ganfra
2025-06-11 13:32:12 +02:00
parent 94e678a905
commit e8bc54cf9e
13 changed files with 69 additions and 54 deletions
@@ -9,6 +9,7 @@ package io.element.android.features.messages.impl
import io.element.android.features.messages.impl.attachments.Attachment import io.element.android.features.messages.impl.attachments.Attachment
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.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
@@ -19,4 +20,5 @@ interface MessagesNavigator {
fun onReportContentClick(eventId: EventId, senderId: UserId) fun onReportContentClick(eventId: EventId, senderId: UserId)
fun onEditPollClick(eventId: EventId) fun onEditPollClick(eventId: EventId)
fun onPreviewAttachment(attachments: ImmutableList<Attachment>) fun onPreviewAttachment(attachments: ImmutableList<Attachment>)
fun onNavigateToRoom(roomId: RoomId)
} }
@@ -49,6 +49,7 @@ import io.element.android.libraries.architecture.NodeInputs
import io.element.android.libraries.architecture.inputs import io.element.android.libraries.architecture.inputs
import io.element.android.libraries.core.bool.orFalse import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.designsystem.utils.OnLifecycleEvent import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.di.RoomScope import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.di.annotations.SessionCoroutineScope import io.element.android.libraries.di.annotations.SessionCoroutineScope
import io.element.android.libraries.matrix.api.analytics.toAnalyticsViewRoom import io.element.android.libraries.matrix.api.analytics.toAnalyticsViewRoom
@@ -71,6 +72,7 @@ import kotlinx.coroutines.launch
class MessagesNode @AssistedInject constructor( class MessagesNode @AssistedInject constructor(
@Assisted buildContext: BuildContext, @Assisted buildContext: BuildContext,
@Assisted plugins: List<Plugin>, @Assisted plugins: List<Plugin>,
@ApplicationContext private val context: Context,
@SessionCoroutineScope @SessionCoroutineScope
private val sessionCoroutineScope: CoroutineScope, private val sessionCoroutineScope: CoroutineScope,
private val room: BaseRoom, private val room: BaseRoom,
@@ -144,15 +146,6 @@ class MessagesNode @AssistedInject constructor(
callbacks.forEach { it.onUserDataClick(userId) } callbacks.forEach { it.onUserDataClick(userId) }
} }
private fun onRoomDataClick(
activity: Activity,
eventSink: (TimelineEvents) -> Unit,
roomId: RoomId
) {
val roomLink = PermalinkData.RoomLink(roomId.toRoomIdOrAlias())
handleRoomLinkClick(activity, roomLink, eventSink)
}
private fun onLinkClick( private fun onLinkClick(
activity: Activity, activity: Activity,
darkTheme: Boolean, darkTheme: Boolean,
@@ -167,7 +160,7 @@ class MessagesNode @AssistedInject constructor(
callbacks.forEach { it.onUserDataClick(permalink.userId) } callbacks.forEach { it.onUserDataClick(permalink.userId) }
} }
is PermalinkData.RoomLink -> { is PermalinkData.RoomLink -> {
handleRoomLinkClick(activity, permalink, eventSink) handleRoomLinkClick(permalink, eventSink)
} }
is PermalinkData.FallbackLink -> { is PermalinkData.FallbackLink -> {
if (customTab) { if (customTab) {
@@ -183,7 +176,6 @@ class MessagesNode @AssistedInject constructor(
} }
private fun handleRoomLinkClick( private fun handleRoomLinkClick(
context: Context,
roomLink: PermalinkData.RoomLink, roomLink: PermalinkData.RoomLink,
eventSink: (TimelineEvents) -> Unit, eventSink: (TimelineEvents) -> Unit,
) { ) {
@@ -193,7 +185,7 @@ class MessagesNode @AssistedInject constructor(
eventSink(TimelineEvents.FocusOnEvent(eventId)) eventSink(TimelineEvents.FocusOnEvent(eventId))
} else { } else {
// Click on the same room, ignore // Click on the same room, ignore
context.toast("Already viewing this room!") context.sameRoomToast()
} }
} else { } else {
callbacks.forEach { it.onPermalinkClick(roomLink) } callbacks.forEach { it.onPermalinkClick(roomLink) }
@@ -220,6 +212,15 @@ class MessagesNode @AssistedInject constructor(
callbacks.forEach { it.onPreviewAttachments(attachments) } callbacks.forEach { it.onPreviewAttachments(attachments) }
} }
override fun onNavigateToRoom(roomId: RoomId) {
if (roomId == room.roomId) {
context.sameRoomToast()
} else {
val permalinkData = PermalinkData.RoomLink(roomId.toRoomIdOrAlias())
callbacks.forEach { it.onPermalinkClick(permalinkData) }
}
}
private fun onViewAllPinnedMessagesClick() { private fun onViewAllPinnedMessagesClick() {
callbacks.forEach { it.onViewAllPinnedEvents() } callbacks.forEach { it.onViewAllPinnedEvents() }
} }
@@ -240,6 +241,10 @@ class MessagesNode @AssistedInject constructor(
callbacks.forEach { it.onViewKnockRequests() } callbacks.forEach { it.onViewKnockRequests() }
} }
private fun Context.sameRoomToast() {
context.toast("Already viewing this room!")
}
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
val activity = requireNotNull(LocalActivity.current) val activity = requireNotNull(LocalActivity.current)
@@ -260,19 +265,18 @@ class MessagesNode @AssistedInject constructor(
onRoomDetailsClick = this::onRoomDetailsClick, onRoomDetailsClick = this::onRoomDetailsClick,
onEventContentClick = this::onEventClick, onEventContentClick = this::onEventClick,
onUserDataClick = this::onUserDataClick, onUserDataClick = this::onUserDataClick,
onRoomDataClick = {roomId -> onRoomDataClick(activity, state.timelineState.eventSink, roomId) },
onLinkClick = { url, customTab -> onLinkClick(activity, isDark, url, state.timelineState.eventSink, customTab) }, onLinkClick = { url, customTab -> onLinkClick(activity, isDark, url, state.timelineState.eventSink, customTab) },
onSendLocationClick = this::onSendLocationClick, onSendLocationClick = this::onSendLocationClick,
onCreatePollClick = this::onCreatePollClick, onCreatePollClick = this::onCreatePollClick,
onJoinCallClick = this::onJoinCallClick, onJoinCallClick = this::onJoinCallClick,
onViewAllPinnedMessagesClick = this::onViewAllPinnedMessagesClick, onViewAllPinnedMessagesClick = this::onViewAllPinnedMessagesClick,
modifier = modifier,
knockRequestsBannerView = { knockRequestsBannerView = {
knockRequestsBannerRenderer.View( knockRequestsBannerRenderer.View(
modifier = Modifier, modifier = Modifier,
onViewRequestsClick = this::onViewKnockRequestsClick onViewRequestsClick = this::onViewKnockRequestsClick
) )
}, },
modifier = modifier,
) )
roomMemberModerationRenderer.Render( roomMemberModerationRenderer.Render(
state = state.roomMemberModerationState, state = state.roomMemberModerationState,
@@ -123,7 +123,6 @@ fun MessagesView(
onRoomDetailsClick: () -> Unit, onRoomDetailsClick: () -> Unit,
onEventContentClick: (isLive: Boolean, event: TimelineItem.Event) -> Boolean, onEventContentClick: (isLive: Boolean, event: TimelineItem.Event) -> Boolean,
onUserDataClick: (UserId) -> Unit, onUserDataClick: (UserId) -> Unit,
onRoomDataClick: (RoomId) -> Unit,
onLinkClick: (String, Boolean) -> Unit, onLinkClick: (String, Boolean) -> Unit,
onSendLocationClick: () -> Unit, onSendLocationClick: () -> Unit,
onCreatePollClick: () -> Unit, onCreatePollClick: () -> Unit,
@@ -214,7 +213,6 @@ fun MessagesView(
.consumeWindowInsets(padding), .consumeWindowInsets(padding),
onContentClick = ::onContentClick, onContentClick = ::onContentClick,
onMessageLongClick = ::onMessageLongClick, onMessageLongClick = ::onMessageLongClick,
onRoomSuccessorClicked = onRoomDataClick,
onUserDataClick = { onUserDataClick = {
hidingKeyboard { hidingKeyboard {
state.eventSink(MessagesEvents.OnUserClicked(it)) state.eventSink(MessagesEvents.OnUserClicked(it))
@@ -305,7 +303,6 @@ private fun MessagesViewContent(
state: MessagesState, state: MessagesState,
onContentClick: (TimelineItem.Event) -> Unit, onContentClick: (TimelineItem.Event) -> Unit,
onUserDataClick: (MatrixUser) -> Unit, onUserDataClick: (MatrixUser) -> Unit,
onRoomSuccessorClicked: (RoomId) -> Unit,
onLinkClick: (Link, Boolean) -> Unit, onLinkClick: (Link, Boolean) -> Unit,
onReactionClick: (key: String, TimelineItem.Event) -> Unit, onReactionClick: (key: String, TimelineItem.Event) -> Unit,
onReactionLongClick: (key: String, TimelineItem.Event) -> Unit, onReactionLongClick: (key: String, TimelineItem.Event) -> Unit,
@@ -417,7 +414,9 @@ private fun MessagesViewContent(
MessagesViewComposerBottomSheetContents( MessagesViewComposerBottomSheetContents(
subcomposing = subcomposing, subcomposing = subcomposing,
state = state, state = state,
onRoomSuccessorClicked = onRoomSuccessorClicked, onRoomSuccessorClick = { roomId ->
state.timelineState.eventSink(TimelineEvents.NavigateToRoom(roomId = roomId))
},
onLinkClick = { url, customTab -> onLinkClick(Link(url), customTab) }, onLinkClick = { url, customTab -> onLinkClick(Link(url), customTab) },
) )
}, },
@@ -432,12 +431,12 @@ private fun MessagesViewContent(
private fun MessagesViewComposerBottomSheetContents( private fun MessagesViewComposerBottomSheetContents(
subcomposing: Boolean, subcomposing: Boolean,
state: MessagesState, state: MessagesState,
onRoomSuccessorClicked: (RoomId) -> Unit, onRoomSuccessorClick: (RoomId) -> Unit,
onLinkClick: (String, Boolean) -> Unit, onLinkClick: (String, Boolean) -> Unit,
) { ) {
when { when {
state.successorRoom != null -> { state.successorRoom != null -> {
SuccessorRoomBanner(roomSuccessor = state.successorRoom, onRoomSuccessorClicked = onRoomSuccessorClicked) SuccessorRoomBanner(roomSuccessor = state.successorRoom, onRoomSuccessorClick = onRoomSuccessorClick)
} }
state.userEventPermissions.canSendMessage -> { state.userEventPermissions.canSendMessage -> {
Column(modifier = Modifier.fillMaxWidth()) { Column(modifier = Modifier.fillMaxWidth()) {
@@ -605,17 +604,17 @@ private fun CantSendMessageBanner() {
@Composable @Composable
private fun SuccessorRoomBanner( private fun SuccessorRoomBanner(
modifier: Modifier = Modifier,
roomSuccessor: SuccessorRoom, roomSuccessor: SuccessorRoom,
onRoomSuccessorClicked: (RoomId) -> Unit onRoomSuccessorClick: (RoomId) -> Unit,
modifier: Modifier = Modifier,
) { ) {
ComposerAlertMolecule( ComposerAlertMolecule(
avatar = null, avatar = null,
content = "This room has been replaced and is no longer active".toAnnotatedString(), content = stringResource(R.string.screen_room_timeline_tombstoned_room_message).toAnnotatedString(),
onSubmitClick = { onRoomSuccessorClicked(roomSuccessor.roomId)}, onSubmitClick = { onRoomSuccessorClick(roomSuccessor.roomId) },
modifier = modifier, modifier = modifier,
isCritical = false, isCritical = false,
submitText = "Jump to new room" submitText = stringResource(R.string.screen_room_timeline_tombstoned_room_action)
) )
} }
@@ -628,7 +627,6 @@ internal fun MessagesViewPreview(@PreviewParameter(MessagesStateProvider::class)
onRoomDetailsClick = {}, onRoomDetailsClick = {},
onEventContentClick = { _, _ -> false }, onEventContentClick = { _, _ -> false },
onUserDataClick = {}, onUserDataClick = {},
onRoomDataClick = { },
onLinkClick = { _, _ -> }, onLinkClick = { _, _ -> },
onSendLocationClick = {}, onSendLocationClick = {},
onCreatePollClick = {}, onCreatePollClick = {},
@@ -40,7 +40,6 @@ internal fun MessagesViewWithIdentityChangePreview(
onCreatePollClick = {}, onCreatePollClick = {},
onJoinCallClick = {}, onJoinCallClick = {},
onViewAllPinnedMessagesClick = {}, onViewAllPinnedMessagesClick = {},
onRoomDataClick = {},
knockRequestsBannerView = {} knockRequestsBannerView = {}
) )
} }
@@ -9,6 +9,7 @@ package io.element.android.features.messages.impl.timeline
import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.TimelineItem
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.timeline.Timeline import io.element.android.libraries.matrix.api.timeline.Timeline
import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield
import kotlin.time.Duration import kotlin.time.Duration
@@ -30,6 +31,7 @@ sealed interface TimelineEvents {
data class ComputeVerifiedUserSendFailure(val event: TimelineItem.Event) : EventFromTimelineItem data class ComputeVerifiedUserSendFailure(val event: TimelineItem.Event) : EventFromTimelineItem
data class ShowShieldDialog(val messageShield: MessageShield) : EventFromTimelineItem data class ShowShieldDialog(val messageShield: MessageShield) : EventFromTimelineItem
data class LoadMore(val direction: Timeline.PaginationDirection) : EventFromTimelineItem data class LoadMore(val direction: Timeline.PaginationDirection) : EventFromTimelineItem
data class NavigateToRoom(val roomId: RoomId) : EventFromTimelineItem
/** /**
* Events coming from a poll item. * Events coming from a poll item.
@@ -178,6 +178,9 @@ class TimelinePresenter @AssistedInject constructor(
is TimelineEvents.ComputeVerifiedUserSendFailure -> { is TimelineEvents.ComputeVerifiedUserSendFailure -> {
resolveVerifiedUserSendFailureState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(event.event)) resolveVerifiedUserSendFailureState.eventSink(ResolveVerifiedUserSendFailureEvents.ComputeForMessage(event.event))
} }
is TimelineEvents.NavigateToRoom -> {
navigator.onNavigateToRoom(event.roomId)
}
} }
} }
@@ -41,7 +41,15 @@ fun TimelineItemVirtualRow(
when (virtual.model) { when (virtual.model) {
is TimelineItemDaySeparatorModel -> TimelineItemDaySeparatorView(virtual.model) is TimelineItemDaySeparatorModel -> TimelineItemDaySeparatorView(virtual.model)
TimelineItemReadMarkerModel -> TimelineItemReadMarkerView() TimelineItemReadMarkerModel -> TimelineItemReadMarkerView()
TimelineItemRoomBeginningModel -> TimelineItemRoomBeginningView(predecessorRoom = timelineRoomInfo.predecessorRoom, roomName = timelineRoomInfo.name) TimelineItemRoomBeginningModel -> {
TimelineItemRoomBeginningView(
predecessorRoom = timelineRoomInfo.predecessorRoom,
roomName = timelineRoomInfo.name,
onPredecessorRoomClick = { roomId ->
eventSink(TimelineEvents.NavigateToRoom(roomId))
},
)
}
is TimelineItemLoadingIndicatorModel -> { is TimelineItemLoadingIndicatorModel -> {
TimelineLoadingMoreIndicator(virtual.model.direction) TimelineLoadingMoreIndicator(virtual.model.direction)
val latestEventSink by rememberUpdatedState(eventSink) val latestEventSink by rememberUpdatedState(eventSink)
@@ -31,8 +31,9 @@ import io.element.android.libraries.matrix.api.room.tombstone.PredecessorRoom
@Composable @Composable
fun TimelineItemRoomBeginningView( fun TimelineItemRoomBeginningView(
predecessorRoom: PredecessorRoom?,
roomName: String?, roomName: String?,
predecessorRoom: PredecessorRoom?,
onPredecessorRoomClick: (RoomId) -> Unit,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
Column( Column(
@@ -41,11 +42,10 @@ fun TimelineItemRoomBeginningView(
if (predecessorRoom != null) { if (predecessorRoom != null) {
ComposerAlertMolecule( ComposerAlertMolecule(
avatar = null, avatar = null,
content = "This room is a continuation of another room".toAnnotatedString(), content = stringResource(R.string.screen_room_timeline_upgraded_room_message).toAnnotatedString(),
onSubmitClick = { }, onSubmitClick = { onPredecessorRoomClick(predecessorRoom.roomId) },
modifier = modifier,
isCritical = false, isCritical = false,
submitText = "See old messages" submitText = stringResource(R.string.screen_room_timeline_upgraded_room_action)
) )
} }
@@ -70,7 +70,6 @@ fun TimelineItemRoomBeginningView(
} }
} }
@PreviewsDayNight @PreviewsDayNight
@Composable @Composable
internal fun TimelineItemRoomBeginningViewPreview() = ElementPreview { internal fun TimelineItemRoomBeginningViewPreview() = ElementPreview {
@@ -78,14 +77,17 @@ internal fun TimelineItemRoomBeginningViewPreview() = ElementPreview {
TimelineItemRoomBeginningView( TimelineItemRoomBeginningView(
predecessorRoom = null, predecessorRoom = null,
roomName = null, roomName = null,
onPredecessorRoomClick = {},
) )
TimelineItemRoomBeginningView( TimelineItemRoomBeginningView(
predecessorRoom = null, predecessorRoom = null,
roomName = "Room Name", roomName = "Room Name",
onPredecessorRoomClick = {},
) )
TimelineItemRoomBeginningView( TimelineItemRoomBeginningView(
predecessorRoom = PredecessorRoom(RoomId("!roomId:matrix.org"), EventId("\$eventId:matrix.org")), predecessorRoom = PredecessorRoom(RoomId("!roomId:matrix.org"), EventId("\$eventId:matrix.org")),
roomName = "Room Name", roomName = "Room Name",
onPredecessorRoomClick = {},
) )
} }
} }
@@ -26,8 +26,6 @@ import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme import io.element.android.compound.theme.ElementTheme
import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.components.avatar.anAvatarData
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.text.toAnnotatedString import io.element.android.libraries.designsystem.text.toAnnotatedString
@@ -237,6 +237,7 @@ interface BaseRoom : Closeable {
* @param reason - The reason the room is being reported. * @param reason - The reason the room is being reported.
*/ */
suspend fun reportRoom(reason: String?): Result<Unit> suspend fun reportRoom(reason: String?): Result<Unit>
/** /**
* Destroy the room and release all resources associated to it. * Destroy the room and release all resources associated to it.
*/ */
@@ -14,7 +14,6 @@ import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.CurrentUserMembership import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.RoomInfo
import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.impl.room.history.map import io.element.android.libraries.matrix.impl.room.history.map
import io.element.android.libraries.matrix.impl.room.join.map import io.element.android.libraries.matrix.impl.room.join.map
@@ -29,7 +28,6 @@ import uniffi.matrix_sdk_base.EncryptionState
import org.matrix.rustcomponents.sdk.Membership as RustMembership import org.matrix.rustcomponents.sdk.Membership as RustMembership
import org.matrix.rustcomponents.sdk.RoomInfo as RustRoomInfo import org.matrix.rustcomponents.sdk.RoomInfo as RustRoomInfo
import org.matrix.rustcomponents.sdk.RoomNotificationMode as RustRoomNotificationMode import org.matrix.rustcomponents.sdk.RoomNotificationMode as RustRoomNotificationMode
import org.matrix.rustcomponents.sdk.SuccessorRoom as RustSuccessorRoom
class RoomInfoMapper { class RoomInfoMapper {
fun map(rustRoomInfo: RustRoomInfo): RoomInfo = rustRoomInfo.let { fun map(rustRoomInfo: RustRoomInfo): RoomInfo = rustRoomInfo.let {
@@ -15,9 +15,9 @@ import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.RoomInfo
import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom
import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility
import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.test.AN_AVATAR_URL import io.element.android.libraries.matrix.test.AN_AVATAR_URL
import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_ID
@@ -15,10 +15,10 @@ import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.RoomInfo import io.element.android.libraries.matrix.api.room.RoomInfo
import io.element.android.libraries.matrix.api.room.RoomMember import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomNotificationMode import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom
import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility
import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.room.message.RoomMessage import io.element.android.libraries.matrix.api.room.message.RoomMessage
import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom
import io.element.android.libraries.matrix.api.roomlist.RoomSummary import io.element.android.libraries.matrix.api.roomlist.RoomSummary
import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser